changeset 323:0d52412d5b1a trunk

[svn r344] Fixed some very minor issues with the usage listing when calling llvmdc with no arguments. Changed the way moduleinfo is registered to use the same approach as DMD, this eliminates the need for correct linking order and should make the way for using a natively compiled runtime library. This should speed up linking tremendously and should now be possible. Fixed the llvm.used array to only be emitted if really necessary.
author lindquist
date Wed, 09 Jul 2008 23:43:51 +0200
parents 1aaf6ff7f685
children c542d12017e5
files dmd/mars.c gen/irstate.cpp gen/irstate.h gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp tango/lib/compiler/llvmdc/genobj.d tango/lib/compiler/llvmdc/llvmdc.mak tango/lib/compiler/llvmdc/moduleinfo.ll tango/lib/llvmdc.conf
diffstat 10 files changed, 129 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/mars.c	Wed Jul 09 17:02:55 2008 +0200
+++ b/dmd/mars.c	Wed Jul 09 23:43:51 2008 +0200
@@ -161,7 +161,7 @@
 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 @@
   -J<path>       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<arch>       emit code specific to <arch>\n\
+  -L<linkerflag> pass <linkerflag> to llvm-ld\n\
+  -m<arch>       emit code specific to <arch> 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 @@
   -O<n>          optimize at level <n> (0-5)\n\
   -o-            do not write object file\n\
   -od<objdir>    write object files to directory <objdir>\n\
-  -of<filename>	 name output file to <filename>\n\
+  -of<filename>  name output file to <filename>\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<path>       provide path to the directory containing the runtime library\n\
   -unittest      compile in unit tests\n\
--- a/gen/irstate.cpp	Wed Jul 09 17:02:55 2008 +0200
+++ b/gen/irstate.cpp	Wed Jul 09 23:43:51 2008 +0200
@@ -51,6 +51,7 @@
 {
     interfaceInfoType = NULL;
     mutexType = NULL;
+    moduleRefType = NULL;
 
     dmodule = 0;
     module = 0;
--- a/gen/irstate.h	Wed Jul 09 17:02:55 2008 +0200
+++ b/gen/irstate.h	Wed Jul 09 23:43:51 2008 +0200
@@ -137,6 +137,7 @@
     // interface info type, used in DtoInterfaceInfoType
     const LLStructType* interfaceInfoType;
     const LLStructType* mutexType;
+    const LLStructType* moduleRefType;
 
     // functions
     typedef std::vector<IrFunction*> FunctionVector;
--- a/gen/tollvm.cpp	Wed Jul 09 17:02:55 2008 +0200
+++ b/gen/tollvm.cpp	Wed Jul 09 23:43:51 2008 +0200
@@ -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 @@
     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<const LLType*> 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;
+}
--- a/gen/tollvm.h	Wed Jul 09 17:02:55 2008 +0200
+++ b/gen/tollvm.h	Wed Jul 09 23:43:51 2008 +0200
@@ -40,6 +40,7 @@
 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);
--- a/gen/toobj.cpp	Wed Jul 09 17:02:55 2008 +0200
+++ b/gen/toobj.cpp	Wed Jul 09 23:43:51 2008 +0200
@@ -131,10 +131,13 @@
     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 @@
     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<const LLType*>(), 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<LLConstant*> 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 @@
     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<const LLType*>(), false);
+    std::vector<const LLType*> magictypes;
+    magictypes.push_back(LLType::Int32Ty);
+    magictypes.push_back(getPtrToType(magicfty));
+    const LLStructType* magicsty = LLStructType::get(magictypes);
+
+    // make the constant element
+    std::vector<LLConstant*> 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<LLConstant*> appendInits;
-    appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, getPtrToType(LLType::Int8Ty)));
+    const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(magicsty, 1);
+    std::vector<LLConstant*> 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);
 }
 
--- a/tango/lib/compiler/llvmdc/genobj.d	Wed Jul 09 17:02:55 2008 +0200
+++ b/tango/lib/compiler/llvmdc/genobj.d	Wed Jul 09 23:43:51 2008 +0200
@@ -1013,19 +1013,22 @@
 }
 
 
-// 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 @@
 {
     debug(PRINTF) printf("_moduleCtor()\n");
 
-    ModuleInfo* mrbegin = cast(ModuleInfo*)_d_get_moduleinfo_array();
-    assert(mrbegin !is null);
+    int len = 0;
+    ModuleReference *mr;
 
-    int len = 0;
-    ModuleInfo* mr;
-    for (mr = mrbegin; *mr !is null; ++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()
--- a/tango/lib/compiler/llvmdc/llvmdc.mak	Wed Jul 09 17:02:55 2008 +0200
+++ b/tango/lib/compiler/llvmdc/llvmdc.mak	Wed Jul 09 23:43:51 2008 +0200
@@ -56,9 +56,6 @@
 .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 @@
     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 @@
 ALL_OBJS= \
     $(OBJ_BASE) \
     $(OBJ_UTIL) \
-    $(OBJ_TI) \
-    moduleinfo.bc
+    $(OBJ_TI)
 
 ######################################################
 
--- a/tango/lib/compiler/llvmdc/moduleinfo.ll	Wed Jul 09 17:02:55 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-}
--- a/tango/lib/llvmdc.conf	Wed Jul 09 17:02:55 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-
-[Environment]
-
-DFLAGS=-I%@P%/../tango -E%@P%/../lib -L-L=%@P%/../lib