[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.
This commit is contained in:
Tomas Lindquist Olsen
2008-07-09 23:43:51 +02:00
parent 64ab226a4b
commit 2dfb2fcf19
10 changed files with 129 additions and 60 deletions

View File

@@ -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<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 @@ Usage:\n\
-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\

View File

@@ -51,6 +51,7 @@ IRState::IRState()
{
interfaceInfoType = NULL;
mutexType = NULL;
moduleRefType = NULL;
dmodule = 0;
module = 0;

View File

@@ -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<IrFunction*> FunctionVector;

View File

@@ -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<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;
}

View File

@@ -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);

View File

@@ -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<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 @@ 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<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);
}

View File

@@ -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()

View File

@@ -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)
######################################################

View File

@@ -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
}

View File

@@ -1,4 +0,0 @@
[Environment]
DFLAGS=-I%@P%/../tango -E%@P%/../lib -L-L=%@P%/../lib