# HG changeset patch # User lindquist # Date 1210610651 -7200 # Node ID aca17e55b7a59f62613a11170b136a894a2aecb2 # Parent 67ed21bf16af248a12d9657d85ca459c4e979835 [svn r209] Fixed: exotic array to pointer casts were broken. Changed: classes now have opaque vtables. diff -r 67ed21bf16af -r aca17e55b7a5 gen/arrays.cpp --- a/gen/arrays.cpp Mon May 12 18:22:55 2008 +0200 +++ b/gen/arrays.cpp Mon May 12 18:44:11 2008 +0200 @@ -934,10 +934,9 @@ Logger::cout() << "from array or sarray" << '\n'; if (totype->ty == Tpointer) { Logger::cout() << "to pointer" << '\n'; - assert(fromtype->next == totype->next || totype->next->ty == Tvoid); rval = DtoArrayPtr(u); - if (fromtype->next != totype->next) - rval = gIR->ir->CreateBitCast(rval, getPtrToType(llvm::Type::Int8Ty), "tmp"); + if (rval->getType() != tolltype) + rval = gIR->ir->CreateBitCast(rval, tolltype, "tmp"); } else if (totype->ty == Tarray) { Logger::cout() << "to array" << '\n'; diff -r 67ed21bf16af -r aca17e55b7a5 gen/classes.cpp --- a/gen/classes.cpp Mon May 12 18:22:55 2008 +0200 +++ b/gen/classes.cpp Mon May 12 18:44:11 2008 +0200 @@ -124,18 +124,20 @@ } }*/ + // push state gIR->structs.push_back(irstruct); gIR->classes.push_back(cd); + // vector holding the field types + std::vector fieldtypes; + // add vtable ts->ir.vtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); const llvm::Type* vtabty = getPtrToType(ts->ir.vtblType->get()); - - std::vector fieldtypes; fieldtypes.push_back(vtabty); // add monitor - fieldtypes.push_back(getPtrToType(llvm::Type::Int8Ty)); + fieldtypes.push_back(getVoidPtrType()); // add base class data fields first LLVM_AddBaseClassData(&cd->baseclasses); @@ -241,7 +243,11 @@ fieldtypes.push_back(ivtblTy); // fix the interface vtable type + #if OPAQUE_VTBLS + iri->vtblTy = isaArray(itc->ir.vtblType->get()); + #else iri->vtblTy = isaStruct(itc->ir.vtblType->get()); + #endif // set index iri->index = interIdx++; @@ -273,6 +279,12 @@ // create vtable type llvm::GlobalVariable* svtblVar = 0; +#if OPAQUE_VTBLS + // void*[vtbl.dim] + const llvm::ArrayType* svtbl_ty + = llvm::ArrayType::get(getVoidPtrType(), cd->vtbl.dim); + +#else std::vector sinits_ty; for (int k=0; k < cd->vtbl.dim; k++) @@ -310,19 +322,29 @@ assert(0); } + // get type assert(!sinits_ty.empty()); const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty); - - std::string styname(cd->mangle()); - styname.append("__vtblType"); - gIR->module->addTypeName(styname, svtbl_ty); +#endif // refine for final vtable type llvm::cast(ts->ir.vtblType->get())->refineAbstractTypeTo(svtbl_ty); +#if !OPAQUE_VTBLS + // name vtbl type + std::string styname(cd->mangle()); + styname.append("__vtblType"); + gIR->module->addTypeName(styname, svtbl_ty); +#endif + + // log + Logger::cout() << "final class type: " << *ts->ir.type->get() << '\n'; + + // pop state gIR->classes.pop_back(); gIR->structs.pop_back(); + // queue declare gIR->declareList.push_back(cd); } @@ -359,9 +381,7 @@ std::string varname("_D"); varname.append(cd->mangle()); varname.append("6__vtblZ"); - - const llvm::StructType* svtbl_ty = isaStruct(ts->ir.vtblType->get()); - cd->ir.irStruct->vtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); + cd->ir.irStruct->vtbl = new llvm::GlobalVariable(ts->ir.vtblType->get(), true, _linkage, 0, varname, gIR->module); } // get interface info type @@ -445,7 +465,11 @@ assert(cd->type->ty == Tclass); TypeClass* ts = (TypeClass*)cd->type; const llvm::StructType* structtype = isaStruct(ts->ir.type->get()); +#if OPAQUE_VTBLS + const llvm::ArrayType* vtbltype = isaArray(ts->ir.vtblType->get()); +#else const llvm::StructType* vtbltype = isaStruct(ts->ir.vtblType->get()); +#endif // make sure each offset knows its default initializer for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) @@ -543,37 +567,40 @@ assert(dsym); //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; + #if OPAQUE_VTBLS + const llvm::Type* targetTy = getVoidPtrType(); + #else + const llvm::Type* targetTy = vtbltype->getElementType(k); + #endif + + llvm::Constant* c = NULL; + // virtual method if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { DtoForceDeclareDsymbol(fd); assert(fd->ir.irFunc->func); - llvm::Constant* c = llvm::cast(fd->ir.irFunc->func); - // cast if necessary (overridden method) - if (c->getType() != vtbltype->getElementType(k)) - c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); - sinits.push_back(c); + c = llvm::cast(fd->ir.irFunc->func); } + // classinfo else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { assert(cd->ir.irStruct->classInfo); - llvm::Constant* c = cd->ir.irStruct->classInfo; - sinits.push_back(c); + c = cd->ir.irStruct->classInfo; } - else - assert(0); - } - - const llvm::StructType* svtbl_ty = isaStruct(ts->ir.vtblType->get()); + assert(c != NULL); -#if 0 - for (size_t i=0; i< sinits.size(); ++i) - { - Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n'; - Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n'; - assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); + // cast if necessary (overridden method) + if (c->getType() != targetTy) + c = llvm::ConstantExpr::getBitCast(c, targetTy); + sinits.push_back(c); } -#endif - + #if OPAQUE_VTBLS + const llvm::ArrayType* svtbl_ty = isaArray(ts->ir.vtblType->get()); + llvm::Constant* cvtblInit = llvm::ConstantArray::get(svtbl_ty, sinits); + cd->ir.irStruct->constVtbl = llvm::cast(cvtblInit); + #else + const llvm::StructType* svtbl_ty = isaStruct(ts->ir.vtblType->get()); llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); cd->ir.irStruct->constVtbl = llvm::cast(cvtblInit); + #endif // create interface vtable const initalizers for (IrStruct::InterfaceVectorIter i=irstruct->interfaceVec.begin(); i!=irstruct->interfaceVec.end(); ++i) @@ -585,7 +612,11 @@ assert(id->type->ty == Tclass); TypeClass* its = (TypeClass*)id->type; + #if OPAQUE_VTBLS + const llvm::ArrayType* ivtbl_ty = isaArray(its->ir.vtblType->get()); + #else const llvm::StructType* ivtbl_ty = isaStruct(its->ir.vtblType->get()); + #endif // generate interface info initializer std::vector infoInits; @@ -613,7 +644,12 @@ std::vector iinits; // add interface info + #if OPAQUE_VTBLS + const llvm::Type* targetTy = getVoidPtrType(); + iinits.push_back(llvm::ConstantExpr::getBitCast(iri->info, targetTy)); + #else iinits.push_back(iri->info); + #endif for (int k=1; k < b->vtbl.dim; k++) { @@ -626,22 +662,24 @@ assert(fd->ir.irFunc->func); llvm::Constant* c = llvm::cast(fd->ir.irFunc->func); + #if !OPAQUE_VTBLS + const llvm::Type* targetTy = iri->vtblTy->getContainedType(k); + #endif + // we have to bitcast, as the type created in ResolveClass expects a different this type - c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); + c = llvm::ConstantExpr::getBitCast(c, targetTy); iinits.push_back(c); + Logger::cout() << "c: " << *c << '\n'; } - #if 0 - for (size_t x=0; x< iinits.size(); ++x) - { - Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n"; - Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n"; - assert(ivtbl_ty->getElementType(x) == iinits[x]->getType()); - } - #endif - + #if OPAQUE_VTBLS + Logger::cout() << "n: " << iinits.size() << " ivtbl_ty: " << *ivtbl_ty << '\n'; + llvm::Constant* civtblInit = llvm::ConstantArray::get(ivtbl_ty, iinits); + iri->vtblInit = llvm::cast(civtblInit); + #else llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); iri->vtblInit = llvm::cast(civtblInit); + #endif } } // we always generate interfaceinfos as best we can @@ -1171,7 +1209,7 @@ assert(DtoDType(inst->getType())->ty == Tclass); llvm::Value* vthis = inst->getRVal(); - //Logger::cout() << "vthis: " << *vthis << '\n'; + Logger::cout() << "vthis: " << *vthis << '\n'; llvm::Value* funcval; funcval = DtoGEPi(vthis, 0, 0, "tmp"); @@ -1179,6 +1217,13 @@ funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars()); funcval = DtoLoad(funcval); + Logger::cout() << "funcval: " << *funcval << '\n'; + +#if OPAQUE_VTBLS + funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type))); + Logger::cout() << "funcval casted: " << *funcval << '\n'; +#endif + //assert(funcval->getType() == DtoType(fdecl->type)); //cc = DtoCallingConv(fdecl->linkage); diff -r 67ed21bf16af -r aca17e55b7a5 gen/toir.cpp --- a/gen/toir.cpp Mon May 12 18:22:55 2008 +0200 +++ b/gen/toir.cpp Mon May 12 18:44:11 2008 +0200 @@ -1474,6 +1474,10 @@ funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb()); funcval = DtoGEP(funcval, zero, vtblidx, toChars(), p->scopebb()); funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb()); + #if OPAQUE_VTBLS + funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type))); + Logger::cout() << "funcval casted: " << *funcval << '\n'; + #endif //assert(funcval->getType() == DtoType(fdecl->type)); //cc = DtoCallingConv(fdecl->linkage); } diff -r 67ed21bf16af -r aca17e55b7a5 gen/tollvm.cpp --- a/gen/tollvm.cpp Mon May 12 18:22:55 2008 +0200 +++ b/gen/tollvm.cpp Mon May 12 18:44:11 2008 +0200 @@ -1428,6 +1428,11 @@ return llvm::PointerType::get(t, 0); } +const llvm::PointerType* getVoidPtrType() +{ + return getPtrToType(llvm::Type::Int8Ty); +} + llvm::ConstantPointerNull* getNullPtr(const llvm::Type* t) { const llvm::PointerType* pt = llvm::cast(t); diff -r 67ed21bf16af -r aca17e55b7a5 gen/tollvm.h --- a/gen/tollvm.h Mon May 12 18:22:55 2008 +0200 +++ b/gen/tollvm.h Mon May 12 18:44:11 2008 +0200 @@ -123,6 +123,7 @@ // llvm::T::get(...) wrappers const llvm::PointerType* getPtrToType(const llvm::Type* t); +const llvm::PointerType* getVoidPtrType(); llvm::ConstantPointerNull* getNullPtr(const llvm::Type* t); // type sizes diff -r 67ed21bf16af -r aca17e55b7a5 ir/irstruct.cpp --- a/ir/irstruct.cpp Mon May 12 18:22:55 2008 +0200 +++ b/ir/irstruct.cpp Mon May 12 18:44:11 2008 +0200 @@ -4,7 +4,11 @@ #include "ir/irstruct.h" #include "gen/irstate.h" +#if OPAQUE_VTBLS +IrInterface::IrInterface(BaseClass* b, const llvm::ArrayType* vt) +#else IrInterface::IrInterface(BaseClass* b, const llvm::StructType* vt) +#endif { base = b; decl = b->base; diff -r 67ed21bf16af -r aca17e55b7a5 ir/irstruct.h --- a/ir/irstruct.h Mon May 12 18:22:55 2008 +0200 +++ b/ir/irstruct.h Mon May 12 18:44:11 2008 +0200 @@ -11,8 +11,13 @@ BaseClass* base; ClassDeclaration* decl; +#if OPAQUE_VTBLS + const llvm::ArrayType* vtblTy; + llvm::ConstantArray* vtblInit; +#else const llvm::StructType* vtblTy; llvm::ConstantStruct* vtblInit; +#endif llvm::GlobalVariable* vtbl; const llvm::StructType* infoTy; @@ -21,7 +26,11 @@ int index; +#if OPAQUE_VTBLS + IrInterface(BaseClass* b, const llvm::ArrayType* vt); +#else IrInterface(BaseClass* b, const llvm::StructType* vt); +#endif ~IrInterface(); }; @@ -67,7 +76,11 @@ bool constinited; llvm::GlobalVariable* vtbl; +#if OPAQUE_VTBLS + llvm::ConstantArray* constVtbl; +#else llvm::ConstantStruct* constVtbl; +#endif llvm::GlobalVariable* init; llvm::Constant* constInit; llvm::GlobalVariable* classInfo; diff -r 67ed21bf16af -r aca17e55b7a5 ir/irtype.cpp --- a/ir/irtype.cpp Mon May 12 18:22:55 2008 +0200 +++ b/ir/irtype.cpp Mon May 12 18:44:11 2008 +0200 @@ -21,7 +21,9 @@ { assert(list.insert(this).second); type = s.type; +#if OPAQUE_VTBLS vtblType = s.type; +#endif } IrType::~IrType() @@ -32,5 +34,7 @@ void IrType::reset() { type = NULL; +#if OPAQUE_VTBLS vtblType = NULL; +#endif } diff -r 67ed21bf16af -r aca17e55b7a5 ir/irtype.h --- a/ir/irtype.h Mon May 12 18:22:55 2008 +0200 +++ b/ir/irtype.h Mon May 12 18:44:11 2008 +0200 @@ -21,7 +21,9 @@ void reset(); llvm::PATypeHolder* type; +#if !OPAQUE_VTBLS llvm::PATypeHolder* vtblType; +#endif }; #endif diff -r 67ed21bf16af -r aca17e55b7a5 premake.lua --- a/premake.lua Mon May 12 18:22:55 2008 +0200 +++ b/premake.lua Mon May 12 18:44:11 2008 +0200 @@ -27,9 +27,13 @@ package.linkoptions = { -- long but it's faster than just 'all' "`llvm-config --libs core asmparser bitreader bitwriter support target transformutils scalaropts ipo instrumentation x86 powerpc`", - "`llvm-config --ldflags`" + "`llvm-config --ldflags`", } -package.defines = { "IN_LLVM", "_DH" } +package.defines = { + "IN_LLVM", + "_DH", + "OPAQUE_VTBLS=1", +} package.config.Release.defines = { "LLVMD_NO_LOGGER" } package.config.Debug.buildoptions = { "-g -O0" } --package.targetprefix = "llvm" diff -r 67ed21bf16af -r aca17e55b7a5 tango/lib/llvmdc-posix.mak --- a/tango/lib/llvmdc-posix.mak Mon May 12 18:22:55 2008 +0200 +++ b/tango/lib/llvmdc-posix.mak Mon May 12 18:44:11 2008 +0200 @@ -31,8 +31,8 @@ ADD_CFLAGS= ADD_DFLAGS= -targets : lib clib doc -all : lib clib doc +targets : lib doc +all : lib doc ######################################################