changeset 77:714057ff2dbb trunk

[svn r81] Fixed: Union support was very buggy. Should be fairly solid now.
author lindquist
date Wed, 31 Oct 2007 09:34:18 +0100
parents 9e1bd80a7e98
children 2332006e1fa4
files dmd/aggregate.h gen/toir.c gen/tollvm.c gen/tollvm.h gen/toobj.c
diffstat 5 files changed, 114 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Wed Oct 31 07:24:02 2007 +0100
+++ b/dmd/aggregate.h	Wed Oct 31 09:34:18 2007 +0100
@@ -104,7 +104,6 @@
     llvm::ConstantStruct* llvmConstVtbl;
     llvm::Constant* llvmInitZ;
     bool llvmHasUnions;
-    virtual size_t offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector
 
     AggregateDeclaration *isAggregateDeclaration() { return this; }
 };
@@ -240,7 +239,7 @@
 
     Symbol *vtblsym;
 
-    virtual size_t offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
+    void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
 
     ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
 };
--- a/gen/toir.c	Wed Oct 31 07:24:02 2007 +0100
+++ b/gen/toir.c	Wed Oct 31 09:34:18 2007 +0100
@@ -640,9 +640,8 @@
             llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->val);
 
             TypeStruct* ts = (TypeStruct*)e1type->next;
-            std::vector<unsigned> offsets(1,0);
-            ts->sym->offsetToIndex(t->next, cofs->getZExtValue(), offsets);
-            e->mem = LLVM_DtoGEP(l->getValue(), offsets, "tmp", p->scopebb());
+            std::vector<unsigned> offsets;
+            e->mem = LLVM_DtoIndexStruct(l->getValue(), ts->sym, t->next, cofs->getZExtValue(), offsets);
             e->type = elem::VAR;
             e->field = true;
         }
@@ -1454,8 +1453,9 @@
                 e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
             }
             else {
-                std::vector<unsigned> dst(1,0);
-                size_t fo = vdt->sym->offsetToIndex(tnext, offset, dst);
+                std::vector<unsigned> dst;
+                e->mem = LLVM_DtoIndexStruct(llvalue,vdt->sym, tnext, offset, dst);
+                /*size_t fo = vdt->sym->offsetToIndex(tnext, offset, dst);
                 llvm::Value* ptr = llvalue;
                 assert(ptr);
                 e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
@@ -1469,7 +1469,7 @@
                 }
                 else if (fo) {
                     e->mem = new llvm::GetElementPtrInst(e->mem, LLVM_DtoConstUint(fo), "tmp", p->scopebb());
-                }
+                }*/
             }
             e->type = elem::VAL;
             e->field = true;
@@ -1564,25 +1564,26 @@
     Logger::print("e1->type=%s\n", e1type->toChars());
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
-        std::vector<unsigned> vdoffsets(1,0);
-        llvm::Value* src = 0;
+        llvm::Value* arrptr;
         if (e1type->ty == Tpointer) {
             assert(e1type->next->ty == Tstruct);
             TypeStruct* ts = (TypeStruct*)e1type->next;
-            ts->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
             Logger::println("Struct member offset:%d", vd->offset);
-            src = l->val ? l->val : l->mem;
+            llvm::Value* src = l->val ? l->val : l->mem;
+            std::vector<unsigned> vdoffsets;
+            arrptr = LLVM_DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
         }
         else if (e1->type->ty == Tclass) {
             TypeClass* tc = (TypeClass*)e1type;
             Logger::println("Class member offset: %d", vd->offset);
+            std::vector<unsigned> vdoffsets(1,0);
             tc->sym->offsetToIndex(vd->type, vd->offset, vdoffsets);
-            src = l->getValue();
+            llvm::Value* src = l->getValue();
+            Logger::cout() << "src: " << *src << '\n';
+            arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb());
         }
-        assert(vdoffsets.size() != 1);
-        assert(src != 0);
-        Logger::cout() << "src: " << *src << '\n';
-        llvm::Value* arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb());
+        else
+            assert(0);
         e->mem = arrptr;
         Logger::cout() << "mem: " << *e->mem << '\n';
         e->type = elem::VAR;
@@ -1698,7 +1699,10 @@
         }
         const llvm::StructType* t = llvm::StructType::get(tys);
         if (t != llt) {
-            assert(gTargetData->getTypeSize(t) == gTargetData->getTypeSize(llt));
+            if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) { 
+                Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n';
+                assert(0 && "type size mismatch");
+            }
             sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp");
             Logger::cout() << "sptr type is now: " << *t << '\n';
         }
--- a/gen/tollvm.c	Wed Oct 31 07:24:02 2007 +0100
+++ b/gen/tollvm.c	Wed Oct 31 09:34:18 2007 +0100
@@ -1387,3 +1387,62 @@
 
     new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* LLVM_DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs)
