diff --git a/dmd/mars.c b/dmd/mars.c index ffb6557a..d1c1edea 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -161,7 +161,7 @@ void usage() D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\ LLVMDC Homepage: http://www.dsource.org/projects/llvmdc\n\ Usage:\n\ - dmd files.d ... { -switch }\n\ + llvmdc files.d ... { -switch }\n\ \n\ files.d D source files\n%s\ -annotate annotate the bitcode with human readable source code\n\ @@ -188,8 +188,8 @@ Usage:\n\ -J where to look for string imports\n\ -ignore ignore unsupported pragmas\n\ -inline do function inlining\n\ - -Llinkerflag pass linkerflag to llvm-ld\n\ - -m emit code specific to \n\ + -L pass to llvm-ld\n\ + -m emit code specific to being one of:\n\ x86 x86-64 ppc32 ppc64\n\ -noasm do not allow use of inline asm\n\ -nofloat do not emit reference to floating point\n\ @@ -199,12 +199,12 @@ Usage:\n\ -O optimize at level (0-5)\n\ -o- do not write object file\n\ -od write object files to directory \n\ - -of name output file to \n\ + -of name output file to \n\ -op do not strip paths from source file\n\ -oq write object files with fully qualified names\n\ - -profile profile runtime performance of generated code\n\ + -profile profile runtime performance of generated code\n\ -quiet suppress unnecessary messages\n\ - -release compile release version\n\ + -release compile release version\n\ -run srcfile args... run resulting program, passing args\n\ -R provide path to the directory containing the runtime library\n\ -unittest compile in unit tests\n\ diff --git a/gen/irstate.cpp b/gen/irstate.cpp index 7d2d8900..317999d0 100644 --- a/gen/irstate.cpp +++ b/gen/irstate.cpp @@ -51,6 +51,7 @@ IRState::IRState() { interfaceInfoType = NULL; mutexType = NULL; + moduleRefType = NULL; dmodule = 0; module = 0; diff --git a/gen/irstate.h b/gen/irstate.h index e92a35fc..f8b6076e 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -137,6 +137,7 @@ struct IRState // interface info type, used in DtoInterfaceInfoType const LLStructType* interfaceInfoType; const LLStructType* mutexType; + const LLStructType* moduleRefType; // functions typedef std::vector FunctionVector; diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 0f00b2e5..87a47774 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -6,6 +6,7 @@ #include "aggregate.h" #include "declaration.h" #include "init.h" +#include "module.h" #include "gen/tollvm.h" #include "gen/irstate.h" @@ -724,3 +725,30 @@ const LLStructType* DtoMutexType() gIR->module->addTypeName("D_CRITICAL_SECTION", pmutex); return pmutex; } + +////////////////////////////////////////////////////////////////////////////////////////// + +const LLStructType* DtoModuleReferenceType() +{ + if (gIR->moduleRefType) + return gIR->moduleRefType; + + // this is a recursive type so start out with the opaque + LLOpaqueType* opaque = LLOpaqueType::get(); + + // add members + std::vector types; + types.push_back(getPtrToType(opaque)); + types.push_back(DtoType(Module::moduleinfo->type)); + + // resolve type + const LLStructType* st = LLStructType::get(types); + LLPATypeHolder pa(st); + opaque->refineAbstractTypeTo(pa.get()); + st = isaStruct(pa.get()); + + // done + gIR->moduleRefType = st; + gIR->module->addTypeName("ModuleReference", st); + return st; +} diff --git a/gen/tollvm.h b/gen/tollvm.h index 110c801b..5bb43eaf 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -40,6 +40,7 @@ LLValue* DtoBoolean(LLValue* val); const LLType* DtoSize_t(); const LLStructType* DtoInterfaceInfoType(); const LLStructType* DtoMutexType(); +const LLStructType* DtoModuleReferenceType(); // getelementptr helpers LLValue* DtoGEP1(LLValue* ptr, LLValue* i0, const char* var=NULL, llvm::BasicBlock* bb=NULL); diff --git a/gen/toobj.cpp b/gen/toobj.cpp index dc08ada5..acebb956 100644 --- a/gen/toobj.cpp +++ b/gen/toobj.cpp @@ -131,10 +131,13 @@ void Module::genobjfile() DtoEmptyAllLists(); // emit usedArray - const LLArrayType* usedTy = LLArrayType::get(getVoidPtrType(), ir.usedArray.size()); - LLConstant* usedInit = LLConstantArray::get(usedTy, ir.usedArray); - LLGlobalVariable* usedArray = new LLGlobalVariable(usedTy, true, LLGlobalValue::AppendingLinkage, usedInit, "llvm.used", ir.module); - usedArray->setSection("llvm.metadata"); + if (!ir.usedArray.empty()) + { + const LLArrayType* usedTy = LLArrayType::get(getVoidPtrType(), ir.usedArray.size()); + LLConstant* usedInit = LLConstantArray::get(usedTy, ir.usedArray); + LLGlobalVariable* usedArray = new LLGlobalVariable(usedTy, true, LLGlobalValue::AppendingLinkage, usedInit, "llvm.used", ir.module); + usedArray->setSection("llvm.metadata"); + } // verify the llvm if (!global.params.novalidate) { @@ -296,6 +299,56 @@ static llvm::Function* build_module_unittest() return fn; } +// build ModuleReference and register function, to register the module info in the global linked list +static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) +{ + // build ctor type + const LLFunctionType* fty = LLFunctionType::get(LLType::VoidTy, std::vector(), false); + + // build ctor name + std::string fname = gIR->dmodule->mangle(); + fname += "16__moduleinfoCtorZ"; + + // build a function that registers the moduleinfo in the global moduleinfo linked list + LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, gIR->module); + + // provide the default initializer + const LLStructType* modulerefTy = DtoModuleReferenceType(); + std::vector mrefvalues; + mrefvalues.push_back(LLConstant::getNullValue(modulerefTy->getContainedType(0))); + mrefvalues.push_back(moduleinfo); + LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, mrefvalues); + + // create the ModuleReference node for this module + std::string thismrefname = gIR->dmodule->mangle(); + thismrefname += "11__moduleRefZ"; + LLGlobalVariable* thismref = new LLGlobalVariable(modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, thismrefname, gIR->module); + + // make sure _Dmodule_ref is declared + LLGlobalVariable* mref = gIR->module->getNamedGlobal("_Dmodule_ref"); + if (!mref) + mref = new LLGlobalVariable(getPtrToType(modulerefTy), false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref", gIR->module); + + // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list + llvm::BasicBlock* bb = llvm::BasicBlock::Create("moduleinfoCtorEntry", ctor); + IRBuilder builder(bb); + + // get current beginning + LLValue* curbeg = builder.CreateLoad(mref, "current"); + + // put current beginning as the next of this one + LLValue* gep = builder.CreateStructGEP(thismref, 0, "next"); + builder.CreateStore(curbeg, gep); + + // replace beginning + builder.CreateStore(thismref, mref); + + // return + builder.CreateRetVoid(); + + return ctor; +} + // Put out instance of ModuleInfo for this Module void Module::genmoduleinfo() @@ -469,12 +522,27 @@ void Module::genmoduleinfo() if (!gvar) gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname, gIR->module); gvar->setInitializer(constMI); + // build the modulereference and ctor for registering it + LLFunction* mictor = build_module_reference_and_ctor(gvar); + + // register this ctor in the magic llvm.global_ctors appending array + const LLFunctionType* magicfty = LLFunctionType::get(LLType::VoidTy, std::vector(), false); + std::vector magictypes; + magictypes.push_back(LLType::Int32Ty); + magictypes.push_back(getPtrToType(magicfty)); + const LLStructType* magicsty = LLStructType::get(magictypes); + + // make the constant element + std::vector magicconstants; + magicconstants.push_back(DtoConstUint(65535)); + magicconstants.push_back(mictor); + LLConstant* magicinit = LLConstantStruct::get(magicsty, magicconstants); + // declare the appending array - const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(getPtrToType(LLType::Int8Ty), 1); - std::vector appendInits; - appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, getPtrToType(LLType::Int8Ty))); + const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(magicsty, 1); + std::vector appendInits(1, magicinit); LLConstant* appendInit = llvm::ConstantArray::get(appendArrTy, appendInits); - std::string appendName("_d_moduleinfo_array"); + std::string appendName("llvm.global_ctors"); llvm::GlobalVariable* appendVar = new llvm::GlobalVariable(appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName, gIR->module); } diff --git a/tango/lib/compiler/llvmdc/genobj.d b/tango/lib/compiler/llvmdc/genobj.d index 1fe2f31e..a41e59e9 100644 --- a/tango/lib/compiler/llvmdc/genobj.d +++ b/tango/lib/compiler/llvmdc/genobj.d @@ -1013,19 +1013,22 @@ class ModuleInfo } -// Win32: this gets initialized by minit.asm -// linux: this gets initialized in _moduleCtor() +// this gets initialized in _moduleCtor() extern (C) ModuleInfo[] _moduleinfo_array; -// llvmdc method -extern (C) void** _d_get_moduleinfo_array(); +// This linked list is created by a compiler generated function inserted +// into the .ctor list by the compiler. +struct ModuleReference +{ + ModuleReference* next; + ModuleInfo mod; +} +extern (C) ModuleReference* _Dmodule_ref; // start of linked list +// this list is built from the linked list above ModuleInfo[] _moduleinfo_dtors; uint _moduleinfo_dtors_i; -// Register termination function pointers -extern (C) int _fatexit(void *); - /** * Initialize the modules. */ @@ -1034,32 +1037,22 @@ extern (C) void _moduleCtor() { debug(PRINTF) printf("_moduleCtor()\n"); - ModuleInfo* mrbegin = cast(ModuleInfo*)_d_get_moduleinfo_array(); - assert(mrbegin !is null); - int len = 0; - ModuleInfo* mr; - for (mr = mrbegin; *mr !is null; ++mr) + ModuleReference *mr; + + for (mr = _Dmodule_ref; mr; mr = mr.next) len++; _moduleinfo_array = new ModuleInfo[len]; - len = 0; - for (mr = mrbegin; *mr !is null; ++mr) - { _moduleinfo_array[len] = *mr; + for (mr = _Dmodule_ref; mr; mr = mr.next) + { _moduleinfo_array[len] = mr.mod; len++; } - version (Win32) - { - // Ensure module destructors also get called on program termination - //_fatexit(&_STD_moduleDtor); - } - _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length]; debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors); _moduleIndependentCtors(); _moduleCtor2(_moduleinfo_array, 0); - debug(PRINTF) printf("_moduleCtor() DONE\n"); } extern (C) void _moduleIndependentCtors() diff --git a/tango/lib/compiler/llvmdc/llvmdc.mak b/tango/lib/compiler/llvmdc/llvmdc.mak index 9aea4749..43b16555 100644 --- a/tango/lib/compiler/llvmdc/llvmdc.mak +++ b/tango/lib/compiler/llvmdc/llvmdc.mak @@ -56,9 +56,6 @@ LIB_DEST=.. .d.bc: $(DC) -c $(DFLAGS) $< -of$@ -.ll.bc: - $(LLC) -f -o=$@ $< - .d.html: $(DC) -c -o- $(DOCFLAGS) -Df$*.html llvmdc.ddoc $< @@ -87,12 +84,6 @@ OBJ_BASE= \ qsort2.bc \ switch.bc \ -# NOTE: trace.obj and cover.obj are not necessary for a successful build -# as both are used for debugging features (profiling and coverage) -# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and -# minit.asm is not used by dmd for linux -# NOTE: deh.o is only needed for Win32, linux uses deh2.o - OBJ_UTIL= \ util/console.bc \ util/ctype.bc \ @@ -139,8 +130,7 @@ OBJ_TI= \ ALL_OBJS= \ $(OBJ_BASE) \ $(OBJ_UTIL) \ - $(OBJ_TI) \ - moduleinfo.bc + $(OBJ_TI) ###################################################### diff --git a/tango/lib/compiler/llvmdc/moduleinfo.ll b/tango/lib/compiler/llvmdc/moduleinfo.ll deleted file mode 100644 index 27473061..00000000 --- a/tango/lib/compiler/llvmdc/moduleinfo.ll +++ /dev/null @@ -1,9 +0,0 @@ -; ModuleID = 'internal.moduleinit_backend' - -@_d_moduleinfo_array = appending constant [1 x i8*] [ i8* null ] - -define i8** @_d_get_moduleinfo_array() { -entry: - %tmp = getelementptr [1 x i8*]* @_d_moduleinfo_array, i32 0, i32 0 - ret i8** %tmp -} diff --git a/tango/lib/llvmdc.conf b/tango/lib/llvmdc.conf deleted file mode 100644 index f1588144..00000000 --- a/tango/lib/llvmdc.conf +++ /dev/null @@ -1,4 +0,0 @@ - -[Environment] - -DFLAGS=-I%@P%/../tango -E%@P%/../lib -L-L=%@P%/../lib