changeset 705:5a2983f97498

Fixed weird struct problem from downs, see mini/compile_structs1.d Rewrote DtoIndexStruct/Class , the old implementation were way too complex for what we really need now - since the DotVar changes.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 14 Oct 2008 15:35:49 +0200
parents 43165a082535
children 611ba592723b
files gen/classes.cpp gen/classes.h gen/structs.cpp gen/structs.h gen/toir.cpp gen/tollvm.cpp gen/tollvm.h tests/mini/compile_structs1.d
diffstat 8 files changed, 56 insertions(+), 168 deletions(-) [+]
line wrap: on
line diff
--- a/gen/classes.cpp	Tue Oct 14 13:21:14 2008 +0200
+++ b/gen/classes.cpp	Tue Oct 14 15:35:49 2008 +0200
@@ -1094,75 +1094,34 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, DStructIndexVector& idxs)
+LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* cd, VarDeclaration* vd)
 {
-    Logger::println("checking for offset %u type %s:", os, t->toChars());
+    Logger::println("indexing class field %s:", vd->toPrettyChars());
     LOG_SCOPE;
 
-    if (idxs.empty())
-        idxs.push_back(0);
+    if (Logger::enabled())
+        Logger::cout() << "src: " << *src << '\n';
+
+    // vd must be a field
+    IrField* field = vd->ir.irField;
+    assert(field);
+
+    unsigned idx = field->index + 2; // vtbl & monitor
+    unsigned off = field->indexOffset;
 
     const LLType* st = DtoType(cd->type);
-    if (ptr->getType() != st) {
-        ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");
-    }
+    src = DtoBitCast(src, st);
 
-    const LLType* llt = getPtrToType(DtoType(t));
-    unsigned dataoffset = 2;
+    LLValue* val = DtoGEPi(src, 0,idx);
+    val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
 
-    IrStruct* irstruct = cd->ir.irStruct;
-    for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
-        VarDeclaration* vd = i->second.var;
-        assert(vd);
-        Type* vdtype = vd->type->toBasetype();
-        //Logger::println("found %u type %s", vd->offset, vdtype->toChars());
-        assert(vd->ir.irField->index >= 0);
-        if (os == vd->offset && vdtype->toBasetype() == t->toBasetype()) {
-            Logger::println("found %s %s", vdtype->toChars(), vd->toChars());
-            idxs.push_back(vd->ir.irField->index + dataoffset);
-            //Logger::cout() << "indexing: " << *ptr << '\n';
-            ptr = DtoGEPi(ptr, idxs, "tmp");
-            if (ptr->getType() != llt)
-                ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-            //Logger::cout() << "indexing: " << *ptr << '\n';
-            if (vd->ir.irField->indexOffset)
-                ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
-            //Logger::cout() << "indexing: " << *ptr << '\n';
-            return ptr;
-        }
-        else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
-            TypeStruct* ts = (TypeStruct*)vdtype;
-            StructDeclaration* ssd = ts->sym;
-            idxs.push_back(vd->ir.irField->index + dataoffset);
-            if (vd->ir.irField->indexOffset) {
-                Logger::println("has union field offset");
-                ptr = DtoGEPi(ptr, idxs, "tmp");
-                if (ptr->getType() != llt)
-                    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-                ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
-                DStructIndexVector tmp;
-                return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-            }
-            else {
-                const LLType* sty = getPtrToType(DtoType(vd->type));
-                if (ptr->getType() != sty) {
-                    ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
-                    DStructIndexVector tmp;
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-                }
-                else {
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
-                }
-            }
-        }
-    }
+    if (off)
+        val = DtoGEPi1(val, off);
 
-    assert(0);
+    if (Logger::enabled())
+        Logger::cout() << "value: " << *val << '\n';
 
-    size_t llt_sz = getABITypeSize(llt->getContainedType(0));
-    assert(os % llt_sz == 0);
-    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-    return llvm::GetElementPtrInst::Create(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
+    return val;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/classes.h	Tue Oct 14 13:21:14 2008 +0200
+++ b/gen/classes.h	Tue Oct 14 15:35:49 2008 +0200
@@ -37,7 +37,7 @@
 DValue* DtoCastInterfaceToObject(DValue* val, Type* to);
 DValue* DtoDynamicCastInterface(DValue* val, Type* to);
 
-LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os, DStructIndexVector& idxs);
+LLValue* DtoIndexClass(LLValue* src, ClassDeclaration* sd, VarDeclaration* vd);
 
 LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl);
 
