From e0176785c70fae7977412e242122e59a0eb67dc3 Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Mon, 26 Nov 2007 04:49:23 +0100 Subject: [PATCH] [svn r121] Finished ModuleInfo implementation. Static ctors/dtors now work according to spec. Changed class vtable types slightly in some cases. Overridden functions now always take the the type of the first class declaring the method as this parameter. This helps when using headers (w. implementation somewhere else) --- gen/classes.cpp | 18 +++++--- gen/functions.cpp | 61 +++++++++++++------------- gen/functions.h | 2 + gen/toobj.cpp | 9 ++++ llvmdc.kdevelop.filelist | 2 +- lphobos/build.sh | 2 - lphobos/internal/moduleinit.d | 24 ---------- lphobos/internal/moduleinit_backend.ll | 14 ++---- lphobos/std/moduleinit.d | 33 +++++--------- test/classes10.d | 17 +++++++ test/moduleinfo2.d | 12 +++++ 11 files changed, 98 insertions(+), 96 deletions(-) delete mode 100644 lphobos/internal/moduleinit.d create mode 100644 test/classes10.d create mode 100644 test/moduleinfo2.d diff --git a/gen/classes.cpp b/gen/classes.cpp index f7f43cbc..b69b1a02 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -167,10 +167,12 @@ void DtoResolveClass(ClassDeclaration* cd) if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { DtoResolveFunction(fd); - assert(fd->type->ty == Tfunction); - TypeFunction* tf = (TypeFunction*)fd->type; - const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get()); - sinits_ty.push_back(fpty); + //assert(fd->type->ty == Tfunction); + //TypeFunction* tf = (TypeFunction*)fd->type; + //const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get()); + const llvm::FunctionType* vfty = DtoBaseFunctionType(fd); + const llvm::Type* vfpty = llvm::PointerType::get(vfty); + sinits_ty.push_back(vfpty); } else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars()); @@ -375,6 +377,7 @@ void DtoConstInitClass(ClassDeclaration* cd) assert(cd->type->ty == Tclass); TypeClass* ts = (TypeClass*)cd->type; const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); + const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get()); // generate initializer #if 0 @@ -406,6 +409,9 @@ void DtoConstInitClass(ClassDeclaration* cd) DtoForceDeclareDsymbol(fd); assert(fd->llvmValue); llvm::Constant* c = llvm::cast(fd->llvmValue); + // cast if necessary (overridden method) + if (c->getType() != vtbltype->getElementType(k)) + c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); sinits.push_back(c); } else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { @@ -1037,8 +1043,8 @@ void DtoDefineClassInfo(ClassDeclaration* cd) if (cd->defaultCtor && !cd->isInterfaceDeclaration()) { DtoForceDeclareDsymbol(cd->defaultCtor); c = isaConstant(cd->defaultCtor->llvmValue); - //const llvm::Type* toTy = cinfo->llvmInitZ->getOperand(11)->getType(); - c = llvm::ConstantExpr::getBitCast(c, llvm::PointerType::get(llvm::Type::Int8Ty)); // toTy); + const llvm::Type* toTy = cinfo->llvmInitZ->getOperand(12)->getType(); + c = llvm::ConstantExpr::getBitCast(c, toTy); } else { c = cinfo->llvmInitZ->getOperand(12); diff --git a/gen/functions.cpp b/gen/functions.cpp index eb1f7621..5faf4269 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -468,23 +468,6 @@ void DtoDefineFunc(FuncDeclaration* fd) { fd->llvmDModule = gIR->dmodule; - // handle static constructor / destructor - if (fd->isStaticCtorDeclaration() || fd->isStaticDtorDeclaration()) { - const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1); - //Logger::cout() << "static ctor type: " << *sctor_type << '\n'; - - llvm::Constant* sctor_func = llvm::cast(fd->llvmValue); - //Logger::cout() << "static ctor func: " << *sctor_func << '\n'; - - llvm::Constant* sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1); - - //Logger::cout() << "static ctor init: " << *sctor_init << '\n'; - - // output the llvm.global_ctors array - const char* varname = fd->isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array"; - llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module); - } - // function definition if (fd->fbody != 0) { @@ -492,18 +475,6 @@ void DtoDefineFunc(FuncDeclaration* fd) assert(fd->llvmIRFunc); gIR->functions.push_back(fd->llvmIRFunc); - /* // moved to declaration - // this handling - if (f->llvmUsesThis) { - Logger::println("uses this"); - if (f->llvmRetInPtr) - fd->llvmThisVar = ++func->arg_begin(); - else - fd->llvmThisVar = func->arg_begin(); - assert(fd->llvmThisVar != 0); - } - */ - if (fd->isMain()) gIR->emitMain = true; @@ -681,7 +652,7 @@ void DtoMain() llvm::BasicBlock* bb = new llvm::BasicBlock("entry",func); // call static ctors - llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_ctors"); + llvm::Function* fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleCtor"); llvm::Instruction* apt = new llvm::CallInst(fn,"",bb); // call user main function @@ -720,7 +691,7 @@ void DtoMain() call->setCallingConv(ir.mainFunc->getCallingConv()); // call static dtors - fn = LLVM_D_GetRuntimeFunction(ir.module,"_d_run_module_dtors"); + fn = LLVM_D_GetRuntimeFunction(ir.module,"_moduleDtor"); new llvm::CallInst(fn,"",bb); // return @@ -728,3 +699,31 @@ void DtoMain() } ////////////////////////////////////////////////////////////////////////////////////////// + +const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl) +{ + Dsymbol* parent = fdecl->toParent(); + ClassDeclaration* cd = parent->isClassDeclaration(); + assert(cd); + + FuncDeclaration* f = fdecl; + + while (cd) + { + ClassDeclaration* base = cd->baseClass; + if (!base) + break; + FuncDeclaration* f2 = base->findFunc(fdecl->ident, (TypeFunction*)fdecl->type); + if (f2) { + f = f2; + cd = base; + } + else + break; + } + + DtoResolveDsymbol(f); + return llvm::cast(DtoType(f->type)); +} + +////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/functions.h b/gen/functions.h index 69e9dd01..b595f61c 100644 --- a/gen/functions.h +++ b/gen/functions.h @@ -4,6 +4,8 @@ const llvm::FunctionType* DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false); const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl); +const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl); + void DtoResolveFunction(FuncDeclaration* fdecl); void DtoDeclareFunction(FuncDeclaration* fdecl); void DtoDefineFunc(FuncDeclaration* fd); diff --git a/gen/toobj.cpp b/gen/toobj.cpp index 363f8160..7c6f4840 100644 --- a/gen/toobj.cpp +++ b/gen/toobj.cpp @@ -123,6 +123,7 @@ Module::genobjfile() if (!global.params.novalidate) { std::string verifyErr; Logger::println("Verifying module..."); + LOG_SCOPE; if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) { error("%s", verifyErr.c_str()); @@ -364,6 +365,14 @@ void Module::genmoduleinfo() // declare // flags will be modified at runtime so can't make it constant llvm::GlobalVariable* gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, constMI, MIname, gIR->module); + + // declare the appending array + const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(llvm::PointerType::get(llvm::Type::Int8Ty), 1); + std::vector appendInits; + appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, llvm::PointerType::get(llvm::Type::Int8Ty))); + llvm::Constant* appendInit = llvm::ConstantArray::get(appendArrTy, appendInits); + std::string appendName("_d_moduleinfo_array"); + llvm::GlobalVariable* appendVar = new llvm::GlobalVariable(appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName, gIR->module); } /* ================================================================== */ diff --git a/llvmdc.kdevelop.filelist b/llvmdc.kdevelop.filelist index cb22874c..9dc7ead6 100644 --- a/llvmdc.kdevelop.filelist +++ b/llvmdc.kdevelop.filelist @@ -151,7 +151,6 @@ lphobos/internal/arrays.d lphobos/internal/cast.d lphobos/internal/contract.d lphobos/internal/mem.d -lphobos/internal/moduleinit.d lphobos/internal/objectimpl.d lphobos/internal/qsort2.d lphobos/llvm @@ -391,6 +390,7 @@ test/intrinsics.d test/mainargs1.d test/memory1.d test/moduleinfo1.d +test/moduleinfo2.d test/multiarr1.d test/multiarr2.d test/multiarr3.d diff --git a/lphobos/build.sh b/lphobos/build.sh index 22d67fe0..9569cf3f 100755 --- a/lphobos/build.sh +++ b/lphobos/build.sh @@ -11,14 +11,12 @@ llvmdc internal/contract.d -c -of../lib/llvmdcore.bc -noruntime || exit 1 echo "compiling common runtime" rebuild internal/arrays.d \ internal/mem.d \ - internal/moduleinit.d \ -c -oqobj -dc=llvmdc-posix || exit 1 echo "compiling module init backend" llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/internal.*.bc` ../lib/llvmdcore.bc obj/moduleinit_backend.bc || exit 1 - echo "compiling typeinfo 1" rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix || exit 1 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo1.*.bc` ../lib/llvmdcore.bc || exit 1 diff --git a/lphobos/internal/moduleinit.d b/lphobos/internal/moduleinit.d deleted file mode 100644 index f9d60e79..00000000 --- a/lphobos/internal/moduleinit.d +++ /dev/null @@ -1,24 +0,0 @@ -module internal.moduleinit; - -private alias extern(C) void function() fptr_t; - -extern(C): - -fptr_t* _d_get_module_ctors(); -fptr_t* _d_get_module_dtors(); - -void _d_run_module_ctors() -{ - auto p = _d_get_module_ctors(); - while(*p) { - (*p++)(); - } -} - -void _d_run_module_dtors() -{ - auto p = _d_get_module_dtors(); - while(*p) { - (*p++)(); - } -} diff --git a/lphobos/internal/moduleinit_backend.ll b/lphobos/internal/moduleinit_backend.ll index 68f63938..27473061 100644 --- a/lphobos/internal/moduleinit_backend.ll +++ b/lphobos/internal/moduleinit_backend.ll @@ -1,15 +1,9 @@ ; ModuleID = 'internal.moduleinit_backend' -@_d_module_ctor_array = appending global [1 x void ()*] zeroinitializer -@_d_module_dtor_array = appending global [1 x void ()*] zeroinitializer -define void ()** @_d_get_module_ctors() { -entry: - %tmp = getelementptr [1 x void ()*]* @_d_module_ctor_array, i32 0, i32 0 - ret void ()** %tmp -} +@_d_moduleinfo_array = appending constant [1 x i8*] [ i8* null ] -define void ()** @_d_get_module_dtors() { +define i8** @_d_get_moduleinfo_array() { entry: - %tmp = getelementptr [1 x void ()*]* @_d_module_dtor_array, i32 0, i32 0 - ret void ()** %tmp + %tmp = getelementptr [1 x i8*]* @_d_moduleinfo_array, i32 0, i32 0 + ret i8** %tmp } diff --git a/lphobos/std/moduleinit.d b/lphobos/std/moduleinit.d index f9d1dc1a..2eee9442 100644 --- a/lphobos/std/moduleinit.d +++ b/lphobos/std/moduleinit.d @@ -30,22 +30,11 @@ class ModuleCtorError : Exception } -// Win32: this gets initialized by minit.asm -// linux: this gets initialized in _moduleCtor() +// this gets initialized in _moduleCtor() extern (C) ModuleInfo[] _moduleinfo_array; -version (linux) -{ - // 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 method returns the linker constructed, null terminated, array of moduleinfos +extern (C) void** _d_get_moduleinfo_array(); ModuleInfo[] _moduleinfo_dtors; uint _moduleinfo_dtors_i; @@ -60,20 +49,20 @@ extern (C) int _fatexit(void *); extern (C) void _moduleCtor() { debug printf("_moduleCtor()\n"); - version (linux) - { int len = 0; - ModuleReference *mr; - for (mr = _Dmodule_ref; mr; mr = mr.next) + ModuleInfo* mrbegin = cast(ModuleInfo*)_d_get_moduleinfo_array(); + assert(mrbegin !is null); + + ModuleInfo* mr; + for (mr = mrbegin; *mr !is null; ++mr) len++; _moduleinfo_array = new ModuleInfo[len]; len = 0; - for (mr = _Dmodule_ref; mr; mr = mr.next) - { _moduleinfo_array[len] = mr.mod; + for (mr = mrbegin; *mr !is null; ++mr) + { _moduleinfo_array[len] = *mr; len++; } - } version (Win32) { @@ -81,7 +70,7 @@ extern (C) void _moduleCtor() //_fatexit(&_STD_moduleDtor); } - _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length]; + _moduleinfo_dtors = new ModuleInfo[len]; debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors); _moduleCtor2(_moduleinfo_array, 0); diff --git a/test/classes10.d b/test/classes10.d new file mode 100644 index 00000000..083e452c --- /dev/null +++ b/test/classes10.d @@ -0,0 +1,17 @@ +module classes10; + +class C +{ + int i; + override char[] toString() + { + return "foobar"; + } +} + +void main() +{ + Object o = new C; + char[] s = o.toString(); + assert(s == "foobar"); +} diff --git a/test/moduleinfo2.d b/test/moduleinfo2.d new file mode 100644 index 00000000..5b3f58c2 --- /dev/null +++ b/test/moduleinfo2.d @@ -0,0 +1,12 @@ +module moduleinfo2; +import std.stdio; +void main() +{ + ModuleInfo[] mi = ModuleInfo.modules(); + writefln("listing ",mi.length," modules"); + foreach(m; mi) + { + writefln(" ",m.name); + } + assert(mi.length > 50); +}