changeset 193:aca17e55b7a5 trunk

[svn r209] Fixed: exotic array to pointer casts were broken. Changed: classes now have opaque vtables.
author lindquist
date Mon, 12 May 2008 18:44:11 +0200
parents 67ed21bf16af
children 8ee2c46ff938
files gen/arrays.cpp gen/classes.cpp gen/toir.cpp gen/tollvm.cpp gen/tollvm.h ir/irstruct.cpp ir/irstruct.h ir/irtype.cpp ir/irtype.h premake.lua tango/lib/llvmdc-posix.mak
diffstat 11 files changed, 129 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- 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';
--- 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<const llvm::Type*> fieldtypes;
+
     // add vtable
     ts->ir.vtblType = new llvm::PATypeHolder(llvm::OpaqueType::get());
     const llvm::Type* vtabty = getPtrToType(ts->ir.vtblType->get());
-
-    std::vector<const llvm::Type*> 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<const llvm::Type*> 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<llvm::OpaqueType>(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<llvm::Constant>(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<llvm::Constant>(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<llvm::ConstantArray>(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<llvm::ConstantStruct>(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<llvm::Constant*> infoInits;
@@ -613,7 +644,12 @@
             std::vector<llvm::Constant*> 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<llvm::Constant>(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<llvm::ConstantArray>(civtblInit);
+        #else
             llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits);
             iri->vtblInit = llvm::cast<llvm::ConstantStruct>(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);
 
--- 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);
         }
--- 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<llvm::PointerType>(t);
--- 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
--- 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;
--- 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;
--- 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
 }
--- 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
--- 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"
--- 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
 
 ######################################################