--- a/gen/structs.cpp	Tue Oct 14 13:21:14 2008 +0200
+++ b/gen/structs.cpp	Tue Oct 14 15:35:49 2008 +0200
@@ -52,73 +52,31 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs)
+LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
 {
-    Logger::println("checking for offset %u type %s:", os, t->toChars());
+    Logger::println("indexing struct field %s:", vd->toPrettyChars());
     LOG_SCOPE;
 
-    if (idxs.empty())
-        idxs.push_back(0);
+    // vd must be a field
+    IrField* field = vd->ir.irField;
+    assert(field);
 
-    const LLType* llt = getPtrToType(DtoType(t));
+    unsigned idx = field->index;
+    unsigned off = field->indexOffset;
+
     const LLType* st = getPtrToType(DtoType(sd->type));
+    src = DtoBitCast(src, st);
+
+    LLValue* val = DtoGEPi(src, 0,idx);
+    val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
+
+    if (off)
+        val = DtoGEPi1(val, off);
 
     if (Logger::enabled())
-    {
-        Logger::cout() << "ptr = " << *ptr << '\n';
-        Logger::cout() << "st  = " << *st << '\n';
-    }
+        Logger::cout() << "value: " << *val << '\n';
 
-    if (ptr->getType() != st) {
-        assert(sd->ir.irStruct->hasUnions);
-        ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");
-    }
-
-    for (unsigned i=0; i<sd->fields.dim; ++i) {
-        VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
-        Type* vdtype = vd->type->toBasetype();
-        //Logger::println("found %u type %s", vd->offset, vdtype->toChars());
-        assert(vd->ir.irField->index >= 0);
-        if (os == vd->offset && vdtype == t) {
-            idxs.push_back(vd->ir.irField->index);
-            ptr = DtoGEPi(ptr, idxs, "tmp");
-            if (ptr->getType() != llt)
-                ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-            if (vd->ir.irField->indexOffset)
-                ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "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->ir.irField->index);
-            if (vd->ir.irField->indexOffset) {
-                Logger::println("has union field offset");
-                ptr = DtoGEPi(ptr, idxs, "tmp");
-                if (ptr->getType() != llt)
-                    ptr = DtoBitCast(ptr, llt);
-                ptr = llvm::GetElementPtrInst::Create(ptr, DtoConstUint(vd->ir.irField->indexOffset), "tmp", gIR->scopebb());
-                DStructIndexVector tmp;
-                return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-            }
-            else {
-                const LLType* sty = getPtrToType(DtoType(vd->type));
-                if (ptr->getType() != sty) {
-                    ptr = DtoBitCast(ptr, sty);
-                    DStructIndexVector tmp;
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-                }
-                else {
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
-                }
-            }
-        }
-    }
-
-    size_t llt_sz = getTypeStoreSize(llt->getContainedType(0));
-    assert(os % llt_sz == 0);
-    ptr = DtoBitCast(ptr, llt);
-    return llvm::GetElementPtrInst::Create(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
+    return val;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/structs.h	Tue Oct 14 13:21:14 2008 +0200
+++ b/gen/structs.h	Tue Oct 14 15:35:49 2008 +0200
@@ -30,8 +30,8 @@
  */
 LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs);
 
-typedef LLSmallVector<unsigned, 3> DStructIndexVector;
-LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned os, DStructIndexVector& idxs);
+// index a struct one level
+LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd);
 
 struct DUnionField
 {
--- a/gen/toir.cpp	Tue Oct 14 13:21:14 2008 +0200
+++ b/gen/toir.cpp	Tue Oct 14 15:35:49 2008 +0200
@@ -500,18 +500,7 @@
     Type* e2type = e2->type->toBasetype();
 
     if (e1type != e2type) {
-        /*if (llvmFieldIndex) {
-            assert(e1type->ty == Tpointer && e1next && e1next->ty == Tstruct);
-            Logger::println("add to AddrExp of struct");
-            assert(r->isConst());
-            llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
-
-            TypeStruct* ts = (TypeStruct*)e1next;
-            DStructIndexVector offsets;
-            LLValue* v = DtoIndexStruct(l->getRVal(), ts->sym, t->next, cofs->getZExtValue(), offsets);
-            return new DFieldValue(type, v);
-        }
-        else*/ if (e1type->ty == Tpointer) {
+        if (e1type->ty == Tpointer) {
             Logger::println("add to pointer");
             if (r->isConst()) {
                 llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
@@ -943,34 +932,21 @@
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
         LLValue* arrptr;
+        // indexing struct pointer
         if (e1type->ty == Tpointer) {
             assert(e1type->next->ty == Tstruct);
             TypeStruct* ts = (TypeStruct*)e1type->next;
-            Logger::println("Struct member offset:%d", vd->offset);
-
-            LLValue* src = l->getRVal();
-
-            DStructIndexVector vdoffsets;
-            arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
+            arrptr = DtoIndexStruct(l->getRVal(), ts->sym, vd);
         }
-        // happens for tuples
+        // indexing normal struct
         else if (e1type->ty == Tstruct) {
             TypeStruct* ts = (TypeStruct*)e1type;
-            Logger::println("Struct member offset:%d", vd->offset);
-
-            LLValue* src = l->getRVal();
-
-            DStructIndexVector vdoffsets;
-            arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
+            arrptr = DtoIndexStruct(l->getRVal(), ts->sym, vd);
         }
+        // indexing class
         else if (e1type->ty == Tclass) {
             TypeClass* tc = (TypeClass*)e1type;
-            Logger::println("Class member offset: %d", vd->offset);
-
-            LLValue* src = l->getRVal();
-
-            DStructIndexVector vdoffsets;
-            arrptr = DtoIndexClass(src, tc->sym, vd->type, vd->offset, vdoffsets);
+            arrptr = DtoIndexClass(l->getRVal(), tc->sym, vd);
         }
         else
             assert(0);
@@ -1343,6 +1319,11 @@
         if (rv->getType() != lv->getType()) {
             rv = DtoBitCast(rv, lv->getType());
         }
+        if (Logger::enabled())
+        {
+            Logger::cout() << "lv: " << *lv << '\n';
+            Logger::cout() << "rv: " << *rv << '\n';
+        }
         eval = p->ir->CreateICmp(cmpop, lv, rv, "tmp");
     }
     else if (t->iscomplex())
--- a/gen/tollvm.cpp	Tue Oct 14 13:21:14 2008 +0200
+++ b/gen/tollvm.cpp	Tue Oct 14 15:35:49 2008 +0200
@@ -389,20 +389,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-LLValue* DtoGEPi(LLValue* ptr, const DStructIndexVector& src, const char* var, llvm::BasicBlock* bb)
-{
-    size_t n = src.size();
-    LLSmallVector<LLValue*, 3> dst(n);
-
-    size_t j=0;
-    for (DStructIndexVector::const_iterator i=src.begin(); i!=src.end(); ++i)
-        dst[j++] = DtoConstUint(*i);
-
-    return llvm::GetElementPtrInst::Create(ptr, dst.begin(), dst.end(), var?var:"tmp", bb?bb:gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 LLValue* DtoGEPi1(LLValue* ptr, unsigned i, const char* var, llvm::BasicBlock* bb)
 {
     return llvm::GetElementPtrInst::Create(ptr, DtoConstUint(i), var?var:"tmp", bb?bb:gIR->scopebb());
--- a/gen/tollvm.h	Tue Oct 14 13:21:14 2008 +0200
+++ b/gen/tollvm.h	Tue Oct 14 15:35:49 2008 +0200
@@ -48,7 +48,7 @@
 // getelementptr helpers
 LLValue* DtoGEP1(LLValue* ptr, LLValue* i0, const char* var=NULL, llvm::BasicBlock* bb=NULL);
 LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var=NULL, llvm::BasicBlock* bb=NULL);
-LLValue* DtoGEPi(LLValue* ptr, const DStructIndexVector& src, const char* var=NULL, llvm::BasicBlock* bb=NULL);
+
 LLValue* DtoGEPi1(LLValue* ptr, unsigned i0, const char* var=NULL, llvm::BasicBlock* bb=NULL);
 LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var=NULL, llvm::BasicBlock* bb=NULL);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/mini/compile_structs1.d	Tue Oct 14 15:35:49 2008 +0200
@@ -0,0 +1,4 @@
+struct Foo { int a, b, c; union Data { } Data data; }
+struct Bar { int a, b; }
+struct Baz { int a; union { Foo foo; Bar bar; } }
+void test() { Baz baz; if (baz.bar.a) return; }