+{
+    Logger::println("checking for offset %u type %s:", os, t->toChars());
+    LOG_SCOPE;
+
+    if (idxs.empty())
+        idxs.push_back(0);
+
+    const llvm::Type* llt = llvm::PointerType::get(LLVM_DtoType(t));
+
+    for (unsigned i=0; i<sd->fields.dim; ++i) {
+        VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
+        Type* vdtype = LLVM_DtoDType(vd->type);
+        Logger::println("found %u type %s", vd->offset, vdtype->toChars());
+        assert(vd->llvmFieldIndex >= 0);
+        if (os == vd->offset && vdtype == t) {
+            idxs.push_back(vd->llvmFieldIndex);
+            ptr = LLVM_DtoGEP(ptr, idxs, "tmp");
+            if (ptr->getType() != llt)
+                ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+            if (vd->llvmFieldIndexOffset)
+                ptr = new llvm::GetElementPtrInst(ptr, LLVM_DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
+            return ptr;
+        }
+        else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
+            TypeStruct* ts = (TypeStruct*)vdtype;
+            StructDeclaration* ssd = ts->sym;
+            idxs.push_back(vd->llvmFieldIndex);
+            if (vd->llvmFieldIndexOffset) {
+                Logger::println("has union field offset");
+                ptr = LLVM_DtoGEP(ptr, idxs, "tmp");
+                if (ptr->getType() != llt)
+                    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+                ptr = new llvm::GetElementPtrInst(ptr, LLVM_DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
+                std::vector<unsigned> tmp;
+                return LLVM_DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
+            }
+            else {
+                const llvm::Type* sty = llvm::PointerType::get(LLVM_DtoType(vd->type));
+                if (ptr->getType() != sty) {
+                    ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
+                    std::vector<unsigned> tmp;
+                    return LLVM_DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
+                }
+                else {
+                    return LLVM_DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
+                }
+            }
+        }
+    }
+
+    size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
+    assert(os % llt_sz == 0);
+    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+    return new llvm::GetElementPtrInst(ptr, LLVM_DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
+}
--- a/gen/tollvm.h	Wed Oct 31 07:24:02 2007 +0100
+++ b/gen/tollvm.h	Wed Oct 31 09:34:18 2007 +0100
@@ -65,4 +65,6 @@
 
 void LLVM_DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
 
+llvm::Value* LLVM_DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs);
+
 #include "enums.h"
--- a/gen/toobj.c	Wed Oct 31 07:24:02 2007 +0100
+++ b/gen/toobj.c	Wed Oct 31 09:34:18 2007 +0100
@@ -148,67 +148,6 @@
 
 /* ================================================================== */
 
-/// Returns the LLVM style index from a DMD style offset
-size_t AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
-{
-    Logger::println("checking for offset %u type %s:", os, t->toChars());
-    LOG_SCOPE;
-    for (unsigned i=0; i<fields.dim; ++i) {
-        VarDeclaration* vd = (VarDeclaration*)fields.data[i];
-        Type* vdtype = LLVM_DtoDType(vd->type);
-        Logger::println("found %u type %s", vd->offset, vdtype->toChars());
-        if (os == vd->offset && vdtype == t) {
-            assert(vd->llvmFieldIndex >= 0);
-            result.push_back(vd->llvmFieldIndex);
-            return vd->llvmFieldIndexOffset;
-        }
-        else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
-            TypeStruct* ts = (TypeStruct*)vdtype;
-            StructDeclaration* sd = ts->sym;
-            result.push_back(i);
-            return sd->offsetToIndex(t, os - vd->offset, result);
-        }
-    }
-    //assert(0 && "Offset not found in any aggregate field");
-    return (size_t)-1;
-}
-
-/* ================================================================== */
-
-static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
-{
-    // start at the bottom of the inheritance chain
-    if (cd->baseClass != 0) {
-        unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx);
-        if (o != (unsigned)-1)
-            return o;
-    }
-
-    // check this class
-    unsigned i;
-    for (i=0; i<cd->fields.dim; ++i) {
-        VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
-        if (os == vd->offset)
-            return i+idx;
-    }
-    idx += i;
-
-    return (unsigned)-1;
-}
-
-/// Returns the LLVM style index from a DMD style offset
-/// Handles class inheritance
-size_t ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
-{
-    unsigned idx = 0;
-    unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
-    assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
-    result.push_back(r+1); // vtable is 0
-    return 0;
-}
-
-/* ================================================================== */
-
 void InterfaceDeclaration::toObjFile()
 {
     Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars());
@@ -271,7 +210,7 @@
                 const llvm::Type* t = LLVM_DtoType(i->second.var->type);
                 size_t s = gTargetData->getTypeSize(t);
                 if (s > prevsize) {
-                    fieldpad = s - prevsize;
+                    fieldpad += s - prevsize;
                     prevsize = s;
                 }
                 llvmHasUnions = true;
@@ -396,6 +335,37 @@
 
 /* ================================================================== */
 
+static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx)
+{
+    // start at the bottom of the inheritance chain
+    if (cd->baseClass != 0) {
+        unsigned o = LLVM_ClassOffsetToIndex(cd->baseClass, os, idx);
+        if (o != (unsigned)-1)
+            return o;
+    }
+
+    // check this class
+    unsigned i;
+    for (i=0; i<cd->fields.dim; ++i) {
+        VarDeclaration* vd = (VarDeclaration*)cd->fields.data[i];
+        if (os == vd->offset)
+            return i+idx;
+    }
+    idx += i;
+
+    return (unsigned)-1;
+}
+
+void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
+{
+    unsigned idx = 0;
+    unsigned r = LLVM_ClassOffsetToIndex(this, os, idx);
+    assert(r != (unsigned)-1 && "Offset not found in any aggregate field");
+    result.push_back(r+1); // vtable is 0
+}
+
+/* ================================================================== */
+
 static void LLVM_AddBaseClassData(BaseClasses* bcs)
 {
     // add base class data members first