diff --git a/dmd2/aggregate.h b/dmd2/aggregate.h index 518cae13..603d9774 100644 --- a/dmd2/aggregate.h +++ b/dmd2/aggregate.h @@ -209,7 +209,7 @@ struct StructDeclaration : AggregateDeclaration StructDeclaration *isStructDeclaration() { return this; } #if IN_LLVM - void codegen(Ir*); + void codegen(IRState*); #endif }; @@ -337,7 +337,7 @@ struct ClassDeclaration : AggregateDeclaration ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } #if IN_LLVM - virtual void codegen(Ir*); + virtual void codegen(IRState*); #endif }; @@ -367,7 +367,7 @@ struct InterfaceDeclaration : ClassDeclaration InterfaceDeclaration *isInterfaceDeclaration() { return this; } #if IN_LLVM - void codegen(Ir*); + void codegen(IRState*); #endif }; diff --git a/dmd2/attrib.h b/dmd2/attrib.h index 42ca18ae..760d3ed0 100644 --- a/dmd2/attrib.h +++ b/dmd2/attrib.h @@ -63,7 +63,7 @@ struct AttribDeclaration : Dsymbol #endif #if IN_LLVM - virtual void codegen(Ir*); + void codegen(IRState*); #endif }; @@ -161,7 +161,7 @@ struct PragmaDeclaration : AttribDeclaration #endif #if IN_LLVM - void codegen(Ir*); + void codegen(IRState*); #endif }; diff --git a/dmd2/declaration.h b/dmd2/declaration.h index 66ce7ab5..ee57cdfd 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -189,11 +189,6 @@ struct Declaration : Dsymbol enum PROT prot(); Declaration *isDeclaration() { return this; } - -#if IN_LLVM - /// Codegen traversal - virtual void codegen(Ir* ir); -#endif }; /**************************************************************/ @@ -216,7 +211,7 @@ struct TupleDeclaration : Declaration #if IN_LLVM void semantic3(Scope *sc); /// Codegen traversal - void codegen(Ir* ir); + void codegen(IRState* ir); #endif }; @@ -256,7 +251,7 @@ struct TypedefDeclaration : Declaration #if IN_LLVM /// Codegen traversal - void codegen(Ir* ir); + void codegen(IRState* ir); #endif }; @@ -362,7 +357,7 @@ struct VarDeclaration : Declaration #if IN_LLVM /// Codegen traversal - virtual void codegen(Ir* ir); + void codegen(IRState* ir); /// Index into parent aggregate. /// Set during type generation. @@ -455,7 +450,7 @@ struct TypeInfoDeclaration : VarDeclaration #if IN_LLVM /// Codegen traversal - void codegen(Ir* ir); + void codegen(IRState* ir); virtual void llvmDefine(); #endif }; @@ -483,7 +478,11 @@ struct TypeInfoClassDeclaration : TypeInfoDeclaration #endif #if IN_LLVM - void codegen(Ir*); + // TypeInfoClassDeclaration instances are different; they describe + // __ClassZ/__InterfaceZ symbols instead of a TypeInfo_….init one. DMD also + // generates them for SomeInterface.classinfo access, so we can't just + // distinguish between them using tinfo and thus need to override codegen(). + void codegen(IRState* ir); void llvmDefine(); #endif }; @@ -819,7 +818,9 @@ struct FuncDeclaration : Declaration // functions FuncDeclarations siblingCallers; // Sibling nested functions which // called this one +#if IN_DMD FuncDeclarations deferred; // toObjFile() these functions after this one +#endif unsigned flags; #define FUNCFLAGpurityInprocess 1 // working on determining purity @@ -918,7 +919,7 @@ struct FuncDeclaration : Declaration IrFuncTy irFty; /// Codegen traversal - void codegen(Ir* ir); + void codegen(IRState* ir); // vars declared in this function that nested funcs reference // is this is not empty, nestedFrameRef is set and these VarDecls diff --git a/dmd2/dsymbol.h b/dmd2/dsymbol.h index 585aae33..a10a46e9 100644 --- a/dmd2/dsymbol.h +++ b/dmd2/dsymbol.h @@ -95,7 +95,7 @@ struct TYPE; #endif #if IN_LLVM -class Ir; +class IRState; namespace llvm { class Value; @@ -287,7 +287,7 @@ struct Dsymbol : Object virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; } /// Codegen traversal - virtual void codegen(Ir* ir); + virtual void codegen(IRState* p); // llvm stuff int llvmInternal; diff --git a/dmd2/enum.h b/dmd2/enum.h index b9e2255c..8efabeaa 100644 --- a/dmd2/enum.h +++ b/dmd2/enum.h @@ -76,7 +76,7 @@ struct EnumDeclaration : ScopeDsymbol #endif #if IN_LLVM - void codegen(Ir*); + void codegen(IRState*); #endif }; diff --git a/dmd2/func.c b/dmd2/func.c index 81121c65..db81f48e 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -4735,11 +4735,7 @@ void UnitTestDeclaration::semantic(Scope *sc) { sc = scope; scope = NULL; } -#if IN_LLVM - if (global.params.useUnitTests && sc->module->isRoot) -#else if (global.params.useUnitTests) -#endif { if (!type) type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); diff --git a/dmd2/irstate.c b/dmd2/irstate.c deleted file mode 100644 index fc6475c6..00000000 --- a/dmd2/irstate.c +++ /dev/null @@ -1,202 +0,0 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com - -#include - -#include "mars.h" -#include "mtype.h" -#include "declaration.h" -#include "irstate.h" -#include "statement.h" - -IRState::IRState(IRState *irs, Statement *s) -{ - prev = irs; - statement = s; - symbol = NULL; - breakBlock = NULL; - contBlock = NULL; - switchBlock = NULL; - defaultBlock = NULL; - ident = NULL; - ehidden = NULL; - startaddress = NULL; - if (irs) - { - m = irs->m; - shidden = irs->shidden; - sclosure = irs->sclosure; - sthis = irs->sthis; - blx = irs->blx; - deferToObj = irs->deferToObj; - varsInScope = irs->varsInScope; - } - else - { - m = NULL; - shidden = NULL; - sclosure = NULL; - sthis = NULL; - blx = NULL; - deferToObj = NULL; - varsInScope = NULL; - } -} - -IRState::IRState(IRState *irs, Dsymbol *s) -{ - prev = irs; - statement = NULL; - symbol = s; - breakBlock = NULL; - contBlock = NULL; - switchBlock = NULL; - defaultBlock = NULL; - ident = NULL; - ehidden = NULL; - startaddress = NULL; - if (irs) - { - m = irs->m; - shidden = irs->shidden; - sclosure = irs->sclosure; - sthis = irs->sthis; - blx = irs->blx; - deferToObj = irs->deferToObj; - varsInScope = irs->varsInScope; - } - else - { - m = NULL; - shidden = NULL; - sclosure = NULL; - sthis = NULL; - blx = NULL; - deferToObj = NULL; - varsInScope = NULL; - } -} - -IRState::IRState(Module *m, Dsymbol *s) -{ - prev = NULL; - statement = NULL; - this->m = m; - symbol = s; - breakBlock = NULL; - contBlock = NULL; - switchBlock = NULL; - defaultBlock = NULL; - ident = NULL; - ehidden = NULL; - shidden = NULL; - sclosure = NULL; - sthis = NULL; - blx = NULL; - deferToObj = NULL; - startaddress = NULL; - varsInScope = NULL; -} - -block *IRState::getBreakBlock(Identifier *ident) -{ - IRState *bc; - if (ident) { - Statement *related = NULL; - block *ret = NULL; - for (bc = this; bc; bc = bc->prev) { - // The label for a breakBlock may actually be some levels up (e.g. - // on a try/finally wrapping a loop). We'll see if this breakBlock - // is the one to return once we reach that outer statement (which - // in many cases will be this same statement). - if (bc->breakBlock) { - related = bc->statement->getRelatedLabeled(); - ret = bc->breakBlock; - } - if (bc->statement == related && bc->prev->ident == ident) - return ret; - } - } else { - for (bc = this; bc; bc = bc->prev) { - if (bc->breakBlock) - return bc->breakBlock; - } - } - return NULL; -} - -block *IRState::getContBlock(Identifier *ident) -{ - IRState *bc; - - for (bc = this; bc; bc = bc->prev) - { - if (ident) - { - if (bc->prev && bc->prev->ident == ident) - return bc->contBlock; - } - else if (bc->contBlock) - return bc->contBlock; - } - return NULL; -} - -block *IRState::getSwitchBlock() -{ - IRState *bc; - - for (bc = this; bc; bc = bc->prev) - { - if (bc->switchBlock) - return bc->switchBlock; - } - return NULL; -} - -block *IRState::getDefaultBlock() -{ - IRState *bc; - - for (bc = this; bc; bc = bc->prev) - { - if (bc->defaultBlock) - return bc->defaultBlock; - } - return NULL; -} - -FuncDeclaration *IRState::getFunc() -{ - IRState *bc; - - for (bc = this; bc->prev; bc = bc->prev) - { - } - return (FuncDeclaration *)(bc->symbol); -} - - -/********************** - * Return !=0 if do array bounds checking - */ -int IRState::arrayBoundsCheck() -{ - int result = global.params.useArrayBounds; - - if (result == 1) - { // For safe functions only - result = 0; - FuncDeclaration *fd = getFunc(); - if (fd) - { Type *t = fd->type; - if (t->ty == Tfunction && ((TypeFunction *)t)->trust == TRUSTsafe) - result = 1; - } - } - return result; -} diff --git a/dmd2/irstate.h b/dmd2/irstate.h deleted file mode 100644 index 4ee24906..00000000 --- a/dmd2/irstate.h +++ /dev/null @@ -1,64 +0,0 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com - -#ifndef DMD_CONTEXT_H -#define DMD_CONTEXT_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -struct Module; -struct Statement; -struct block; -struct Dsymbol; -struct Identifier; -struct Symbol; -struct FuncDeclaration; -struct Blockx; -#if IN_LLVM -class DValue; -typedef DValue elem; -#else -struct elem; -#endif -#include "arraytypes.h" - -struct IRState -{ - IRState *prev; - Statement *statement; - Module *m; // module - Dsymbol *symbol; - Identifier *ident; - Symbol *shidden; // hidden parameter to function - Symbol *sthis; // 'this' parameter to function (member and nested) - Symbol *sclosure; // pointer to closure instance - Blockx *blx; - Dsymbols *deferToObj; // array of Dsymbol's to run toObjFile(int multiobj) on later - elem *ehidden; // transmit hidden pointer to CallExp::toElem() - Symbol *startaddress; - VarDeclarations *varsInScope; // variables that are in scope that will need destruction later - - block *breakBlock; - block *contBlock; - block *switchBlock; - block *defaultBlock; - - IRState(IRState *irs, Statement *s); - IRState(IRState *irs, Dsymbol *s); - IRState(Module *m, Dsymbol *s); - - block *getBreakBlock(Identifier *ident); - block *getContBlock(Identifier *ident); - block *getSwitchBlock(); - block *getDefaultBlock(); - FuncDeclaration *getFunc(); - int arrayBoundsCheck(); -}; - -#endif /* DMD_CONTEXT_H */ diff --git a/dmd2/module.h b/dmd2/module.h index c2365545..7d616e61 100644 --- a/dmd2/module.h +++ b/dmd2/module.h @@ -28,7 +28,6 @@ class Library; // Back end #if IN_LLVM -class Ir; class DValue; typedef DValue elem; namespace llvm { @@ -196,7 +195,7 @@ struct Module : Package #if IN_LLVM // LDC - llvm::Module* genLLVMModule(llvm::LLVMContext& context, Ir* sir); + llvm::Module* genLLVMModule(llvm::LLVMContext& context); void buildTargetFiles(bool singleObj); File* buildFilePath(const char* forcename, const char* path, const char* ext); Module *isModule() { return this; } diff --git a/dmd2/mtype.c b/dmd2/mtype.c index 89690046..dbea4b6c 100644 --- a/dmd2/mtype.c +++ b/dmd2/mtype.c @@ -50,9 +50,6 @@ #include "aggregate.h" #include "hdrgen.h" -#if IN_LLVM -Ir* Type::sir = NULL; -#endif FuncDeclaration *hasThis(Scope *sc); @@ -197,11 +194,7 @@ char Type::needThisPrefix() return 'M'; // name mangling prefix for functions needing 'this' } -#if IN_LLVM -void Type::init(Ir* _sir) -#else void Type::init() -#endif { stringtable._init(1543); Lexer::initKeywords(); @@ -353,10 +346,6 @@ void Type::init() Tptrdiff_t = Tint32; } -#if IN_LLVM - sir = _sir; -#endif - tsize_t = basic[Tsize_t]; tptrdiff_t = basic[Tptrdiff_t]; thash_t = tsize_t; diff --git a/dmd2/mtype.h b/dmd2/mtype.h index c61b0ba1..7aa4075f 100644 --- a/dmd2/mtype.h +++ b/dmd2/mtype.h @@ -24,7 +24,6 @@ #if IN_LLVM #include "../ir/irfuncty.h" namespace llvm { class Type; } -class Ir; class IrType; #endif @@ -247,11 +246,7 @@ struct Type : Object int covariant(Type *t, StorageClass *pstc = NULL); char *toChars(); static char needThisPrefix(); -#if IN_LLVM - static void init(Ir*); -#else static void init(); -#endif #define SIZE_INVALID (~(d_uns64)0) d_uns64 size(); @@ -371,7 +366,6 @@ struct Type : Object virtual TypeBasic *isTypeBasic(); #if IN_LLVM - static Ir* sir; IrType* irtype; #endif }; diff --git a/dmd2/template.h b/dmd2/template.h index ddb2a5b5..12d0783f 100644 --- a/dmd2/template.h +++ b/dmd2/template.h @@ -356,7 +356,7 @@ struct TemplateInstance : ScopeDsymbol bool ignore; // true if the instance must be ignored when codegen'ing Module* emittedInModule; // which module this template instance has been emitted in - void codegen(Ir*); + void codegen(IRState*); #endif }; @@ -386,7 +386,7 @@ struct TemplateMixin : TemplateInstance TemplateMixin *isTemplateMixin() { return this; } #if IN_LLVM - void codegen(Ir*); + void codegen(IRState*); #endif }; diff --git a/driver/main.cpp b/driver/main.cpp index f349cc4a..ee3d8b12 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -614,9 +614,6 @@ int main(int argc, char **argv) if (global.errors) fatal(); - // create a proper target - Ir ir; - // Set up the TargetMachine. ExplicitBitness::Type bitness = ExplicitBitness::None; if ((m32bits || m64bits) && (!mArch.empty() || !mTargetTriple.empty())) @@ -669,7 +666,7 @@ int main(int argc, char **argv) } // Initialization - Type::init(&ir); + Type::init(); Id::initialize(); Module::init(); Target::init(); @@ -987,7 +984,7 @@ int main(int argc, char **argv) printf("code %s\n", m->toChars()); if (global.params.obj) { - llvm::Module* lm = m->genLLVMModule(context, &ir); + llvm::Module* lm = m->genLLVMModule(context); if (!singleObj) { m->deleteObjFile(); diff --git a/gen/arrays.cpp b/gen/arrays.cpp index db90c9a4..399509e9 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -867,14 +867,6 @@ static LLValue* DtoArrayEqCmp_impl(Loc& loc, const char* func, DValue* l, DValue if (useti) { Type* t = l->getType(); LLValue* tival = DtoTypeInfoOf(t); - // DtoTypeInfoOf only does declare, not enough in this case :/ - t->vtinfo->codegen(Type::sir); - -#if 0 - if (Logger::enabled()) - Logger::cout() << "typeinfo decl: " << *tival << '\n'; -#endif - args.push_back(DtoBitCast(tival, fn->getFunctionType()->getParamType(2))); } diff --git a/gen/classes.cpp b/gen/classes.cpp index c7af9b7d..2e8e13b6 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -35,24 +35,21 @@ void DtoResolveClass(ClassDeclaration* cd) { - // make sure the base classes are processed first - ArrayIter base_iter(cd->baseclasses); - while (base_iter.more()) - { - BaseClass* bc = base_iter.get(); - if (bc) - { - bc->base->codegen(Type::sir); - } - base_iter.next(); - } - if (cd->ir.resolved) return; cd->ir.resolved = true; Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); LOG_SCOPE; + // make sure the base classes are processed first + ArrayIter base_iter(cd->baseclasses); + while (base_iter.more()) + { + BaseClass* bc = base_iter.get(); + DtoResolveClass(bc->base); + base_iter.next(); + } + // make sure type exists DtoType(cd->type); @@ -73,11 +70,6 @@ void DtoResolveClass(ClassDeclaration* cd) } } - bool needs_def = mustDefineSymbol(cd); - - // emit the ClassZ symbol - LLGlobalVariable* ClassZ = irAggr->getClassInfoSymbol(); - // emit the interfaceInfosZ symbol if necessary if (cd->vtblInterfaces && cd->vtblInterfaces->dim > 0) irAggr->getInterfaceArraySymbol(); // initializer is applied when it's built @@ -87,43 +79,6 @@ void DtoResolveClass(ClassDeclaration* cd) { irAggr->initializeInterface(); } - else - { - // emit the initZ symbol - LLGlobalVariable* initZ = irAggr->getInitSymbol(); - // emit the vtblZ symbol - LLGlobalVariable* vtblZ = irAggr->getVtblSymbol(); - - // perform definition - if (needs_def) - { - // set symbol initializers - initZ->setInitializer(irAggr->getDefaultInit()); - vtblZ->setInitializer(irAggr->getVtblInit()); - } - } - - // emit members - if (cd->members) - { - ArrayIter it(*cd->members); - while (!it.done()) - { - Dsymbol* member = it.get(); - if (member) - member->codegen(Type::sir); - it.next(); - } - } - - if (needs_def) - { - // emit typeinfo - DtoTypeInfoOf(cd->type); - - // define classinfo - ClassZ->setInitializer(irAggr->getClassInfoInit()); - } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -131,7 +86,7 @@ void DtoResolveClass(ClassDeclaration* cd) DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) { // resolve type - tc->sym->codegen(Type::sir); + DtoResolveClass(tc->sym); // allocate LLValue* mem; @@ -143,7 +98,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) // custom allocator else if (newexp->allocator) { - newexp->allocator->codegen(Type::sir); + DtoResolveFunction(newexp->allocator); DFuncValue dfn(newexp->allocator, newexp->allocator->ir.irFunc->func); DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs); mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom"); @@ -184,7 +139,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) { Logger::println("Calling constructor"); assert(newexp->arguments != NULL); - newexp->member->codegen(Type::sir); + DtoResolveFunction(newexp->member); DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem); return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments); } @@ -197,7 +152,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) void DtoInitClass(TypeClass* tc, LLValue* dst) { - tc->sym->codegen(Type::sir); + DtoResolveClass(tc->sym); uint64_t n = tc->sym->structsize - Target::ptrsize * 2; @@ -365,8 +320,8 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to) // call: // Object _d_dynamic_cast(Object o, ClassInfo c) - ClassDeclaration::object->codegen(Type::sir); - ClassDeclaration::classinfo->codegen(Type::sir); + DtoResolveClass(ClassDeclaration::object); + DtoResolveClass(ClassDeclaration::classinfo); llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast"); LLFunctionType* funcTy = func->getFunctionType(); @@ -378,7 +333,7 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to) // ClassInfo c TypeClass* to = static_cast(_to->toBasetype()); - to->sym->codegen(Type::sir); + DtoResolveClass(to->sym); LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol(); // unfortunately this is needed as the implementation of object differs somehow from the declaration @@ -428,8 +383,8 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to) // call: // Object _d_interface_cast(void* p, ClassInfo c) - ClassDeclaration::object->codegen(Type::sir); - ClassDeclaration::classinfo->codegen(Type::sir); + DtoResolveClass(ClassDeclaration::object); + DtoResolveClass(ClassDeclaration::classinfo); llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast"); LLFunctionType* funcTy = func->getFunctionType(); @@ -440,7 +395,7 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to) // ClassInfo c TypeClass* to = static_cast(_to->toBasetype()); - to->sym->codegen(Type::sir); + DtoResolveClass(to->sym); LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol(); // unfortunately this is needed as the implementation of object differs somehow from the declaration // this could happen in user code as well :/ @@ -623,7 +578,7 @@ static LLConstant* build_class_dtor(ClassDeclaration* cd) if (!dtor) return getNullPtr(getVoidPtrType()); - dtor->codegen(Type::sir); + DtoResolveFunction(dtor); return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::getInt8Ty(gIR->context()))); } diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 5357baac..58b04ff5 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -14,73 +14,144 @@ #include "init.h" #include "rmem.h" #include "template.h" +#include "gen/classes.h" +#include "gen/functions.h" #include "gen/irstate.h" #include "gen/llvm.h" #include "gen/llvmhelpers.h" #include "gen/logger.h" #include "gen/tollvm.h" -#include "ir/ir.h" +#include "gen/utils.h" #include "ir/irtype.h" #include "ir/irvar.h" /* ================================================================== */ -void Dsymbol::codegen(Ir*) +void Dsymbol::codegen(IRState *) { - Logger::println("Ignoring Dsymbol::codegen for %s", toChars()); + IF_LOG Logger::println("Ignoring Dsymbol::codegen for %s", toPrettyChars()); } /* ================================================================== */ -void Declaration::codegen(Ir*) +void InterfaceDeclaration::codegen(IRState *p) { - Logger::println("Ignoring Declaration::codegen for %s", toChars()); -} + IF_LOG Logger::println("InterfaceDeclaration::codegen: '%s'", toPrettyChars()); + LOG_SCOPE -/* ================================================================== */ + if (ir.defined) return; + ir.defined = true; -void InterfaceDeclaration::codegen(Ir*) -{ if (type->ty == Terror) { error("had semantic errors when compiling"); return; } if (members && symtab) - DtoResolveDsymbol(this); + { + DtoResolveClass(this); + + // Emit any members (e.g. final functions). + for (ArrayIter it(members); !it.done(); it.next()) + { + it->codegen(p); + } + + // Emit TypeInfo. + DtoTypeInfoOf(type); + + // Define __InterfaceZ. + llvm::GlobalVariable *interfaceZ = ir.irAggr->getClassInfoSymbol(); + interfaceZ->setInitializer(ir.irAggr->getClassInfoInit()); + interfaceZ->setLinkage(DtoExternalLinkage(this)); + } } /* ================================================================== */ -void StructDeclaration::codegen(Ir*) +void StructDeclaration::codegen(IRState *p) { + IF_LOG Logger::println("StructDeclaration::codegen: '%s'", toPrettyChars()); + LOG_SCOPE + + if (ir.defined) return; + ir.defined = true; + if (type->ty == Terror) { error("had semantic errors when compiling"); return; } if (members && symtab) - DtoResolveDsymbol(this); + { + DtoResolveStruct(this); + + for (ArrayIter it(members); !it.done(); it.next()) + { + it->codegen(p); + } + + // Define the __initZ symbol. + llvm::GlobalVariable *initZ = ir.irAggr->getInitSymbol(); + initZ->setInitializer(ir.irAggr->getDefaultInit()); + initZ->setLinkage(DtoExternalLinkage(this)); + + // emit typeinfo + DtoTypeInfoOf(type); + } } /* ================================================================== */ -void ClassDeclaration::codegen(Ir*) +void ClassDeclaration::codegen(IRState *p) { + IF_LOG Logger::println("ClassDeclaration::codegen: '%s'", toPrettyChars()); + LOG_SCOPE + + if (ir.defined) return; + ir.defined = true; + if (type->ty == Terror) { error("had semantic errors when compiling"); return; } if (members && symtab) - DtoResolveDsymbol(this); + { + DtoResolveClass(this); + + for (ArrayIter it(members); !it.done(); it.next()) + { + it->codegen(p); + } + + llvm::GlobalValue::LinkageTypes const linkage = DtoExternalLinkage(this); + + llvm::GlobalVariable *initZ = ir.irAggr->getInitSymbol(); + initZ->setInitializer(ir.irAggr->getDefaultInit()); + initZ->setLinkage(linkage); + + llvm::GlobalVariable *vtbl = ir.irAggr->getVtblSymbol(); + vtbl->setInitializer(ir.irAggr->getVtblInit()); + vtbl->setLinkage(linkage); + + llvm::GlobalVariable *classZ = ir.irAggr->getClassInfoSymbol(); + classZ->setInitializer(ir.irAggr->getClassInfoInit()); + classZ->setLinkage(linkage); + + // No need to do TypeInfo here, it is __classZ for classes in D2. + } } /* ================================================================== */ -void TupleDeclaration::codegen(Ir* p) +void TupleDeclaration::codegen(IRState *p) { - Logger::println("TupleDeclaration::codegen(): %s", toChars()); + IF_LOG Logger::println("TupleDeclaration::codegen(): '%s'", toPrettyChars()); + LOG_SCOPE + + if (ir.defined) return; + ir.defined = true; assert(isexp); assert(objects); @@ -97,16 +168,21 @@ void TupleDeclaration::codegen(Ir* p) /* ================================================================== */ -void VarDeclaration::codegen(Ir* p) +void VarDeclaration::codegen(IRState *p) { - Logger::print("VarDeclaration::codegen(): %s | %s\n", toChars(), type->toChars()); + IF_LOG Logger::println("VarDeclaration::codegen(): '%s'", toPrettyChars()); LOG_SCOPE; + if (ir.defined) return; + ir.defined = true; + if (type->ty == Terror) { error("had semantic errors when compiling"); return; } + DtoResolveVariable(this); + // just forward aliases if (aliassym) { @@ -115,10 +191,6 @@ void VarDeclaration::codegen(Ir* p) return; } - // output the parent aggregate first - if (AggregateDeclaration* ad = isMember()) - ad->codegen(p); - // global variable if (isDataseg() || (storage_class & (STCconst | STCimmutable) && init)) { @@ -129,37 +201,14 @@ void VarDeclaration::codegen(Ir* p) "manifest constant being codegen'd!"); #endif - // don't duplicate work - if (this->ir.resolved) return; - this->ir.resolved = true; - this->ir.declared = true; + llvm::GlobalVariable *gvar = llvm::cast( + this->ir.irGlobal->value); + assert(gvar && "DtoResolveVariable should have created value"); - this->ir.irGlobal = new IrGlobal(this); - - Logger::println("parent: %s (%s)", parent->toChars(), parent->kind()); - - const bool isLLConst = isConst() && init; const llvm::GlobalValue::LinkageTypes llLinkage = DtoLinkage(this); - assert(!ir.initialized); - ir.initialized = gIR->dmodule; - std::string llName(mangle()); - - // Since the type of a global must exactly match the type of its - // initializer, we cannot know the type until after we have emitted the - // latter (e.g. in case of unions, …). However, it is legal for the - // initializer to refer to the address of the variable. Thus, we first - // create a global with the generic type (note the assignment to - // this->ir.irGlobal->value!), and in case we also do an initializer - // with a different type later, swap it out and replace any existing - // uses with bitcasts to the previous type. - llvm::GlobalVariable* gvar = getOrCreateGlobal(loc, *gIR->module, - i1ToI8(DtoType(type)), isLLConst, llLinkage, 0, llName, - isThreadlocal()); - this->ir.irGlobal->value = gvar; - // Check if we are defining or just declaring the global in this module. - if (!(storage_class & STCextern) && mustDefineSymbol(this)) + if (!(storage_class & STCextern)) { // Build the initializer. Might use this->ir.irGlobal->value! LLConstant *initVal = DtoConstInitializer(loc, type, init); @@ -168,10 +217,12 @@ void VarDeclaration::codegen(Ir* p) if (initVal->getType() != gvar->getType()->getElementType()) { llvm::GlobalVariable* newGvar = getOrCreateGlobal(loc, - *gIR->module, initVal->getType(), isLLConst, llLinkage, 0, + *p->module, initVal->getType(), gvar->isConstant(), + llLinkage, 0, "", // We take on the name of the old global below. - isThreadlocal()); + gvar->isThreadLocal()); + newGvar->setAlignment(gvar->getAlignment()); newGvar->takeName(gvar); llvm::Constant* newValue = @@ -187,22 +238,17 @@ void VarDeclaration::codegen(Ir* p) assert(!ir.irGlobal->constInit); ir.irGlobal->constInit = initVal; gvar->setInitializer(initVal); + gvar->setLinkage(llLinkage); // Also set up the edbug info. - gIR->DBuilder.EmitGlobalVariable(gvar, this); + p->DBuilder.EmitGlobalVariable(gvar, this); } - // Set the alignment (it is important not to use type->alignsize because - // VarDeclarations can have an align() attribute independent of the type - // as well). - if (alignment != STRUCTALIGN_DEFAULT) - gvar->setAlignment(alignment); - // If this global is used from a naked function, we need to create an // artificial "use" for it, or it could be removed by the optimizer if // the only reference to it is in inline asm. if (nakedUse) - gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType())); + p->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType())); if (Logger::enabled()) Logger::cout() << *gvar << '\n'; @@ -211,11 +257,14 @@ void VarDeclaration::codegen(Ir* p) /* ================================================================== */ -void TypedefDeclaration::codegen(Ir*) +void TypedefDeclaration::codegen(IRState *) { - Logger::print("TypedefDeclaration::codegen: %s\n", toChars()); + IF_LOG Logger::println("TypedefDeclaration::codegen: '%s'", toPrettyChars()); LOG_SCOPE; + if (ir.defined) return; + ir.defined = true; + if (type->ty == Terror) { error("had semantic errors when compiling"); return; @@ -227,9 +276,9 @@ void TypedefDeclaration::codegen(Ir*) /* ================================================================== */ -void EnumDeclaration::codegen(Ir*) +void EnumDeclaration::codegen(IRState *) { - Logger::println("Ignoring EnumDeclaration::codegen for %s", toChars()); + IF_LOG Logger::println("Ignoring EnumDeclaration::codegen: '%s'", toPrettyChars()); if (type->ty == Terror) { error("had semantic errors when compiling"); @@ -239,54 +288,56 @@ void EnumDeclaration::codegen(Ir*) /* ================================================================== */ -void FuncDeclaration::codegen(Ir* p) +void FuncDeclaration::codegen(IRState *p) { // don't touch function aliases, they don't contribute any new symbols if (!isFuncAliasDeclaration()) { - DtoResolveDsymbol(this); + DtoDefineFunction(this); } } /* ================================================================== */ -void TemplateInstance::codegen(Ir* p) +void TemplateInstance::codegen(IRState *p) { -#if LOG - printf("TemplateInstance::codegen('%s', this = %p)\n", toChars(), this); -#endif - if (ignore) - return; + IF_LOG Logger::println("TemplateInstance::codegen: '%s'", toPrettyChars()); + LOG_SCOPE + + if (ir.defined) return; + ir.defined = true; if (!errors && members) { for (unsigned i = 0; i < members->dim; i++) { - Dsymbol *s = static_cast(members->data[i]); - s->codegen(p); + (*members)[i]->codegen(p); } } } /* ================================================================== */ -void TemplateMixin::codegen(Ir* p) +void TemplateMixin::codegen(IRState *p) { + IF_LOG Logger::println("TemplateInstance::codegen: '%s'", toPrettyChars()); + LOG_SCOPE + + if (ir.defined) return; + ir.defined = true; + if (!errors && members) { for (unsigned i = 0; i < members->dim; i++) { - Dsymbol *s = static_cast(members->data[i]); - if (s->isVarDeclaration()) - continue; - s->codegen(p); + (*members)[i]->codegen(p); } } } /* ================================================================== */ -void AttribDeclaration::codegen(Ir* p) +void AttribDeclaration::codegen(IRState *p) { Array *d = include(NULL, NULL); @@ -301,7 +352,7 @@ void AttribDeclaration::codegen(Ir* p) /* ================================================================== */ -void PragmaDeclaration::codegen(Ir* p) +void PragmaDeclaration::codegen(IRState *p) { if (ident == Id::lib) { diff --git a/gen/functions.cpp b/gen/functions.cpp index 7e0122a1..57d4fb78 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -702,6 +702,12 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) Logger::println("DtoDeclareFunction(%s): %s", fdecl->toPrettyChars(), fdecl->loc.toChars()); LOG_SCOPE; + if (fdecl->isUnitTestDeclaration() && !global.params.useUnitTests) + { + Logger::println("unit tests not enabled"); + return; + } + //printf("declare function: %s\n", fdecl->toPrettyChars()); // intrinsic sanity check @@ -715,10 +721,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) TypeFunction* f = static_cast(t); IrFuncTy &irFty = fdecl->irFty; - bool declareOnly = !mustDefineSymbol(fdecl); - - if (fdecl->llvmInternal == LLVMva_start) - declareOnly = true; if (!fdecl->ir.irFunc) { fdecl->ir.irFunc = new IrFunction(fdecl); @@ -753,9 +755,16 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) LLFunction* func = vafunc ? vafunc : gIR->module->getFunction(mangledName); if (!func) { if(fdecl->llvmInternal == LLVMinline_ir) + { func = DtoInlineIRFunction(fdecl); + } else - func = LLFunction::Create(functype, DtoLinkage(fdecl), mangledName, gIR->module); + { + // All function declarations are "external" - any other linkage type + // is set when actually defining the function. + func = LLFunction::Create(functype, + llvm::GlobalValue::ExternalLinkage, mangledName, gIR->module); + } } else if (func->getFunctionType() != functype) { error(fdecl->loc, "Function type does not match previously declared function with the same mangled name: %s", fdecl->mangle()); } @@ -792,35 +801,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) gIR->mainFunc = func; } - // shared static ctor - if (fdecl->isSharedStaticCtorDeclaration()) { - if (mustDefineSymbol(fdecl)) { - gIR->sharedCtors.push_back(fdecl); - } - } - // shared static dtor - else if (StaticDtorDeclaration *dtorDecl = fdecl->isSharedStaticDtorDeclaration()) { - if (mustDefineSymbol(fdecl)) { - gIR->sharedDtors.push_front(fdecl); - if (dtorDecl->vgate) - gIR->sharedGates.push_front(dtorDecl->vgate); - } - } else - // static ctor - if (fdecl->isStaticCtorDeclaration()) { - if (mustDefineSymbol(fdecl)) { - gIR->ctors.push_back(fdecl); - } - } - // static dtor - else if (StaticDtorDeclaration *dtorDecl = fdecl->isStaticDtorDeclaration()) { - if (mustDefineSymbol(fdecl)) { - gIR->dtors.push_front(fdecl); - if (dtorDecl->vgate) - gIR->gates.push_front(dtorDecl->vgate); - } - } - if (fdecl->neverInline) { fdecl->ir.irFunc->setNeverInline(); @@ -909,14 +889,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl) } } } - - if (fdecl->isUnitTestDeclaration() && !declareOnly) - gIR->unitTests.push_back(fdecl); - - if (!declareOnly) - Type::sir->addFunctionBody(fdecl->ir.irFunc); - else - assert(func->getLinkage() != llvm::GlobalValue::InternalLinkage); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -927,15 +899,37 @@ void DtoDefineFunction(FuncDeclaration* fd) { DtoDeclareFunction(fd); - if (fd->ir.defined) return; - fd->ir.defined = true; - assert(fd->ir.declared); if (Logger::enabled()) - Logger::println("DtoDefineFunc(%s): %s", fd->toPrettyChars(), fd->loc.toChars()); + Logger::println("DtoDefineFunction(%s): %s", fd->toPrettyChars(), fd->loc.toChars()); LOG_SCOPE; + // Be sure to call DtoDeclareFunction first, as LDC_inline_asm functions are + // "defined" there. TODO: Clean this up. + if (fd->ir.defined) return; + fd->ir.defined = true; + + if (fd->isUnitTestDeclaration()) { + if (global.params.useUnitTests) + gIR->unitTests.push_back(fd); + else + return; + } else if (fd->isSharedStaticCtorDeclaration()) { + gIR->sharedCtors.push_back(fd); + } else if (StaticDtorDeclaration *dtorDecl = fd->isSharedStaticDtorDeclaration()) { + gIR->sharedDtors.push_front(fd); + if (dtorDecl->vgate) + gIR->sharedGates.push_front(dtorDecl->vgate); + } else if (fd->isStaticCtorDeclaration()) { + gIR->ctors.push_back(fd); + } else if (StaticDtorDeclaration *dtorDecl = fd->isStaticDtorDeclaration()) { + gIR->dtors.push_front(fd); + if (dtorDecl->vgate) + gIR->gates.push_front(dtorDecl->vgate); + } + + // if this function is naked, we take over right away! no standard processing! if (fd->naked) { @@ -954,9 +948,6 @@ void DtoDefineFunction(FuncDeclaration* fd) llvm::Function* func = fd->ir.irFunc->func; - // sanity check - assert(mustDefineSymbol(fd)); - // set module owner fd->ir.DModule = gIR->dmodule; @@ -972,6 +963,8 @@ void DtoDefineFunction(FuncDeclaration* fd) if (fd->isMain()) gIR->emitMain = true; + func->setLinkage(DtoLinkage(fd)); + // On x86_64, always set 'uwtable' for System V ABI compatibility. // TODO: Find a better place for this. if (global.params.targetTriple.getArch() == llvm::Triple::x86_64) @@ -1185,7 +1178,7 @@ llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl) break; } - DtoResolveDsymbol(f); + DtoResolveFunction(f); return llvm::cast(DtoType(f->type)); } diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 0fdd54af..e2cef943 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -737,10 +737,10 @@ DValue* DtoCastNull(Loc& loc, DValue* val, Type* to) Type* totype = to->toBasetype(); LLType* tolltype = DtoType(to); - if (totype->ty == Tpointer) + if (totype->ty == Tpointer || totype->ty == Tclass) { if (Logger::enabled()) - Logger::cout() << "cast null to pointer: " << *tolltype << '\n'; + Logger::cout() << "cast null to pointer/class: " << *tolltype << '\n'; LLValue *rval = DtoBitCast(val->getRVal(), tolltype); return new DImValue(to, rval); } @@ -1005,8 +1005,86 @@ void DtoResolveDsymbol(Dsymbol* dsym) else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) { DtoResolveTypeInfo(fd); } - else { - llvm_unreachable("Unsupported DSymbol for DtoResolveDsymbol."); + else if (VarDeclaration* vd = dsym->isVarDeclaration()) { + DtoResolveVariable(vd); + } +} + +void DtoResolveVariable(VarDeclaration* vd) +{ + if (vd->isTypeInfoDeclaration()) + return DtoResolveTypeInfo(static_cast(vd)); + + IF_LOG Logger::println("DtoResolveVariable(%s)", vd->toPrettyChars()); + LOG_SCOPE; + + // just forward aliases + // TODO: Is this required here or is the check in VarDeclaration::codegen + // sufficient? + if (vd->aliassym) + { + Logger::println("alias sym"); + DtoResolveDsymbol(vd->aliassym); + return; + } + + if (AggregateDeclaration* ad = vd->isMember()) + DtoResolveDsymbol(ad); + + // global variable + if (vd->isDataseg() || (vd->storage_class & (STCconst | STCimmutable) && vd->init)) + { + Logger::println("data segment"); + + #if 0 // TODO: + assert(!(storage_class & STCmanifest) && + "manifest constant being codegen'd!"); + #endif + + // don't duplicate work + if (vd->ir.resolved) return; + vd->ir.resolved = true; + vd->ir.declared = true; + + vd->ir.irGlobal = new IrGlobal(vd); + + IF_LOG { + if (vd->parent) + Logger::println("parent: %s (%s)", vd->parent->toChars(), vd->parent->kind()); + else + Logger::println("parent: null"); + } + + const bool isLLConst = vd->isConst() && vd->init; + + assert(!vd->ir.initialized); + vd->ir.initialized = gIR->dmodule; + std::string llName(vd->mangle()); + + // Since the type of a global must exactly match the type of its + // initializer, we cannot know the type until after we have emitted the + // latter (e.g. in case of unions, …). However, it is legal for the + // initializer to refer to the address of the variable. Thus, we first + // create a global with the generic type (note the assignment to + // vd->ir.irGlobal->value!), and in case we also do an initializer + // with a different type later, swap it out and replace any existing + // uses with bitcasts to the previous type. + // + // We always start out with external linkage; any other type is set + // when actually defining it in VarDeclaration::codegen. + llvm::GlobalVariable* gvar = getOrCreateGlobal(vd->loc, *gIR->module, + i1ToI8(DtoType(vd->type)), isLLConst, llvm::GlobalValue::ExternalLinkage, + 0, llName, vd->isThreadlocal()); + vd->ir.irGlobal->value = gvar; + + // Set the alignment (it is important not to use type->alignsize because + // VarDeclarations can have an align() attribute independent of the type + // as well). + if (vd->alignment != STRUCTALIGN_DEFAULT) + gvar->setAlignment(vd->alignment); + + if (Logger::enabled()) + Logger::cout() << *gvar << '\n'; } } @@ -1132,7 +1210,7 @@ DValue* DtoDeclarationExp(Dsymbol* declaration) // static if (vd->isDataseg()) { - vd->codegen(Type::sir); + vd->codegen(gIR); } else { @@ -1144,19 +1222,19 @@ DValue* DtoDeclarationExp(Dsymbol* declaration) else if (StructDeclaration* s = declaration->isStructDeclaration()) { Logger::println("StructDeclaration"); - s->codegen(Type::sir); + s->codegen(gIR); } // function declaration else if (FuncDeclaration* f = declaration->isFuncDeclaration()) { Logger::println("FuncDeclaration"); - f->codegen(Type::sir); + f->codegen(gIR); } // class else if (ClassDeclaration* e = declaration->isClassDeclaration()) { Logger::println("ClassDeclaration"); - e->codegen(Type::sir); + e->codegen(gIR); } // typedef else if (TypedefDeclaration* tdef = declaration->isTypedefDeclaration()) @@ -1293,7 +1371,7 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init) else if (StructInitializer* si = init->isStructInitializer()) { Logger::println("const struct initializer"); - si->ad->codegen(Type::sir); + DtoResolveDsymbol(si->ad); return si->ad->ir.irAggr->createStructInitializer(si); } else if (ArrayInitializer* ai = init->isArrayInitializer()) @@ -1315,41 +1393,6 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init) ////////////////////////////////////////////////////////////////////////////////////////// -static LLConstant* expand_to_sarray(Type* targetType, Type* initType, LLConstant* initConst) -{ - Type* expbase = stripModifiers(initType); - IF_LOG Logger::println("expbase: %s", expbase->toChars()); - Type* t = targetType; - - LLSmallVector dims; - - while(1) - { - Logger::println("t: %s", t->toChars()); - if (t->equals(expbase)) - break; - assert(t->ty == Tsarray); - TypeSArray* tsa = static_cast(t); - dims.push_back(tsa->dim->toInteger()); - assert(t->nextOf()); - t = stripModifiers(t->nextOf()->toBasetype()); - } - - size_t i = dims.size(); - assert(i); - - std::vector inits; - while (i--) - { - LLArrayType* arrty = LLArrayType::get(initConst->getType(), dims[i]); - inits.clear(); - inits.insert(inits.end(), dims[i], initConst); - initConst = LLConstantArray::get(arrty, inits); - } - - return initConst; -} - LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp) { IF_LOG Logger::println("DtoConstExpInit(targetType = %s, exp = %s)", @@ -1374,7 +1417,6 @@ LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp) if (expBase->equals(targetBase) && targetBase->ty != Tbool) { - Logger::println("Matching D types, nothing left to do."); return val; } @@ -1393,7 +1435,12 @@ LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp) fatal(); } Logger::println("Building constant array initializer to single value."); - return expand_to_sarray(targetBase, expBase, val); + + d_uns64 elemCount = targetBase->size() / expBase->size(); + assert(targetBase->size() % expBase->size() == 0); + + std::vector initVals(elemCount, val); + return llvm::ConstantArray::get(llvm::ArrayType::get(llType, elemCount), initVals); } if (targetBase->ty == Tvector) @@ -1428,11 +1475,14 @@ LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp) LLConstant* DtoTypeInfoOf(Type* type, bool base) { + IF_LOG Logger::println("DtoTypeInfoOf(type = '%s', base='%d')", type->toChars(), base); + LOG_SCOPE + type = type->merge2(); // needed.. getTypeInfo does the same type->getTypeInfo(NULL); TypeInfoDeclaration* tidecl = type->vtinfo; assert(tidecl); - tidecl->codegen(Type::sir); + tidecl->codegen(gIR); assert(tidecl->ir.irGlobal != NULL); assert(tidecl->ir.irGlobal->value != NULL); LLConstant* c = isaConstant(tidecl->ir.irGlobal->value); @@ -1500,98 +1550,6 @@ void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, s ////////////////////////////////////////////////////////////////////////////////////////// -bool mustDefineSymbol(Dsymbol* s) -{ - if (FuncDeclaration* fd = s->isFuncDeclaration()) - { - // we can't (and probably shouldn't?) define functions - // that weren't semantic3'ed - if (fd->semanticRun < PASSsemantic3) - return false; - - // If a function has no body, we cannot possibly emit it (and so it - // cannot be available_externally either). - if (!fd->fbody) - return false; - - if (fd->isArrayOp == 1) - return true; - - if (global.inExtraInliningSemantic && fd->availableExternally) { - // Emit extra functions if we're inlining. - // These will get available_externally linkage, - // so they shouldn't end up in object code. - - assert(fd->type->ty == Tfunction); - // * If we define extra static constructors, static destructors - // and unittests they'll get registered to run, and we won't - // be calling them directly anyway. - // * If it's a large function, don't emit it unnecessarily. - // Use DMD's canInline() to determine whether it's large. - // inlineCost() members have been changed to pay less attention - // to DMDs limitations, but still have some issues. The most glaring - // offenders are any kind of control flow statements other than - // 'if' and 'return'. - if ( !fd->isStaticCtorDeclaration() - && !fd->isStaticDtorDeclaration() - && !fd->isUnitTestDeclaration() - && fd->canInline(true, false, false)) - { - return true; - } - - // This was only semantic'ed for inlining checks. - // We won't be inlining this, so we only need to emit a declaration. - return false; - } - } - - if (VarDeclaration* vd = s->isVarDeclaration()) - { - // Never define 'extern' variables. - if (vd->storage_class & STCextern) - return false; - } - - // Inlining checks may create some variable and class declarations - // we don't need to emit. - if (global.inExtraInliningSemantic) - { - if (VarDeclaration* vd = s->isVarDeclaration()) - if (vd->availableExternally) - return false; - - if (ClassDeclaration* cd = s->isClassDeclaration()) - if (cd->availableExternally) - return false; - } - - TemplateInstance* tinst = DtoIsTemplateInstance(s, true); - if (tinst) - { - if (!global.params.singleObj) - return true; - - if (!tinst->emittedInModule) - { - gIR->seenTemplateInstances.insert(tinst); - tinst->emittedInModule = gIR->dmodule; - } - return tinst->emittedInModule == gIR->dmodule; - } - - return s->getModule() == gIR->dmodule; -} - -////////////////////////////////////////////////////////////////////////////////////////// - -bool needsTemplateLinkage(Dsymbol* s) -{ - return DtoIsTemplateInstance(s) && mustDefineSymbol(s); -} - -////////////////////////////////////////////////////////////////////////////////////////// - bool hasUnalignedFields(Type* t) { t = t->toBasetype(); @@ -1732,7 +1690,7 @@ void callPostblit(Loc &loc, Expression *exp, LLValue *val) FuncDeclaration *fd = sd->postblit; if (fd->storage_class & STCdisable) fd->toParent()->error(loc, "is not copyable because it is annotated with @disable"); - fd->codegen(Type::sir); + DtoResolveFunction(fd); Expressions args; DFuncValue dfn(fd, fd->ir.irFunc->func, val); DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args); @@ -1865,14 +1823,14 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl) else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration()) { Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars()); - cid->cd->codegen(Type::sir);; + DtoResolveClass(cid->cd); return new DVarValue(type, vd, cid->cd->ir.irAggr->getClassInfoSymbol()); } // typeinfo else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) { Logger::println("TypeInfoDeclaration"); - tid->codegen(Type::sir); + DtoResolveTypeInfo(tid); assert(tid->ir.getIrValue()); LLType* vartype = DtoType(type); LLValue* m = tid->ir.getIrValue(); @@ -1921,7 +1879,7 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl) // take care of forward references of global variables const bool isGlobal = vd->isDataseg() || (vd->storage_class & STCextern); if (isGlobal) - vd->codegen(Type::sir); + DtoResolveVariable(vd); assert(vd->ir.isSet() && "Variable not resolved."); @@ -1950,19 +1908,15 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl) if (FuncDeclaration* fdecl = decl->isFuncDeclaration()) { Logger::println("FuncDeclaration"); - LLValue* func = 0; fdecl = fdecl->toAliasFunc(); if (fdecl->llvmInternal == LLVMinline_asm) { + // TODO: Is this needed? If so, what about other intrinsics? error("special ldc inline asm is not a normal function"); fatal(); } - else if (fdecl->llvmInternal != LLVMva_arg) - { - fdecl->codegen(Type::sir); - func = fdecl->ir.irFunc->func; - } - return new DFuncValue(fdecl, func); + DtoResolveFunction(fdecl); + return new DFuncValue(fdecl, fdecl->ir.irFunc->func); } if (SymbolDeclaration* sdecl = decl->isSymbolDeclaration()) @@ -1973,7 +1927,7 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl) assert(sdecltype->ty == Tstruct); TypeStruct* ts = static_cast(sdecltype); assert(ts->sym); - ts->sym->codegen(Type::sir); + DtoResolveStruct(ts->sym); LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol(); initsym = DtoBitCast(initsym, DtoType(ts->pointerTo())); @@ -2009,7 +1963,7 @@ llvm::Constant* DtoConstSymbolAddress(const Loc& loc, Declaration* decl) return NULL; } - vd->codegen(Type::sir); + DtoResolveVariable(vd); LLConstant* llc = llvm::dyn_cast(vd->ir.getIrValue()); assert(llc); return llc; @@ -2017,7 +1971,7 @@ llvm::Constant* DtoConstSymbolAddress(const Loc& loc, Declaration* decl) // static function else if (FuncDeclaration* fd = decl->isFuncDeclaration()) { - fd->codegen(Type::sir); + DtoResolveFunction(fd); IrFunction* irfunc = fd->ir.irFunc; return irfunc->func; } diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 14a15678..14d3adf6 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -102,9 +102,15 @@ DValue* DtoPaintType(Loc& loc, DValue* val, Type* to); // is template instance check, returns module where instantiated TemplateInstance* DtoIsTemplateInstance(Dsymbol* s, bool checkLiteralOwner = false); -/// Generate code for the symbol. -/// Dispatches as appropriate. +/// Makes sure the declarations corresponding to the given D symbol have been +/// emitted to the currently processed LLVM module. +/// +/// This means that dsym->ir can be expected to set to reasonable values. +/// +/// This function does *not* emit any (function, variable) *definitions*; this +/// is done by Dsymbol::codegen. void DtoResolveDsymbol(Dsymbol* dsym); +void DtoResolveVariable(VarDeclaration* var); // declaration inside a declarationexp void DtoVarDeclaration(VarDeclaration* var); @@ -135,12 +141,6 @@ void findDefaultTarget(); /// Fixup an overloaded intrinsic name string. void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name); -/// Returns 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); diff --git a/gen/module.cpp b/gen/module.cpp index ebd447d0..3974b1e9 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -326,7 +326,7 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) return ctor; } -llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) +llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context) { bool logenabled = Logger::enabled(); if (llvmForceLogging && !logenabled) @@ -363,8 +363,6 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) // reset all IR data stored in Dsymbols IrDsymbol::resetAll(); - sir->setState(&ir); - // set target triple ir.module->setTargetTriple(global.params.targetTriple.str()); @@ -395,12 +393,9 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) for (unsigned k=0; k < members->dim; k++) { Dsymbol* dsym = static_cast(members->data[k]); assert(dsym); - dsym->codegen(sir); + dsym->codegen(&ir); } - // emit function bodies - sir->emitFunctionBodies(); - // for singleobj-compilation, fully emit all seen template instances if (global.params.singleObj) { @@ -408,11 +403,8 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) { IRState::TemplateInstanceSet::iterator it, end = ir.seenTemplateInstances.end(); for (it = ir.seenTemplateInstances.begin(); it != end; ++it) - (*it)->codegen(sir); + (*it)->codegen(&ir); ir.seenTemplateInstances.clear(); - - // emit any newly added function bodies - sir->emitFunctionBodies(); } } @@ -432,8 +424,6 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) Logger::disable(); } - sir->setState(NULL); - return ir.module; } @@ -532,8 +522,8 @@ void Module::genmoduleinfo() std::vector classInits; for (size_t i = 0; i < aclasses.dim; i++) { - ClassDeclaration* cd = static_cast(aclasses.data[i]); - cd->codegen(Type::sir); + ClassDeclaration* cd = aclasses[i]; + DtoResolveClass(cd); if (cd->isInterfaceDeclaration()) { @@ -638,6 +628,7 @@ void Module::genmoduleinfo() // create and set initializer LLGlobalVariable *moduleInfoSym = moduleInfoSymbol(); b.finalize(moduleInfoSym->getType()->getPointerElementType(), moduleInfoSym); + moduleInfoSym->setLinkage(llvm::GlobalValue::ExternalLinkage); // build the modulereference and ctor for registering it LLFunction* mictor = build_module_reference_and_ctor(moduleInfoSym); diff --git a/gen/naked.cpp b/gen/naked.cpp index 5e6f5d12..0e598091 100644 --- a/gen/naked.cpp +++ b/gen/naked.cpp @@ -85,7 +85,8 @@ void ExpStatement::toNakedIR(IRState *p) // enum decls should always be safe // make sure the symbols gets processed - d->declaration->codegen(Type::sir); + // TODO: codegen() here is likely incorrect + d->declaration->codegen(p); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/rttibuilder.cpp b/gen/rttibuilder.cpp index c1711d70..9b6b5a9e 100644 --- a/gen/rttibuilder.cpp +++ b/gen/rttibuilder.cpp @@ -11,6 +11,7 @@ #include "aggregate.h" #include "mtype.h" #include "gen/arrays.h" +#include "gen/functions.h" #include "gen/irstate.h" #include "gen/linkage.h" #include "gen/llvm.h" @@ -20,8 +21,7 @@ RTTIBuilder::RTTIBuilder(AggregateDeclaration* base_class) { - // make sure the base typeinfo class has been processed - base_class->codegen(Type::sir); + DtoResolveDsymbol(base_class); base = base_class; basetype = static_cast(base->type); @@ -136,7 +136,7 @@ void RTTIBuilder::push_funcptr(FuncDeclaration* fd, Type* castto) { if (fd) { - fd->codegen(Type::sir); + DtoResolveFunction(fd); LLConstant* F = fd->ir.irFunc->func; if (castto) F = DtoBitCast(F, DtoType(castto)); @@ -177,7 +177,9 @@ void RTTIBuilder::finalize(LLType* type, LLValue* value) LLConstant* tiInit = LLConstantStruct::get(st, inits); // set the initializer - isaGlobalVar(value)->setInitializer(tiInit); + llvm::GlobalVariable* gvar = llvm::cast(value); + gvar->setInitializer(tiInit); + gvar->setLinkage(TYPEINFO_LINKAGE_TYPE); } LLConstant* RTTIBuilder::get_constant(LLStructType *initType) diff --git a/gen/structs.cpp b/gen/structs.cpp index 19055036..ed2171c9 100644 --- a/gen/structs.cpp +++ b/gen/structs.cpp @@ -55,32 +55,6 @@ void DtoResolveStruct(StructDeclaration* sd) assert(!vd->ir.irField); (void)new IrField(vd); } - - // perform definition - bool emitGlobalData = mustDefineSymbol(sd); - if (emitGlobalData) - { - // emit the initZ symbol - LLGlobalVariable* initZ = iraggr->getInitSymbol(); - - // set initZ initializer - initZ->setInitializer(iraggr->getDefaultInit()); - } - - // emit members - if (sd->members) - { - for (ArrayIter it(sd->members); !it.done(); it.next()) - { - it.get()->codegen(Type::sir); - } - } - - if (emitGlobalData) - { - // emit typeinfo - DtoTypeInfoOf(sd->type); - } } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/target.cpp b/gen/target.cpp index f4babdfa..6c2b8f39 100644 --- a/gen/target.cpp +++ b/gen/target.cpp @@ -10,14 +10,10 @@ #include #include "target.h" +#include "gen/irstate.h" #include "mars.h" #include "mtype.h" -unsigned GetTypeAlignment(Type* t); -unsigned GetPointerSize(); -unsigned GetTypeStoreSize(Type* t); -unsigned GetTypeAllocSize(Type* t); - int Target::ptrsize; int Target::realsize; int Target::realpad; @@ -25,10 +21,12 @@ int Target::realalignsize; void Target::init() { - ptrsize = GetPointerSize(); - realsize = GetTypeAllocSize(Type::basic[Tfloat80]); - realpad = realsize - GetTypeStoreSize(Type::basic[Tfloat80]); - realalignsize = GetTypeAlignment(Type::basic[Tfloat80]); + ptrsize = gDataLayout->getPointerSize(ADDRESS_SPACE); + + llvm::Type* real = DtoType(Type::basic[Tfloat80]); + realsize = gDataLayout->getTypeAllocSize(real); + realpad = realsize - gDataLayout->getTypeStoreSize(real); + realalignsize = gDataLayout->getABITypeAlignment(real); } /****************************** @@ -39,7 +37,7 @@ unsigned Target::alignsize (Type* type) { assert (type->isTypeBasic()); if (type->ty == Tvoid) return 1; - return GetTypeAlignment(type); + return gDataLayout->getABITypeAlignment(DtoType(type)); } /****************************** diff --git a/gen/toir.cpp b/gen/toir.cpp index 2f794e13..2f3acc09 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -13,6 +13,7 @@ #include "id.h" #include "init.h" #include "mtype.h" +#include "module.h" #include "port.h" #include "rmem.h" #include "template.h" @@ -200,8 +201,7 @@ LLConstant* VarExp::toConstElem(IRState* p) Logger::print("Sym: type=%s\n", sdecltype->toChars()); assert(sdecltype->ty == Tstruct); TypeStruct* ts = static_cast(sdecltype); - ts->sym->codegen(Type::sir); - + DtoResolveStruct(ts->sym); return ts->sym->ir.irAggr->getDefaultInit(); } @@ -1186,7 +1186,7 @@ LLConstant* CastExp::toConstElem(IRState* p) else if (tb->ty == Tpointer && e1->op == TOKvar) { VarDeclaration *vd = static_cast(e1)->var->isVarDeclaration(); assert(vd); - vd->codegen(Type::sir); + DtoResolveVariable(vd); LLConstant *value = vd->ir.irGlobal ? isaConstant(vd->ir.irGlobal->value) : 0; if (!value) goto Lerr; @@ -1355,7 +1355,7 @@ DValue* AddrExp::toElem(IRState* p) //Logger::println("FuncDeclaration"); FuncDeclaration* fd = fv->func; assert(fd); - fd->codegen(Type::sir); + DtoResolveFunction(fd); return new DFuncValue(fd, fd->ir.irFunc->func); } else if (v->isIm()) { @@ -1407,7 +1407,7 @@ LLConstant* AddrExp::toConstElem(IRState* p) VarDeclaration* vd = vexp->var->isVarDeclaration(); assert(vd); assert(vd->type->toBasetype()->ty == Tsarray); - vd->codegen(Type::sir); + DtoResolveVariable(vd); assert(vd->ir.irGlobal); // get index @@ -1585,7 +1585,7 @@ DValue* DotVarExp::toElem(IRState* p) } else if (FuncDeclaration* fdecl = var->isFuncDeclaration()) { - DtoResolveDsymbol(fdecl); + DtoResolveFunction(fdecl); // This is a bit more convoluted than it would need to be, because it // has to take templated interface methods into account, for which @@ -1632,7 +1632,6 @@ DValue* DotVarExp::toElem(IRState* p) } else { - fdecl->codegen(Type::sir); funcval = fdecl->ir.irFunc->func; } assert(funcval); @@ -2123,7 +2122,7 @@ DValue* NewExp::toElem(IRState* p) if (allocator) { // custom allocator - allocator->codegen(Type::sir); + DtoResolveFunction(allocator); DFuncValue dfn(allocator, allocator->ir.irFunc->func); DValue* res = DtoCallFunction(loc, NULL, &dfn, newargs); mem = DtoBitCast(res->getRVal(), DtoType(ntype->pointerTo()), ".newstruct_custom"); @@ -2139,7 +2138,7 @@ DValue* NewExp::toElem(IRState* p) } else { assert(ts->sym); - ts->sym->codegen(Type::sir); + DtoResolveStruct(ts->sym); DtoAggrCopy(mem, ts->sym->ir.irAggr->getInitSymbol()); } if (ts->sym->isNested() && ts->sym->vthis) @@ -2150,7 +2149,7 @@ DValue* NewExp::toElem(IRState* p) { Logger::println("Calling constructor"); assert(arguments != NULL); - member->codegen(Type::sir); + DtoResolveFunction(member); DFuncValue dfn(member, member->ir.irFunc->func, mem); DtoCallFunction(loc, ts, &dfn, arguments); } @@ -2313,7 +2312,7 @@ DValue* AssertExp::toElem(IRState* p) (invdecl = static_cast(condty->nextOf())->sym->inv) != NULL) { Logger::print("calling struct invariant"); - static_cast(condty->nextOf())->sym->codegen(Type::sir); + DtoResolveFunction(invdecl); DFuncValue invfunc(invdecl, invdecl->ir.irFunc->func, cond->getRVal()); DtoCallFunction(loc, NULL, &invfunc, NULL); } @@ -2541,7 +2540,21 @@ DValue* DelegateExp::toElem(IRState* p) llvm_unreachable("Delegate to interface method not implemented."); else { - func->codegen(Type::sir); + DtoResolveFunction(func); + + // We need to actually codegen the function here, as literals are not + // added to the module member list. + if (func->semanticRun == PASSsemantic3done) + { + Dsymbol *owner = func->toParent(); + while (!owner->isTemplateInstance() && owner->toParent()) + owner = owner->toParent(); + if (owner->isTemplateInstance() || owner == p->dmodule) + { + func->codegen(p); + } + } + castfptr = func->ir.irFunc->func; } @@ -2785,7 +2798,9 @@ DValue* FuncExp::toElem(IRState* p) if (fd->isNested()) Logger::println("nested"); Logger::println("kind = %s", fd->kind()); - fd->codegen(Type::sir); + // We need to actually codegen the function here, as literals are not added + // to the module member list. + fd->codegen(p); assert(fd->ir.irFunc->func); if (fd->isNested()) { @@ -2852,7 +2867,9 @@ LLConstant* FuncExp::toConstElem(IRState* p) return 0; } - fd->codegen(Type::sir); + // We need to actually codegen the function here, as literals are not added + // to the module member list. + fd->codegen(p); assert(fd->ir.irFunc->func); return fd->ir.irFunc->func; @@ -2987,7 +3004,7 @@ DValue* StructLiteralExp::toElem(IRState* p) assert(sdecltype->ty == Tstruct); TypeStruct* ts = static_cast(sdecltype); assert(ts->sym); - ts->sym->codegen(Type::sir); + DtoResolveStruct(ts->sym); LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol(); initsym = DtoBitCast(initsym, DtoType(ts->pointerTo())); @@ -2997,7 +3014,7 @@ DValue* StructLiteralExp::toElem(IRState* p) if (inProgressMemory) return new DVarValue(type, inProgressMemory); // make sure the struct is fully resolved - sd->codegen(Type::sir); + DtoResolveStruct(sd); // alloca a stack slot inProgressMemory = DtoRawAlloca(DtoType(type), 0, ".structliteral"); @@ -3101,13 +3118,13 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p) Logger::print("Sym: type=%s\n", sdecltype->toChars()); assert(sdecltype->ty == Tstruct); TypeStruct* ts = static_cast(sdecltype); - ts->sym->codegen(Type::sir); + DtoResolveStruct(ts->sym); return ts->sym->ir.irAggr->getDefaultInit(); } // make sure the struct is resolved - sd->codegen(Type::sir); + DtoResolveStruct(sd); std::map varInits; const size_t nexprs = elements->dim; @@ -3129,8 +3146,7 @@ llvm::Constant* ClassReferenceExp::toConstElem(IRState *p) LOG_SCOPE; ClassDeclaration* origClass = originalClass(); - - origClass->codegen(Type::sir); + DtoResolveClass(origClass); if (value->globalVar) { diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index a23aad11..9bbaceaf 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -294,22 +294,17 @@ LLValue* DtoDelegateEquals(TOK op, LLValue* lhs, LLValue* rhs) LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) { - const bool mustDefine = mustDefineSymbol(sym); - // global/static variable if (VarDeclaration* vd = sym->isVarDeclaration()) { - if (mustDefine) - { - IF_LOG Logger::println("Variable %savailable externally: %s", - (vd->availableExternally ? "" : "not "), vd->toChars()); - } + IF_LOG Logger::println("Variable %savailable externally: %s", + (vd->availableExternally ? "" : "not "), vd->toChars()); // generated by inlining semantics run - if (vd->availableExternally && mustDefine) + if (vd->availableExternally) return llvm::GlobalValue::AvailableExternallyLinkage; // template - if (needsTemplateLinkage(sym)) + if (DtoIsTemplateInstance(sym)) return templateLinkage; // Currently, we have to consider all variables, even function-local @@ -330,11 +325,8 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) } else if (FuncDeclaration* fdecl = sym->isFuncDeclaration()) { - if (mustDefine) - { - IF_LOG Logger::println("Function %savailable externally: %s", - (fdecl->availableExternally ? "" : "not "), fdecl->toChars()); - } + IF_LOG Logger::println("Function %savailable externally: %s", + (fdecl->availableExternally ? "" : "not "), fdecl->toChars()); assert(fdecl->type->ty == Tfunction); TypeFunction* ft = static_cast(fdecl->type); @@ -347,7 +339,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) // available_externally. Naked functions are turned into module-level // inline asm and are thus declaration-only as far as the LLVM IR level // is concerned. - if (fdecl->availableExternally && mustDefine && !fdecl->naked) + if (fdecl->availableExternally && !fdecl->naked) return llvm::GlobalValue::AvailableExternallyLinkage; // array operations are always template linkage @@ -357,7 +349,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) // template instances should have weak linkage // but only if there's a body, and it's not naked // otherwise we make it external - if (needsTemplateLinkage(fdecl) && fdecl->fbody && !fdecl->naked) + if (DtoIsTemplateInstance(fdecl) && fdecl->fbody && !fdecl->naked) return templateLinkage; // extern(C) functions are always external @@ -375,16 +367,14 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) // class else if (ClassDeclaration* cd = sym->isClassDeclaration()) { - if (mustDefine) - { - IF_LOG Logger::println("Class %savailable externally: %s", - (cd->availableExternally ? "" : "not "), vd->toChars()); - } + IF_LOG Logger::println("Class %savailable externally: %s", + (cd->availableExternally ? "" : "not "), vd->toChars()); + // generated by inlining semantics run - if (cd->availableExternally && mustDefine) + if (cd->availableExternally) return llvm::GlobalValue::AvailableExternallyLinkage; // template - if (needsTemplateLinkage(cd)) + if (DtoIsTemplateInstance(cd)) return templateLinkage; } else @@ -392,10 +382,8 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) llvm_unreachable("not global/function"); } - // If the function needs to be defined in the current module, check if it - // is a nested function and we can declare it as internal. - bool canInternalize = mustDefine; - + // Check if sym is a nested function and we can declare it as internal. + // // Nested naked functions and the implicitly generated __require/__ensure // functions for in/out contracts cannot be internalized. The reason // for the latter is that contract functions, despite being nested, can be @@ -403,39 +391,28 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) // interface methods (where __require/__ensure are emitted to the module // where the interface is declared, but an actual interface implementation // can be in a completely different place). - if (canInternalize) - { - if (FuncDeclaration* fd = sym->isFuncDeclaration()) - { - if ((fd->naked != 0) || - (fd->ident == Id::require) || (fd->ident == Id::ensure)) - { - canInternalize = false; - } - } - } - - // Any symbol nested in a function that cannot be inlined can't be - // referenced directly from outside that function, so we can give - // such symbols internal linkage. This holds even if nested indirectly, - // such as member functions of aggregates nested in functions. - // - // Note: This must be checked after things like template member-ness or - // symbols nested in templates would get duplicated for each module, - // breaking things like - // --- - // int counter(T)() { static int i; return i++; }" - // --- - // if instances get emitted in multiple object files because they'd use - // different instances of 'i'. - // TODO: Check if we are giving away too much inlining potential due to - // canInline being overly conservative here. - if (canInternalize) + FuncDeclaration* fd = sym->isFuncDeclaration(); + if (!fd || (!fd->naked && fd->ident != Id::require && fd->ident != Id::ensure)) { + // Any symbol nested in a function that cannot be inlined can't be + // referenced directly from outside that function, so we can give + // such symbols internal linkage. This holds even if nested indirectly, + // such as member functions of aggregates nested in functions. + // + // Note: This must be checked after things like template member-ness or + // symbols nested in templates would get duplicated for each module, + // breaking things like + // --- + // int counter(T)() { static int i; return i++; }" + // --- + // if instances get emitted in multiple object files because they'd use + // different instances of 'i'. + // TODO: Check if we are giving away too much inlining potential due to + // canInline being overly conservative here. for (Dsymbol* parent = sym->parent; parent ; parent = parent->parent) { - FuncDeclaration *fd = parent->isFuncDeclaration(); - if (fd && !fd->canInline(fd->needThis(), false, false)) + FuncDeclaration *parentFd = parent->isFuncDeclaration(); + if (parentFd && !parentFd->canInline(parentFd->needThis(), false, false)) { // We also cannot internalize nested functions which are // leaked to the outside via a templated return type, because @@ -444,8 +421,8 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) // Since we can't easily determine if this is really the case // here, just don't internalize it if the parent returns a // template at all, to be safe. - TypeFunction* tf = static_cast(fd->type); - if (!DtoIsTemplateInstance(tf->next->toDsymbol(fd->scope))) + TypeFunction* tf = static_cast(parentFd->type); + if (!DtoIsTemplateInstance(tf->next->toDsymbol(parentFd->scope))) return llvm::GlobalValue::InternalLinkage; } } @@ -468,8 +445,8 @@ static bool isAvailableExternally(Dsymbol* sym) llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym) { - if (needsTemplateLinkage(sym)) { - if (isAvailableExternally(sym) && mustDefineSymbol(sym)) + if (DtoIsTemplateInstance(sym)) { + if (isAvailableExternally(sym)) return llvm::GlobalValue::AvailableExternallyLinkage; return templateLinkage; } @@ -479,9 +456,9 @@ llvm::GlobalValue::LinkageTypes DtoInternalLinkage(Dsymbol* sym) llvm::GlobalValue::LinkageTypes DtoExternalLinkage(Dsymbol* sym) { - if (needsTemplateLinkage(sym)) + if (DtoIsTemplateInstance(sym)) return templateLinkage; - else if (isAvailableExternally(sym) && mustDefineSymbol(sym)) + else if (isAvailableExternally(sym)) return llvm::GlobalValue::AvailableExternallyLinkage; else return llvm::GlobalValue::ExternalLinkage; diff --git a/gen/typeinf.h b/gen/typeinf.h index 7a77ad5b..e2d37b6b 100644 --- a/gen/typeinf.h +++ b/gen/typeinf.h @@ -17,7 +17,6 @@ struct TypeInfoDeclaration; void DtoResolveTypeInfo(TypeInfoDeclaration* tid); -void DtoDeclareTypeInfo(TypeInfoDeclaration* tid); void DtoConstInitTypeInfo(TypeInfoDeclaration* tid); #endif diff --git a/gen/typinf.cpp b/gen/typinf.cpp index b59fffdb..561cb516 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -115,7 +115,9 @@ Expression *Type::getInternalTypeInfo(Scope *sc) Expression *Type::getTypeInfo(Scope *sc) { - //printf("Type::getTypeInfo() %p, %s\n", this, toChars()); + IF_LOG Logger::println("Type::getTypeInfo(): %s", toChars()); + LOG_SCOPE + if (!Type::typeinfo) { error(Loc(), "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch"); @@ -150,7 +152,7 @@ Expression *Type::getTypeInfo(Scope *sc) } else // if in obj generation pass { - t->vtinfo->codegen(sir); + t->vtinfo->codegen(gIR); } } } @@ -280,40 +282,8 @@ int TypeClass::builtinTypeInfo() // (wut?) ////////////////////////////////////////////////////////////////////////////// -void DtoResolveTypeInfo(TypeInfoDeclaration* tid); -void DtoDeclareTypeInfo(TypeInfoDeclaration* tid); - -void TypeInfoDeclaration::codegen(Ir*) +static void emitTypeMetadata(TypeInfoDeclaration *tid) { - DtoResolveTypeInfo(this); -} - -void DtoResolveTypeInfo(TypeInfoDeclaration* tid) -{ - if (tid->ir.resolved) return; - tid->ir.resolved = true; - - Logger::println("DtoResolveTypeInfo(%s)", tid->toChars()); - LOG_SCOPE; - - std::string mangle(tid->mangle()); - - IrGlobal* irg = new IrGlobal(tid); - irg->value = gIR->module->getGlobalVariable(mangle); - - if (!irg->value) { - if (tid->tinfo->builtinTypeInfo()) // this is a declaration of a builtin __initZ var - irg->type = Type::typeinfo->type->irtype->isClass()->getMemoryLLType(); - else - irg->type = LLStructType::create(gIR->context(), tid->toPrettyChars()); - irg->value = new llvm::GlobalVariable(*gIR->module, irg->type, true, - TYPEINFO_LINKAGE_TYPE, NULL, mangle); - } else { - irg->type = irg->value->getType()->getContainedType(0); - } - - tid->ir.irGlobal = irg; - // We don't want to generate metadata for non-concrete types (such as tuple // types, slice types, typeof(expr), etc.), void and function types (without // an indirection), as there must be a valid LLVM undef value of that type. @@ -322,13 +292,14 @@ void DtoResolveTypeInfo(TypeInfoDeclaration* tid) Type* t = tid->tinfo->toBasetype(); if (t->ty < Terror && t->ty != Tvoid && t->ty != Tfunction && t->ty != Tident) { // Add some metadata for use by optimization passes. - std::string metaname = std::string(TD_PREFIX) + mangle; + std::string metaname(TD_PREFIX); + metaname += tid->mangle(); llvm::NamedMDNode* meta = gIR->module->getNamedMetadata(metaname); if (!meta) { // Construct the fields MDNodeField* mdVals[TD_NumFields]; - mdVals[TD_TypeInfo] = llvm::cast(irg->value); + mdVals[TD_TypeInfo] = llvm::cast(tid->ir.irGlobal->value); mdVals[TD_Type] = llvm::UndefValue::get(DtoType(tid->tinfo)); // Construct the metadata and insert it into the module. @@ -337,39 +308,59 @@ void DtoResolveTypeInfo(TypeInfoDeclaration* tid) llvm::makeArrayRef(mdVals, TD_NumFields))); } } - - DtoDeclareTypeInfo(tid); } -void DtoDeclareTypeInfo(TypeInfoDeclaration* tid) +void DtoResolveTypeInfo(TypeInfoDeclaration* tid) { - DtoResolveTypeInfo(tid); + if (tid->ir.resolved) return; + tid->ir.resolved = true; - if (tid->ir.declared) return; - tid->ir.declared = true; + // TypeInfo instances (except ClassInfo ones) are always emitted as weak + // symbols when they are used. + tid->codegen(gIR); +} - Logger::println("DtoDeclareTypeInfo(%s)", tid->toChars()); +void TypeInfoDeclaration::codegen(IRState* p) +{ + Logger::println("TypeInfoDeclaration::codegen(%s)", toPrettyChars()); LOG_SCOPE; + if (ir.defined) return; + ir.defined = true; + + std::string mangled(mangle()); if (Logger::enabled()) { - std::string mangled(tid->mangle()); - Logger::println("type = '%s'", tid->tinfo->toChars()); + Logger::println("type = '%s'", tinfo->toChars()); Logger::println("typeinfo mangle: %s", mangled.c_str()); } - IrGlobal* irg = tid->ir.irGlobal; - assert(irg->value != NULL); + IrGlobal* irg = new IrGlobal(this); + ir.irGlobal = irg; + irg->value = gIR->module->getGlobalVariable(mangled); + if (irg->value) { + irg->type = irg->value->getType()->getContainedType(0); + assert(irg->type->isStructTy()); + } else { + if (tinfo->builtinTypeInfo()) // this is a declaration of a builtin __initZ var + irg->type = Type::typeinfo->type->irtype->isClass()->getMemoryLLType(); + else + irg->type = LLStructType::create(gIR->context(), toPrettyChars()); + irg->value = new llvm::GlobalVariable(*gIR->module, irg->type, true, + llvm::GlobalValue::ExternalLinkage, NULL, mangled); + } + + emitTypeMetadata(this); // this is a declaration of a builtin __initZ var - if (tid->tinfo->builtinTypeInfo()) { + if (tinfo->builtinTypeInfo()) { LLGlobalVariable* g = isaGlobalVar(irg->value); g->setLinkage(llvm::GlobalValue::ExternalLinkage); return; } // define custom typedef - tid->llvmDefine(); + llvmDefine(); } /* ========================================================================= */ @@ -611,7 +602,7 @@ void TypeInfoStructDeclaration::llvmDefine() fatal(); } - sd->codegen(Type::sir); + DtoResolveStruct(sd); IrAggr* iraggr = sd->ir.irAggr; RTTIBuilder b(Type::typeinfostruct); @@ -737,20 +728,31 @@ void TypeInfoStructDeclaration::llvmDefine() /* ========================================================================= */ -void TypeInfoClassDeclaration::codegen(Ir*i) +void TypeInfoClassDeclaration::codegen(IRState *p) { - - IrGlobal* irg = new IrGlobal(this); + // For classes, the TypeInfo is in fact a ClassInfo instance and emitted + // as a __ClassZ symbol. For interfaces, the __InterfaceZ symbol is + // referenced as "info" member in a (normal) TypeInfo_Interface instance. + IrGlobal *irg = new IrGlobal(this); ir.irGlobal = irg; + assert(tinfo->ty == Tclass); TypeClass *tc = static_cast(tinfo); - tc->sym->codegen(Type::sir); // make sure class is resolved + DtoResolveClass(tc->sym); + irg->value = tc->sym->ir.irAggr->getClassInfoSymbol(); + irg->type = irg->value->getType()->getContainedType(0); + + if (!tc->sym->isInterfaceDeclaration()) + { + emitTypeMetadata(this); + } } void TypeInfoClassDeclaration::llvmDefine() { - llvm_unreachable("TypeInfoClassDeclaration should not be called for D2"); + llvm_unreachable("TypeInfoClassDeclaration::llvmDefine() should not be called, " + "as a custom Dsymbol::codegen() override is used"); } /* ========================================================================= */ @@ -763,7 +765,7 @@ void TypeInfoInterfaceDeclaration::llvmDefine() // make sure interface is resolved assert(tinfo->ty == Tclass); TypeClass *tc = static_cast(tinfo); - tc->sym->codegen(Type::sir); + DtoResolveClass(tc->sym); RTTIBuilder b(Type::typeinfointerface); diff --git a/ir/ir.cpp b/ir/ir.cpp deleted file mode 100644 index 156c209c..00000000 --- a/ir/ir.cpp +++ /dev/null @@ -1,64 +0,0 @@ -//===-- ir.cpp ------------------------------------------------------------===// -// -// LDC – the LLVM D compiler -// -// This file is distributed under the BSD-style LDC license. See the LICENSE -// file for details. -// -//===----------------------------------------------------------------------===// - -#if LDC_LLVM_VER >= 303 -#include "llvm/IR/DataLayout.h" -#elif LDC_LLVM_VER == 302 -#include "llvm/DataLayout.h" -#else -#include "llvm/Target/TargetData.h" -#endif - -#include "gen/irstate.h" -#include "gen/tollvm.h" -#include "gen/functions.h" - -#include "ir/ir.h" -#include "ir/irfunction.h" - - -unsigned GetTypeAlignment(Type* t) -{ - return gDataLayout->getABITypeAlignment(DtoType(t)); -} - -unsigned GetPointerSize() -{ - return gDataLayout->getPointerSize(ADDRESS_SPACE); -} - -unsigned GetTypeStoreSize(Type* t) -{ - return gDataLayout->getTypeStoreSize(DtoType(t)); -} - -unsigned GetTypeAllocSize(Type* t) -{ - return gDataLayout->getTypeAllocSize(DtoType(t)); -} - -Ir::Ir() -: irs(NULL) -{ -} - -void Ir::addFunctionBody(IrFunction * f) -{ - functionbodies.push_back(f); -} - -void Ir::emitFunctionBodies() -{ - while (!functionbodies.empty()) - { - IrFunction* irf = functionbodies.front(); - functionbodies.pop_front(); - DtoDefineFunction(irf->decl); - } -} diff --git a/ir/ir.h b/ir/ir.h deleted file mode 100644 index fa20b998..00000000 --- a/ir/ir.h +++ /dev/null @@ -1,43 +0,0 @@ -//===-- ir/ir.h - Base definitions for codegen metadata ---------*- C++ -*-===// -// -// LDC – the LLVM D compiler -// -// This file is distributed under the BSD-style LDC license. See the LICENSE -// file for details. -// -//===----------------------------------------------------------------------===// -// -// Declares the base class for all codegen info classes and the top-level Ir -// class. -// -//===----------------------------------------------------------------------===// - - -#ifndef LDC_IR_IR_H -#define LDC_IR_IR_H - -#include "root.h" -#include "ir/irforw.h" -#include - -struct IRState; -struct IrFunction; - -class Ir -{ -public: - Ir(); - - void setState(IRState* p) { irs = p; } - IRState* getState() { return irs; } - - void addFunctionBody(IrFunction* f); - void emitFunctionBodies(); - -private: - IRState* irs; - - std::deque functionbodies; -}; - -#endif diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp index 35733b79..2f457b1d 100644 --- a/ir/iraggr.cpp +++ b/ir/iraggr.cpp @@ -61,10 +61,8 @@ LLGlobalVariable * IrAggr::getInitSymbol() initname.append(aggrdecl->mangle()); initname.append("6__initZ"); - llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl); - init = getOrCreateGlobal(aggrdecl->loc, - *gIR->module, init_type, true, _linkage, NULL, initname); + *gIR->module, init_type, true, llvm::GlobalValue::ExternalLinkage, NULL, initname); // set alignment init->setAlignment(type->alignsize()); @@ -207,14 +205,19 @@ LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init) { return DtoConstInitializer(init->loc, vd->type, init); } - else if (vd->init) + + if (vd->init) { return DtoConstInitializer(vd->init->loc, vd->type, vd->init); } - else + + if (vd->type->size(vd->loc) == 0) { - return DtoConstExpInit(vd->loc, vd->type, vd->type->defaultInit(vd->loc)); + // We need to be able to handle void[0] struct members even if void has + // no default initializer. + return llvm::ConstantPointerNull::get(getPtrToType(DtoType(vd->type))); } + return DtoConstExpInit(vd->loc, vd->type, vd->type->defaultInit(vd->loc)); } // return a constant array of type arrTypeD initialized with a constant value, or that constant value diff --git a/ir/iraggr.h b/ir/iraggr.h index 04621c28..99d88d67 100644 --- a/ir/iraggr.h +++ b/ir/iraggr.h @@ -15,7 +15,6 @@ #ifndef LDC_IR_IRAGGR_H #define LDC_IR_IRAGGR_H -#include "ir/ir.h" #include "llvm/ADT/SmallVector.h" #include #include @@ -57,9 +56,9 @@ struct IrAggr /// Builds the __vtblZ initializer constant lazily. LLConstant* getVtblInit(); - /// Create the __ClassZ symbol lazily. + /// Create the __ClassZ/__InterfaceZ symbol lazily. LLGlobalVariable* getClassInfoSymbol(); - /// Builds the __ClassZ initializer constant lazily. + /// Builds the __ClassZ/__InterfaceZ initializer constant lazily. LLConstant* getClassInfoInit(); /// Create the __interfaceInfos symbol lazily. diff --git a/ir/irclass.cpp b/ir/irclass.cpp index c651397e..a9618298 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -53,12 +53,10 @@ LLGlobalVariable * IrAggr::getVtblSymbol() initname.append(aggrdecl->mangle()); initname.append("6__vtblZ"); - llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl); - LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl(); vtbl = getOrCreateGlobal(aggrdecl->loc, - *gIR->module, vtblTy, true, _linkage, NULL, initname); + *gIR->module, vtblTy, true, llvm::GlobalValue::ExternalLinkage, NULL, initname); return vtbl; } @@ -79,8 +77,9 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol() else initname.append("7__ClassZ"); - llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl); - + // The type is also ClassInfo for interfaces – the actual TypeInfo for them + // is a TypeInfo_Interface instance that references __ClassZ in its "base" + // member. ClassDeclaration* cinfo = ClassDeclaration::classinfo; DtoType(cinfo->type); IrTypeClass* tc = stripModifiers(cinfo->type)->irtype->isClass(); @@ -88,7 +87,8 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol() // classinfos cannot be constants since they're used as locks for synchronized classInfo = getOrCreateGlobal(aggrdecl->loc, - *gIR->module, tc->getMemoryLLType(), false, _linkage, NULL, initname); + *gIR->module, tc->getMemoryLLType(), false, + llvm::GlobalValue::ExternalLinkage, NULL, initname); // Generate some metadata on this ClassInfo if it's for a class. ClassDeclaration* classdecl = aggrdecl->isClassDeclaration(); @@ -138,9 +138,8 @@ LLGlobalVariable * IrAggr::getInterfaceArraySymbol() name.append(cd->mangle()); name.append("16__interfaceInfosZ"); - llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl); classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module, - array_type, true, _linkage, NULL, name); + array_type, true, llvm::GlobalValue::ExternalLinkage, NULL, name); return classInterfacesArray; } @@ -182,7 +181,7 @@ LLConstant * IrAggr::getVtblInit() } else { - fd->codegen(Type::sir); + DtoResolveFunction(fd); assert(fd->ir.irFunc && "invalid vtbl function"); c = fd->ir.irFunc->func; if (cd->isFuncHidden(fd)) @@ -320,7 +319,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance assert((!fd->isAbstract() || fd->fbody) && "null symbol in interface implementation vtable"); - fd->codegen(Type::sir); + DtoResolveFunction(fd); assert(fd->ir.irFunc && "invalid vtbl function"); LLFunction *fn = fd->ir.irFunc->func; @@ -380,9 +379,6 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance // build the vtbl constant llvm::Constant* vtbl_constant = LLConstantStruct::getAnon(gIR->context(), constants, false); - // create the global variable to hold it - llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl); - std::string mangle("_D"); mangle.append(cd->mangle()); mangle.append("11__interface"); @@ -393,7 +389,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance *gIR->module, vtbl_constant->getType(), true, - _linkage, + llvm::GlobalValue::ExternalLinkage, vtbl_constant, mangle ); diff --git a/ir/irdsymbol.cpp b/ir/irdsymbol.cpp index d16565e6..9a2dded0 100644 --- a/ir/irdsymbol.cpp +++ b/ir/irdsymbol.cpp @@ -9,7 +9,6 @@ #include "gen/llvm.h" #include "gen/logger.h" -#include "ir/ir.h" #include "ir/irdsymbol.h" #include "ir/irvar.h" diff --git a/ir/irdsymbol.h b/ir/irdsymbol.h index 546b7891..62131628 100644 --- a/ir/irdsymbol.h +++ b/ir/irdsymbol.h @@ -25,6 +25,7 @@ struct IrParameter; struct IrField; struct IrVar; struct Dsymbol; +struct Module; namespace llvm { class Value; diff --git a/ir/irfunction.h b/ir/irfunction.h index 7bfa1423..55727ef4 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -17,7 +17,6 @@ #define LDC_IR_IRFUNCTION_H #include "gen/llvm.h" -#include "ir/ir.h" #include "ir/irlandingpad.h" #include #include diff --git a/ir/irfuncty.h b/ir/irfuncty.h index 43a468fa..66efc566 100644 --- a/ir/irfuncty.h +++ b/ir/irfuncty.h @@ -16,7 +16,6 @@ #ifndef LDC_IR_IRFUNCTY_H #define LDC_IR_IRFUNCTY_H -#include "ir/ir.h" #include "llvm/ADT/SmallVector.h" #if LDC_LLVM_VER >= 303 #include "llvm/IR/Attributes.h" @@ -27,6 +26,7 @@ #include class DValue; +struct Type; struct ABIRewrite; namespace llvm { class Type; diff --git a/ir/irlandingpad.cpp b/ir/irlandingpad.cpp index 69a1e96f..ac3f6077 100644 --- a/ir/irlandingpad.cpp +++ b/ir/irlandingpad.cpp @@ -34,7 +34,7 @@ IRLandingPadCatchInfo::IRLandingPadCatchInfo(Catch* catchstmt_, llvm::BasicBlock assert(catchStmt->type); catchType = catchStmt->type->toBasetype()->isClassHandle(); assert(catchType); - catchType->codegen(Type::sir); + DtoResolveClass(catchType); if (catchStmt->var) { if (!catchStmt->var->nestedrefs.dim) { diff --git a/ir/irlandingpad.h b/ir/irlandingpad.h index c70a1ded..b1116ea8 100644 --- a/ir/irlandingpad.h +++ b/ir/irlandingpad.h @@ -16,7 +16,6 @@ #define LDC_IR_IRLANDINGPADINFO_H #include "statement.h" -#include "ir/ir.h" #include #include diff --git a/ir/irmodule.h b/ir/irmodule.h index e69545e2..bf5ee250 100644 --- a/ir/irmodule.h +++ b/ir/irmodule.h @@ -15,9 +15,11 @@ #ifndef LDC_IR_IRMODULE_H #define LDC_IR_IRMODULE_H -#include "ir/ir.h" - struct Module; +namespace llvm +{ + class GlobalVariable; +} struct IrModule { @@ -26,7 +28,7 @@ struct IrModule Module* M; - LLGlobalVariable* fileName; + llvm::GlobalVariable* fileName; }; #endif diff --git a/ir/irtype.h b/ir/irtype.h index 9fdd203f..6b388468 100644 --- a/ir/irtype.h +++ b/ir/irtype.h @@ -81,7 +81,7 @@ public: /// virtual IrTypeStruct* isStruct() { return 0; } /// - IrTypeVector* isVector() { return 0; } + virtual IrTypeVector* isVector() { return 0; } /// Type* getDType() { return dtype; } diff --git a/ir/irvar.h b/ir/irvar.h index 50ab184a..d4b00663 100644 --- a/ir/irvar.h +++ b/ir/irvar.h @@ -15,7 +15,6 @@ #ifndef LDC_IR_IRVAR_H #define LDC_IR_IRVAR_H -#include "ir/ir.h" #if LDC_LLVM_VER >= 303 #include "llvm/IR/Type.h" #else @@ -23,6 +22,7 @@ #endif struct IrFuncTyArg; +struct VarDeclaration; struct IrVar {