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