From 3d9b70c7a621aa1068bb2292c0f909220b33a40e Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Wed, 9 Oct 2013 19:28:09 +0200 Subject: [PATCH 01/12] Mention TypeInfo emission in debug log. --- gen/llvmhelpers.cpp | 3 +++ gen/typinf.cpp | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 0fdd54af..0b055a82 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1428,6 +1428,9 @@ 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; diff --git a/gen/typinf.cpp b/gen/typinf.cpp index b59fffdb..5df51507 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"); From 7dff0bbe4b4259369b6c167f0d29592fce179e2f Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 10 Oct 2013 18:26:28 +0200 Subject: [PATCH 02/12] Fix IrType::isVector (so far unused anyway). --- ir/irtype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; } From e1abb01e5564f516e04e34ac87a84e8e6e54f891 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 12 Oct 2013 23:14:07 +0200 Subject: [PATCH 03/12] Remove superfluous Dsymbol::codegen overload. --- dmd2/declaration.h | 5 ----- gen/declarations.cpp | 9 +-------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/dmd2/declaration.h b/dmd2/declaration.h index 66ce7ab5..8b73bad9 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 }; /**************************************************************/ diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 5357baac..aea69157 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -27,14 +27,7 @@ void Dsymbol::codegen(Ir*) { - Logger::println("Ignoring Dsymbol::codegen for %s", toChars()); -} - -/* ================================================================== */ - -void Declaration::codegen(Ir*) -{ - Logger::println("Ignoring Declaration::codegen for %s", toChars()); + Logger::println("Ignoring Dsymbol::codegen for %s", toPrettyChars()); } /* ================================================================== */ From b556ad9996b3dd2ade51639d2442fa54164586be Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 12 Oct 2013 23:14:48 +0200 Subject: [PATCH 04/12] Don't log the uninteresting case of DtoConstExpInit. --- gen/llvmhelpers.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 0b055a82..aec891d7 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1374,7 +1374,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; } From 787c147986913f74fc02546dde068fe421c8cf05 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 13 Oct 2013 04:31:41 +0200 Subject: [PATCH 05/12] Use Module::members -> Dsymbol::codegen to define symbols. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fundamentally changes the way symbol emission in LDC works: Previously, whenever a declaration was used in some way, the compiler would check whether it actually needs to be defined in the currently processed module, based only on the symbol itself. This lack of contextual information proved to be a major problem in correctly handling emission of templates (see e.g. #454). Now, the DtoResolve…() family of functions and similar only ever declare the symbols, and definition is handled by doing a single pass over Module::members for the root module. This is the same strategy that DMD uses as well, which should also reduce the maintainance burden down the road (which is important as during the last few releases, there was pretty much always a symbol emission related problem slowing us down). Our old approach might have been a bit better tuned w.r.t. avoiding emission of unneeded template instances, but 2.064 will bring improvements here (DMD: FuncDeclaration::toObjFile). Barring such issues, the change shoud also marginally improve compile times because of declarations no longer being emitted when they are not needed. In the future, we should also consider refactoring the code so that it no longer directly accesses Dsymbol::ir but uses wrapper functions that ensure that the appropriate DtoResolve…() function has been called. GitHub: Fixes #454. --- dmd2/declaration.h | 8 +- dmd2/func.c | 4 - gen/arrays.cpp | 8 -- gen/classes.cpp | 85 +++++------------- gen/declarations.cpp | 181 ++++++++++++++++++++++++++------------- gen/functions.cpp | 91 +++++++++----------- gen/llvmhelpers.cpp | 200 ++++++++++++++++++++----------------------- gen/llvmhelpers.h | 16 ++-- gen/module.cpp | 11 +-- gen/naked.cpp | 1 + gen/rttibuilder.cpp | 9 +- gen/structs.cpp | 26 ------ gen/toir.cpp | 50 +++++++---- gen/tollvm.cpp | 103 +++++++++------------- gen/typeinf.h | 1 - gen/typinf.cpp | 110 ++++++++++++------------ ir/ir.cpp | 15 ---- ir/ir.h | 3 - ir/iraggr.cpp | 4 +- ir/iraggr.h | 4 +- ir/irclass.cpp | 24 +++--- ir/irlandingpad.cpp | 2 +- 22 files changed, 439 insertions(+), 517 deletions(-) diff --git a/dmd2/declaration.h b/dmd2/declaration.h index 8b73bad9..a503a20d 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -478,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(Ir* p); void llvmDefine(); #endif }; @@ -814,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 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/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..8dc9a9e6 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); + DtoResolveDsymbol(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); + DtoResolveDsymbol(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); + DtoResolveDsymbol(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 aea69157..e9bff5c8 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -14,11 +14,14 @@ #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 "gen/utils.h" #include "ir/ir.h" #include "ir/irtype.h" #include "ir/irvar.h" @@ -27,53 +30,129 @@ void Dsymbol::codegen(Ir*) { - Logger::println("Ignoring Dsymbol::codegen for %s", toPrettyChars()); + IF_LOG Logger::println("Ignoring Dsymbol::codegen for %s", toPrettyChars()); } /* ================================================================== */ -void InterfaceDeclaration::codegen(Ir*) +void InterfaceDeclaration::codegen(Ir* p) { + IF_LOG Logger::println("InterfaceDeclaration::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); + + // 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(Ir* 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(Ir* 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) { - 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); @@ -92,14 +171,19 @@ void TupleDeclaration::codegen(Ir* p) void VarDeclaration::codegen(Ir* 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) { @@ -108,10 +192,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)) { @@ -122,37 +202,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); @@ -161,10 +218,12 @@ void VarDeclaration::codegen(Ir* p) if (initVal->getType() != gvar->getType()->getElementType()) { llvm::GlobalVariable* newGvar = getOrCreateGlobal(loc, - *gIR->module, initVal->getType(), isLLConst, llLinkage, 0, + *gIR->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 = @@ -180,17 +239,12 @@ 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); } - // 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. @@ -206,9 +260,12 @@ void VarDeclaration::codegen(Ir* p) void TypedefDeclaration::codegen(Ir*) { - 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; @@ -222,7 +279,7 @@ void TypedefDeclaration::codegen(Ir*) void EnumDeclaration::codegen(Ir*) { - 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"); @@ -237,7 +294,7 @@ void FuncDeclaration::codegen(Ir* p) // don't touch function aliases, they don't contribute any new symbols if (!isFuncAliasDeclaration()) { - DtoResolveDsymbol(this); + DtoDefineFunction(this); } } @@ -245,18 +302,17 @@ void FuncDeclaration::codegen(Ir* p) void TemplateInstance::codegen(Ir* 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); } } } @@ -265,14 +321,17 @@ void TemplateInstance::codegen(Ir* p) void TemplateMixin::codegen(Ir* 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); } } } diff --git a/gen/functions.cpp b/gen/functions.cpp index 7e0122a1..74bae086 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) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index aec891d7..14cf1f8d 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -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'; } } @@ -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()) @@ -1502,98 +1580,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(); @@ -1734,7 +1720,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); @@ -1867,14 +1853,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(); @@ -1923,7 +1909,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); + DtoResolveDsymbol(vd); assert(vd->ir.isSet() && "Variable not resolved."); @@ -1952,19 +1938,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()) @@ -1975,7 +1957,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())); @@ -2011,7 +1993,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; @@ -2019,7 +2001,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..e894912b 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -398,9 +398,6 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) dsym->codegen(sir); } - // emit function bodies - sir->emitFunctionBodies(); - // for singleobj-compilation, fully emit all seen template instances if (global.params.singleObj) { @@ -410,9 +407,6 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) for (it = ir.seenTemplateInstances.begin(); it != end; ++it) (*it)->codegen(sir); ir.seenTemplateInstances.clear(); - - // emit any newly added function bodies - sir->emitFunctionBodies(); } } @@ -532,8 +526,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 +632,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..7850dc6e 100644 --- a/gen/naked.cpp +++ b/gen/naked.cpp @@ -85,6 +85,7 @@ void ExpStatement::toNakedIR(IRState *p) // enum decls should always be safe // make sure the symbols gets processed + // TODO: codegen() here is likely incorrect d->declaration->codegen(Type::sir); } diff --git a/gen/rttibuilder.cpp b/gen/rttibuilder.cpp index c1711d70..1a2cc847 100644 --- a/gen/rttibuilder.cpp +++ b/gen/rttibuilder.cpp @@ -20,8 +20,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 +135,7 @@ void RTTIBuilder::push_funcptr(FuncDeclaration* fd, Type* castto) { if (fd) { - fd->codegen(Type::sir); + DtoResolveDsymbol(fd); LLConstant* F = fd->ir.irFunc->func; if (castto) F = DtoBitCast(F, DtoType(castto)); @@ -177,7 +176,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/toir.cpp b/gen/toir.cpp index 2f794e13..2c613612 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 @@ -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); + DtoResolveDsymbol(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); + DtoResolveDsymbol(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(Type::sir); + } + } + castfptr = func->ir.irFunc->func; } @@ -2785,6 +2798,8 @@ DValue* FuncExp::toElem(IRState* p) if (fd->isNested()) Logger::println("nested"); Logger::println("kind = %s", fd->kind()); + // We need to actually codegen the function here, as literals are not added + // to the module member list. fd->codegen(Type::sir); assert(fd->ir.irFunc->func); @@ -2852,6 +2867,8 @@ LLConstant* FuncExp::toConstElem(IRState* p) return 0; } + // We need to actually codegen the function here, as literals are not added + // to the module member list. fd->codegen(Type::sir); assert(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 5df51507..bb99c1ce 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -282,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. @@ -324,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. @@ -339,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(Type::sir); +} - Logger::println("DtoDeclareTypeInfo(%s)", tid->toChars()); +void TypeInfoDeclaration::codegen(Ir*) +{ + 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(); } /* ========================================================================= */ @@ -613,7 +602,7 @@ void TypeInfoStructDeclaration::llvmDefine() fatal(); } - sd->codegen(Type::sir); + DtoResolveStruct(sd); IrAggr* iraggr = sd->ir.irAggr; RTTIBuilder b(Type::typeinfostruct); @@ -739,20 +728,31 @@ void TypeInfoStructDeclaration::llvmDefine() /* ========================================================================= */ -void TypeInfoClassDeclaration::codegen(Ir*i) +void TypeInfoClassDeclaration::codegen(Ir* 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"); } /* ========================================================================= */ @@ -765,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 index 156c209c..8cf64d92 100644 --- a/ir/ir.cpp +++ b/ir/ir.cpp @@ -47,18 +47,3 @@ 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 index fa20b998..505b23de 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -31,9 +31,6 @@ public: void setState(IRState* p) { irs = p; } IRState* getState() { return irs; } - void addFunctionBody(IrFunction* f); - void emitFunctionBodies(); - private: IRState* irs; diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp index 35733b79..a065df66 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()); diff --git a/ir/iraggr.h b/ir/iraggr.h index 04621c28..87e53764 100644 --- a/ir/iraggr.h +++ b/ir/iraggr.h @@ -57,9 +57,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/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) { From 8ead24a2bb2e6ca64ca3e15cadc356d1f5c3cca5 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 13 Oct 2013 05:48:27 +0200 Subject: [PATCH 06/12] Handle typeof(null) -> Object conversion. Not sure why this wasn't triggered by the test suite before. --- gen/llvmhelpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 14cf1f8d..a33b16ce 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); } From 48b7710d22b8c69cd7254e964008dd61ed462e18 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 13 Oct 2013 05:49:26 +0200 Subject: [PATCH 07/12] More robust way of handling static array single element initialization. Fixes a std.traits test where there would be a mismatch in const/shared qualifiers on the element type of a dynamic array initializer. --- gen/llvmhelpers.cpp | 42 ++++++------------------------------------ 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index a33b16ce..0d9677f1 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1393,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)", @@ -1470,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) From 4fee629c4d16cea1e663cde53392073b6d7cb85d Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 13 Oct 2013 06:09:38 +0200 Subject: [PATCH 08/12] Prefer more specific functions to DtoResolveDsymbol. The remaining ones should also be easy to remove with a closer look at the situation. Ideally, we would get rid of all of them at some point and use safe wrapper functions for accessing the IrDsymbol associated with a given declaration (which would emit the declarations on the fly if not already present). --- gen/classes.cpp | 6 +++--- gen/declarations.cpp | 2 +- gen/functions.cpp | 2 +- gen/llvmhelpers.cpp | 2 +- gen/rttibuilder.cpp | 3 ++- gen/toir.cpp | 6 +++--- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/gen/classes.cpp b/gen/classes.cpp index 8dc9a9e6..2e8e13b6 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -98,7 +98,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) // custom allocator else if (newexp->allocator) { - DtoResolveDsymbol(newexp->allocator); + 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"); @@ -139,7 +139,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) { Logger::println("Calling constructor"); assert(newexp->arguments != NULL); - DtoResolveDsymbol(newexp->member); + DtoResolveFunction(newexp->member); DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem); return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments); } @@ -578,7 +578,7 @@ static LLConstant* build_class_dtor(ClassDeclaration* cd) if (!dtor) return getNullPtr(getVoidPtrType()); - DtoResolveDsymbol(dtor); + 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 e9bff5c8..87faaf59 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -50,7 +50,7 @@ void InterfaceDeclaration::codegen(Ir* p) if (members && symtab) { - DtoResolveDsymbol(this); + DtoResolveClass(this); // Emit any members (e.g. final functions). for (ArrayIter it(members); !it.done(); it.next()) diff --git a/gen/functions.cpp b/gen/functions.cpp index 74bae086..57d4fb78 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -1178,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 0d9677f1..de034092 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1879,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) - DtoResolveDsymbol(vd); + DtoResolveVariable(vd); assert(vd->ir.isSet() && "Variable not resolved."); diff --git a/gen/rttibuilder.cpp b/gen/rttibuilder.cpp index 1a2cc847..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" @@ -135,7 +136,7 @@ void RTTIBuilder::push_funcptr(FuncDeclaration* fd, Type* castto) { if (fd) { - DtoResolveDsymbol(fd); + DtoResolveFunction(fd); LLConstant* F = fd->ir.irFunc->func; if (castto) F = DtoBitCast(F, DtoType(castto)); diff --git a/gen/toir.cpp b/gen/toir.cpp index 2c613612..6106dff2 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -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 @@ -2122,7 +2122,7 @@ DValue* NewExp::toElem(IRState* p) if (allocator) { // custom allocator - DtoResolveDsymbol(allocator); + 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"); @@ -2149,7 +2149,7 @@ DValue* NewExp::toElem(IRState* p) { Logger::println("Calling constructor"); assert(arguments != NULL); - DtoResolveDsymbol(member); + DtoResolveFunction(member); DFuncValue dfn(member, member->ir.irFunc->func, mem); DtoCallFunction(loc, ts, &dfn, arguments); } From 857d37636e107baef7fb29451881293388845161 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 13 Oct 2013 06:10:03 +0200 Subject: [PATCH 09/12] Handle void[0] struct/class members. This was also broken before the symbol emission changes; we just accidentally managed to avoid the only occurence in the standard library tests. --- ir/iraggr.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp index a065df66..2f457b1d 100644 --- a/ir/iraggr.cpp +++ b/ir/iraggr.cpp @@ -205,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 From c6cf35a0120746d64a5b9f4ecbd97be0e8c2fe51 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 13 Oct 2013 19:20:37 +0200 Subject: [PATCH 10/12] Remove unused DMD IRState implementations. --- dmd2/irstate.c | 202 ------------------------------------------------- dmd2/irstate.h | 64 ---------------- 2 files changed, 266 deletions(-) delete mode 100644 dmd2/irstate.c delete mode 100644 dmd2/irstate.h 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 */ From 1242be25d0e3cc3d639f3d8b2e4cc685ba4b57e1 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 13 Oct 2013 19:44:29 +0200 Subject: [PATCH 11/12] Remove unused, empty Ir type. The codegen parameter was changed to IRState instead of removing it to set the stage for an eventual eradication of the gIR global. --- dmd2/aggregate.h | 6 +++--- dmd2/attrib.h | 4 ++-- dmd2/declaration.h | 12 +++++------ dmd2/dsymbol.h | 4 ++-- dmd2/enum.h | 2 +- dmd2/module.h | 3 +-- dmd2/mtype.c | 11 ---------- dmd2/mtype.h | 6 ------ dmd2/template.h | 4 ++-- driver/main.cpp | 7 ++----- gen/declarations.cpp | 27 ++++++++++++------------ gen/llvmhelpers.cpp | 10 ++++----- gen/module.cpp | 10 +++------ gen/naked.cpp | 2 +- gen/target.cpp | 18 ++++++++-------- gen/toir.cpp | 6 +++--- gen/typinf.cpp | 8 ++++---- ir/ir.cpp | 49 -------------------------------------------- ir/ir.h | 40 ------------------------------------ ir/iraggr.h | 1 - ir/irdsymbol.cpp | 1 - ir/irdsymbol.h | 1 + ir/irfunction.h | 1 - ir/irfuncty.h | 2 +- ir/irlandingpad.h | 1 - ir/irmodule.h | 8 +++++--- ir/irvar.h | 2 +- 27 files changed, 64 insertions(+), 182 deletions(-) delete mode 100644 ir/ir.cpp delete mode 100644 ir/ir.h 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 a503a20d..ee57cdfd 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -211,7 +211,7 @@ struct TupleDeclaration : Declaration #if IN_LLVM void semantic3(Scope *sc); /// Codegen traversal - void codegen(Ir* ir); + void codegen(IRState* ir); #endif }; @@ -251,7 +251,7 @@ struct TypedefDeclaration : Declaration #if IN_LLVM /// Codegen traversal - void codegen(Ir* ir); + void codegen(IRState* ir); #endif }; @@ -357,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. @@ -450,7 +450,7 @@ struct TypeInfoDeclaration : VarDeclaration #if IN_LLVM /// Codegen traversal - void codegen(Ir* ir); + void codegen(IRState* ir); virtual void llvmDefine(); #endif }; @@ -482,7 +482,7 @@ struct TypeInfoClassDeclaration : TypeInfoDeclaration // __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(Ir* p); + void codegen(IRState* ir); void llvmDefine(); #endif }; @@ -919,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/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/declarations.cpp b/gen/declarations.cpp index 87faaf59..64de6ec8 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -22,20 +22,19 @@ #include "gen/logger.h" #include "gen/tollvm.h" #include "gen/utils.h" -#include "ir/ir.h" #include "ir/irtype.h" #include "ir/irvar.h" /* ================================================================== */ -void Dsymbol::codegen(Ir*) +void Dsymbol::codegen(IRState *) { IF_LOG Logger::println("Ignoring Dsymbol::codegen for %s", toPrettyChars()); } /* ================================================================== */ -void InterfaceDeclaration::codegen(Ir* p) +void InterfaceDeclaration::codegen(IRState *p) { IF_LOG Logger::println("InterfaceDeclaration::codegen: '%s'", toPrettyChars()); LOG_SCOPE @@ -70,7 +69,7 @@ void InterfaceDeclaration::codegen(Ir* p) /* ================================================================== */ -void StructDeclaration::codegen(Ir* p) +void StructDeclaration::codegen(IRState *p) { IF_LOG Logger::println("StructDeclaration::codegen: '%s'", toPrettyChars()); LOG_SCOPE @@ -104,7 +103,7 @@ void StructDeclaration::codegen(Ir* p) /* ================================================================== */ -void ClassDeclaration::codegen(Ir* p) +void ClassDeclaration::codegen(IRState *p) { IF_LOG Logger::println("ClassDeclaration::codegen: '%s'", toPrettyChars()); LOG_SCOPE @@ -146,7 +145,7 @@ void ClassDeclaration::codegen(Ir* p) /* ================================================================== */ -void TupleDeclaration::codegen(Ir* p) +void TupleDeclaration::codegen(IRState *p) { IF_LOG Logger::println("TupleDeclaration::codegen(): '%s'", toPrettyChars()); LOG_SCOPE @@ -169,7 +168,7 @@ void TupleDeclaration::codegen(Ir* p) /* ================================================================== */ -void VarDeclaration::codegen(Ir* p) +void VarDeclaration::codegen(IRState *p) { IF_LOG Logger::println("VarDeclaration::codegen(): '%s'", toPrettyChars()); LOG_SCOPE; @@ -258,7 +257,7 @@ void VarDeclaration::codegen(Ir* p) /* ================================================================== */ -void TypedefDeclaration::codegen(Ir*) +void TypedefDeclaration::codegen(IRState *) { IF_LOG Logger::println("TypedefDeclaration::codegen: '%s'", toPrettyChars()); LOG_SCOPE; @@ -277,7 +276,7 @@ void TypedefDeclaration::codegen(Ir*) /* ================================================================== */ -void EnumDeclaration::codegen(Ir*) +void EnumDeclaration::codegen(IRState *) { IF_LOG Logger::println("Ignoring EnumDeclaration::codegen: '%s'", toPrettyChars()); @@ -289,7 +288,7 @@ 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()) @@ -300,7 +299,7 @@ void FuncDeclaration::codegen(Ir* p) /* ================================================================== */ -void TemplateInstance::codegen(Ir* p) +void TemplateInstance::codegen(IRState *p) { IF_LOG Logger::println("TemplateInstance::codegen: '%s'", toPrettyChars()); LOG_SCOPE @@ -319,7 +318,7 @@ void TemplateInstance::codegen(Ir* p) /* ================================================================== */ -void TemplateMixin::codegen(Ir* p) +void TemplateMixin::codegen(IRState *p) { IF_LOG Logger::println("TemplateInstance::codegen: '%s'", toPrettyChars()); LOG_SCOPE @@ -338,7 +337,7 @@ void TemplateMixin::codegen(Ir* p) /* ================================================================== */ -void AttribDeclaration::codegen(Ir* p) +void AttribDeclaration::codegen(IRState *p) { Array *d = include(NULL, NULL); @@ -353,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/llvmhelpers.cpp b/gen/llvmhelpers.cpp index de034092..e2cef943 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1210,7 +1210,7 @@ DValue* DtoDeclarationExp(Dsymbol* declaration) // static if (vd->isDataseg()) { - vd->codegen(Type::sir); + vd->codegen(gIR); } else { @@ -1222,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()) @@ -1482,7 +1482,7 @@ LLConstant* DtoTypeInfoOf(Type* type, bool base) 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); diff --git a/gen/module.cpp b/gen/module.cpp index e894912b..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,7 +393,7 @@ 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); } // for singleobj-compilation, fully emit all seen template instances @@ -405,7 +403,7 @@ 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(); } } @@ -426,8 +424,6 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) Logger::disable(); } - sir->setState(NULL); - return ir.module; } diff --git a/gen/naked.cpp b/gen/naked.cpp index 7850dc6e..0e598091 100644 --- a/gen/naked.cpp +++ b/gen/naked.cpp @@ -86,7 +86,7 @@ void ExpStatement::toNakedIR(IRState *p) // make sure the symbols gets processed // TODO: codegen() here is likely incorrect - d->declaration->codegen(Type::sir); + d->declaration->codegen(p); } ////////////////////////////////////////////////////////////////////////////////////////// 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 6106dff2..2f3acc09 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2551,7 +2551,7 @@ DValue* DelegateExp::toElem(IRState* p) owner = owner->toParent(); if (owner->isTemplateInstance() || owner == p->dmodule) { - func->codegen(Type::sir); + func->codegen(p); } } @@ -2800,7 +2800,7 @@ DValue* FuncExp::toElem(IRState* p) // We need to actually codegen the function here, as literals are not added // to the module member list. - fd->codegen(Type::sir); + fd->codegen(p); assert(fd->ir.irFunc->func); if (fd->isNested()) { @@ -2869,7 +2869,7 @@ LLConstant* FuncExp::toConstElem(IRState* p) // We need to actually codegen the function here, as literals are not added // to the module member list. - fd->codegen(Type::sir); + fd->codegen(p); assert(fd->ir.irFunc->func); return fd->ir.irFunc->func; diff --git a/gen/typinf.cpp b/gen/typinf.cpp index bb99c1ce..561cb516 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -152,7 +152,7 @@ Expression *Type::getTypeInfo(Scope *sc) } else // if in obj generation pass { - t->vtinfo->codegen(sir); + t->vtinfo->codegen(gIR); } } } @@ -317,10 +317,10 @@ void DtoResolveTypeInfo(TypeInfoDeclaration* tid) // TypeInfo instances (except ClassInfo ones) are always emitted as weak // symbols when they are used. - tid->codegen(Type::sir); + tid->codegen(gIR); } -void TypeInfoDeclaration::codegen(Ir*) +void TypeInfoDeclaration::codegen(IRState* p) { Logger::println("TypeInfoDeclaration::codegen(%s)", toPrettyChars()); LOG_SCOPE; @@ -728,7 +728,7 @@ void TypeInfoStructDeclaration::llvmDefine() /* ========================================================================= */ -void TypeInfoClassDeclaration::codegen(Ir* p) +void TypeInfoClassDeclaration::codegen(IRState *p) { // For classes, the TypeInfo is in fact a ClassInfo instance and emitted // as a __ClassZ symbol. For interfaces, the __InterfaceZ symbol is diff --git a/ir/ir.cpp b/ir/ir.cpp deleted file mode 100644 index 8cf64d92..00000000 --- a/ir/ir.cpp +++ /dev/null @@ -1,49 +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) -{ -} diff --git a/ir/ir.h b/ir/ir.h deleted file mode 100644 index 505b23de..00000000 --- a/ir/ir.h +++ /dev/null @@ -1,40 +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; } - -private: - IRState* irs; - - std::deque functionbodies; -}; - -#endif diff --git a/ir/iraggr.h b/ir/iraggr.h index 87e53764..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 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.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/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 { From 60f385b06282f59779d05c6cc8e92a604a11273c Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 13 Oct 2013 19:46:35 +0200 Subject: [PATCH 12/12] Use IRState parameter instead of gIR where available. --- gen/declarations.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 64de6ec8..58b04ff5 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -217,7 +217,7 @@ void VarDeclaration::codegen(IRState *p) if (initVal->getType() != gvar->getType()->getElementType()) { llvm::GlobalVariable* newGvar = getOrCreateGlobal(loc, - *gIR->module, initVal->getType(), gvar->isConstant(), + *p->module, initVal->getType(), gvar->isConstant(), llLinkage, 0, "", // We take on the name of the old global below. gvar->isThreadLocal()); @@ -241,14 +241,14 @@ void VarDeclaration::codegen(IRState *p) gvar->setLinkage(llLinkage); // Also set up the edbug info. - gIR->DBuilder.EmitGlobalVariable(gvar, this); + p->DBuilder.EmitGlobalVariable(gvar, this); } // 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';