view gen/llvmhelpers.h @ 1117:4c20fcc4252b

Fun with parameter attributes: For several of the "synthetic" parameters added to D functions, we can apply noalias and nocapture. They are sret parameters, 'nest' pointers passed to nested functions, and _argptr: Nocapture: - Sret and nest are nocapture because they don't represent D-level variables, and thus the callee can't (validly) obtain a pointer to them, let alone keep it around after it returns. - _argptr is nocapture because although the callee has access to it as a pointer, that pointer is invalidated when it returns. All three are noalias because they're function-local variables - Sret and _argptr are noalias because they're freshly alloca'd memory only used for a single function call that's not allowed to keep an aliasing pointer to it around (since the parameter is nocapture). - 'Nest' is noalias because the callee only ever has access to one such pointer per parent function, and every parent function has a different one. This commit also ensures attributes set on sret, _arguments and _argptr are propagated to calls to such functions. It also adds one exception to the general rule that attributes on function types should propagate to calls: the type of a delegate's function pointer has a 'nest' parameter, but this can either be a true 'nest' (for delegates to nested functions) or a 'this' (for delegates to member functions). Since 'this' is neither noalias nor nocapture, and there's generally no way to tell which one it is, we remove these attributes at the call site if the callee is a delegate.
author Frits van Bommel <fvbommel wxs.nl>
date Sat, 14 Mar 2009 22:15:31 +0100
parents 7ce8355fbcc6
children f99a3b393c03
line wrap: on
line source

#ifndef LDC_GEN_LLVMHELPERS_H
#define LDC_GEN_LLVMHELPERS_H

#include "gen/llvm.h"
#include "statement.h"

// dynamic memory helpers
LLValue* DtoNew(Type* newtype);
void DtoDeleteMemory(LLValue* ptr);
void DtoDeleteClass(LLValue* inst);
void DtoDeleteInterface(LLValue* inst);
void DtoDeleteArray(DValue* arr);

// emit an alloca
llvm::AllocaInst* DtoAlloca(const LLType* lltype, const std::string& name = "");
llvm::AllocaInst* DtoAlloca(const LLType* lltype, LLValue* arraysize, const std::string& name = "");

// assertion generator
void DtoAssert(Module* M, Loc* loc, DValue* msg);

// return the LabelStatement from the current function with the given identifier or NULL if not found
LabelStatement* DtoLabelStatement(Identifier* ident);
// emit goto
void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosingtryfinally, TryFinallyStatement* sourcetf);

// generates IR for finally blocks between the 'start' and 'end' statements
// will begin with the finally block belonging to 'start' and does not include
// the finally block of 'end'
void DtoEnclosingHandlers(EnclosingHandler* start, EnclosingHandler* end);

// enters a critical section
void DtoEnterCritical(LLValue* g);
// leaves a critical section
void DtoLeaveCritical(LLValue* g);

// enters a monitor lock
void DtoEnterMonitor(LLValue* v);
// leaves a monitor lock
void DtoLeaveMonitor(LLValue* v);

// nested variable and context helpers

// gets the context value for a call to a nested function or newing a class, with arbitrary nesting
LLValue* DtoNestedContext(Loc loc, Dsymbol* sym);
// gets the dvalue of a nested variable with arbitrary nesting
DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd);

// basic operations
void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs);

// create a null dvalue
DValue* DtoNullValue(Type* t);

// casts
DValue* DtoCastInt(Loc& loc, DValue* val, Type* to);
DValue* DtoCastPtr(Loc& loc, DValue* val, Type* to);
DValue* DtoCastFloat(Loc& loc, DValue* val, Type* to);
DValue* DtoCastDelegate(Loc& loc, DValue* val, Type* to);
DValue* DtoCast(Loc& loc, DValue* val, Type* to);

// return the same val as passed in, modified to the target type, if possible, otherwise returns a new DValue
DValue* DtoPaintType(Loc& loc, DValue* val, Type* to);

// is template instance check, returns module where instantiated
TemplateInstance* DtoIsTemplateInstance(Dsymbol* s);

// these are all basically drivers for the codegeneration called by the main loop
void DtoResolveDsymbol(Dsymbol* dsym);
void DtoDeclareDsymbol(Dsymbol* dsym);
void DtoDefineDsymbol(Dsymbol* dsym);
void DtoConstInitDsymbol(Dsymbol* dsym);
void DtoConstInitGlobal(VarDeclaration* vd);
void DtoEmptyResolveList();
void DtoEmptyDeclareList();
void DtoEmptyConstInitList();
void DtoEmptyAllLists();
void DtoForceDeclareDsymbol(Dsymbol* dsym);
void DtoForceConstInitDsymbol(Dsymbol* dsym);
void DtoForceDefineDsymbol(Dsymbol* dsym);

// declaration inside a declarationexp
DValue* DtoDeclarationExp(Dsymbol* declaration);
LLValue* DtoRawVarDeclaration(VarDeclaration* var);

// initializer helpers
LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init);
LLConstant* DtoConstExpInit(Loc loc, Type* t, Expression* exp);
DValue* DtoInitializer(LLValue* target, Initializer* init);

// annotation generator
void DtoAnnotation(const char* str);

// getting typeinfo of type, base=true casts to object.TypeInfo
LLConstant* DtoTypeInfoOf(Type* ty, bool base=true);

// binary operations
DValue* DtoBinAdd(DValue* lhs, DValue* rhs);
DValue* DtoBinSub(DValue* lhs, DValue* rhs);
// these binops need an explicit result type to handling
// to give 'ifloat op float' and 'float op ifloat' the correct type
DValue* DtoBinMul(Type* resulttype, DValue* lhs, DValue* rhs);
DValue* DtoBinDiv(Type* resulttype, DValue* lhs, DValue* rhs);
DValue* DtoBinRem(Type* resulttype, DValue* lhs, DValue* rhs);

// target stuff
void findDefaultTarget();

// fixup an overloaded intrinsic name string
void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name);

// return true if the symbol should be defined in the current module, not just declared
bool mustDefineSymbol(Dsymbol* s);

// returns true if the symbol needs template linkage, or just external
bool needsTemplateLinkage(Dsymbol* s);

// returns true if there is any unaligned type inside the aggregate
bool hasUnalignedFields(Type* t);

////////////////////////////////////////////
// gen/tocall.cpp stuff below
////////////////////////////////////////////

/// convert DMD calling conv to LLVM
unsigned DtoCallingConv(Loc loc, LINK l);

///
TypeFunction* DtoTypeFunction(DValue* fnval);

///
DValue* DtoVaArg(Loc& loc, Type* type, Expression* valistArg);

///
LLValue* DtoCallableValue(DValue* fn);

///
const LLFunctionType* DtoExtractFunctionType(const LLType* type);

///
void DtoBuildDVarArgList(std::vector<LLValue*>& args, llvm::AttrListPtr& palist, TypeFunction* tf, Expressions* arguments, size_t argidx);

///
DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* arguments);

#endif