changeset 8:5e69b77a5c51 trunk

[svn r12] fixed accessing aggregate fields of aggregates removed some useless branches for successive scopes ala {}{}{}
author lindquist
date Thu, 27 Sep 2007 06:03:06 +0200
parents 7a155ba88c53
children dafae18f9c08
files dmd/aggregate.h gen/toir.c gen/tollvm.c gen/tollvm.h gen/toobj.c test/classes5.d test/scope1.d test/structs3.d
diffstat 8 files changed, 95 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Wed Sep 26 19:17:54 2007 +0200
+++ b/dmd/aggregate.h	Thu Sep 27 06:03:06 2007 +0200
@@ -18,6 +18,8 @@
 #include "root.h"
 #include "dsymbol.h"
 
+#include <vector>
+
 struct Identifier;
 struct Type;
 struct TypeFunction;
@@ -97,7 +99,7 @@
     llvm::Type* llvmType;
     llvm::Value* llvmVtbl;
     llvm::Constant* llvmInitZ;
-    virtual unsigned offsetToIndex(unsigned os); // converts a DMD field offsets to LLVM struct index
+    virtual void offsetToIndex(unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector
 
     AggregateDeclaration *isAggregateDeclaration() { return this; }
 };
@@ -232,7 +234,7 @@
 
     Symbol *vtblsym;
 
-    virtual unsigned offsetToIndex(unsigned os);
+    virtual void offsetToIndex(unsigned os, std::vector<unsigned>& result);
 
     ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
 };
--- a/gen/toir.c	Wed Sep 26 19:17:54 2007 +0200
+++ b/gen/toir.c	Thu Sep 27 06:03:06 2007 +0200
@@ -434,15 +434,15 @@
 
     if (e1->type != e2->type) {
         if (e1->type->ty == Tpointer && e1->type->next->ty == Tstruct) {
-            assert(l->field);
+            //assert(l->field);
             llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             assert(r->type == elem::CONST);
             llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->val);
 
             TypeStruct* ts = (TypeStruct*)e1->type->next;
-            llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, ts->sym->offsetToIndex(cofs->getZExtValue()), false);
-
-            e->mem = LLVM_DtoGEP(l->getValue(), zero, offset, "tmp", p->scopebb());
+            std::vector<unsigned> offsets(1,0);
+            ts->sym->offsetToIndex(cofs->getZExtValue(), offsets);
+            e->mem = LLVM_DtoGEP(l->getValue(), offsets, "tmp", p->scopebb());
             e->type = elem::VAR;
             e->field = true;
         }
@@ -1126,12 +1126,11 @@
         if (vd->type->ty == Tstruct && !(type->ty == Tpointer && type->next == vd->type)) {
             TypeStruct* vdt = (TypeStruct*)vd->type;
             e = new elem;
-            llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-            llvm::Value* idx1 = llvm::ConstantInt::get(llvm::Type::Int32Ty, (uint64_t)vdt->sym->offsetToIndex(offset), false);
-            //const llvm::Type* _typ = llvm::GetElementPtrInst::getIndexedType(LLVM_DtoType(type), idx1);
+            std::vector<unsigned> dst(1,0);
+            vdt->sym->offsetToIndex(offset, dst);
             llvm::Value* ptr = vd->llvmValue;
             assert(ptr);
-            e->mem = LLVM_DtoGEP(ptr,idx0,idx1,"tmp",p->scopebb());
+            e->mem = LLVM_DtoGEP(ptr,dst,"tmp",p->scopebb());
             e->type = elem::VAL;
             e->field = true;
         }
@@ -1210,26 +1209,24 @@
     Logger::print("e1->type=%s\n", e1->type->toChars());
 
     if (VarDeclaration* vd = var->isVarDeclaration()) {
-        size_t vdoffset = (size_t)-1;
+        std::vector<unsigned> vdoffsets(1,0);
         llvm::Value* src = 0;
         if (e1->type->ty == Tpointer) {
             assert(e1->type->next->ty == Tstruct);
             TypeStruct* ts = (TypeStruct*)e1->type->next;
-            vdoffset = ts->sym->offsetToIndex(vd->offset);
-            Logger::println("Struct member offset:%d index:%d", vd->offset, vdoffset);
+            ts->sym->offsetToIndex(vd->offset, vdoffsets);
+            Logger::println("Struct member offset:%d", vd->offset);
             src = l->val;
         }
         else if (e1->type->ty == Tclass) {
             TypeClass* tc = (TypeClass*)e1->type;
             Logger::println("Class member offset: %d", vd->offset);
-            vdoffset = tc->sym->offsetToIndex(vd->offset);
+            tc->sym->offsetToIndex(vd->offset, vdoffsets);
             src = l->getValue();
         }
-        assert(vdoffset != (size_t)-1);
+        assert(vdoffsets.size() != 1);
         assert(src != 0);
-        llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-        llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, vdoffset, false);
-        llvm::Value* arrptr = LLVM_DtoGEP(src,zero,offset,"tmp",p->scopebb());
+        llvm::Value* arrptr = LLVM_DtoGEP(src,vdoffsets,"tmp",p->scopebb());
         e->mem = arrptr;
         Logger::cout() << "mem: " << *e->mem << '\n';
         e->type = elem::VAR;
@@ -2588,12 +2585,17 @@
     llvm::BasicBlock* oldend = gIR->scopeend();
 
     IRScope irs;
-    irs.begin = new llvm::BasicBlock("scope", gIR->topfunc(), oldend);
+    // remove useless branches by clearing and reusing the current basicblock
+    llvm::BasicBlock* bb = gIR->scopebegin();
+    if (bb->empty()) {
+        irs.begin = bb;
+    }
+    else {
+        irs.begin = new llvm::BasicBlock("scope", gIR->topfunc(), oldend);
+        new llvm::BranchInst(irs.begin, gIR->scopebegin());
+    }
     irs.end = new llvm::BasicBlock("endscope", gIR->topfunc(), oldend);
 
-    // pass the previous BB into this
-    new llvm::BranchInst(irs.begin, gIR->scopebegin());
-
     gIR->scope() = irs;
 
     statement->toIR(p);
--- a/gen/tollvm.c	Wed Sep 26 19:17:54 2007 +0200
+++ b/gen/tollvm.c	Thu Sep 27 06:03:06 2007 +0200
@@ -460,7 +460,11 @@
         VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
         assert(vd);
         Logger::println("vars[%d] = %s", i, vd->toChars());
-        unsigned idx = si->ad->offsetToIndex(vd->offset);
+
+        std::vector<unsigned> idxs;
+        si->ad->offsetToIndex(vd->offset, idxs);
+        assert(idxs.size() == 1);
+        unsigned idx = idxs[0];
 
         llvm::Constant* v = 0;
 
@@ -819,3 +823,17 @@
     v[1] = i1;
     return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb);
 }
+
+llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb)
+{
+    size_t n = src.size();
+    std::vector<llvm::Value*> dst(n);
+    Logger::cout() << "indices:";
+    for (size_t i=0; i<n; ++i)
+    {
+        Logger::cout() << ' ' << i;
+        dst[i] = llvm::ConstantInt::get(llvm::Type::Int32Ty, src[i], false);
+    }
+    Logger::cout() << '\n';
+    return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb);
+}
--- a/gen/tollvm.h	Wed Sep 26 19:17:54 2007 +0200
+++ b/gen/tollvm.h	Thu Sep 27 06:03:06 2007 +0200
@@ -37,5 +37,6 @@
 llvm::Function* LLVM_DeclareMemCpy64();
 
 llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb);
+llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb);
 
 #include "enums.h"
--- a/gen/toobj.c	Wed Sep 26 19:17:54 2007 +0200
+++ b/gen/toobj.c	Thu Sep 27 06:03:06 2007 +0200
@@ -139,15 +139,27 @@
 /* ================================================================== */
 
 /// Returns the LLVM style index from a DMD style offset
-unsigned AggregateDeclaration::offsetToIndex(unsigned os)
+void AggregateDeclaration::offsetToIndex(unsigned os, std::vector<unsigned>& result)
 {
+    unsigned vos = 0;
     for (unsigned i=0; i<fields.dim; ++i) {
         VarDeclaration* vd = (VarDeclaration*)fields.data[i];
-        if (os == vd->offset)
-            return i;
+        if (vd->type->ty == Tstruct) {
+            if (vos + vd->type->size() > os) {
+                TypeStruct* ts = (TypeStruct*)vd->type;
+                StructDeclaration* sd = ts->sym;
+                result.push_back(i);
+                sd->offsetToIndex(os - vos, result);
+                return;
+            }
+        }
+        else if (os == vd->offset) {
+            result.push_back(i);
+            return;
+        }
+        vos += vd->offset;
     }
     assert(0 && "Offset not found in any aggregate field");
-    return 0;
 }
 
 /* ================================================================== */
@@ -175,12 +187,12 @@
 
 /// Returns the LLVM style index from a DMD style offset
 /// Handles class inheritance
-unsigned ClassDeclaration::offsetToIndex(unsigned os)
+void ClassDeclaration::offsetToIndex(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");
-    return r+1; // vtable is 0
+    result.push_back(r+1); // vtable is 0
 }
 
 /* ================================================================== */
--- a/test/classes5.d	Wed Sep 26 19:17:54 2007 +0200
+++ b/test/classes5.d	Thu Sep 27 06:03:06 2007 +0200
@@ -13,5 +13,11 @@
 
 void main()
 {
-    //C c = new C;
+    C c = new C;
+    long* lp = void;
+    {c.s.l = 64;}
+    {assert(c.s.l == 64);}
+    {lp = &c.s.l;}
+    {assert(*lp == 64);}
+    printf("classes5 success\n");
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/scope1.d	Thu Sep 27 06:03:06 2007 +0200
@@ -0,0 +1,10 @@
+module scope1;
+
+void main()
+{
+    printf("1\n");
+    {
+        scope(exit) printf("2\n");
+    }
+    printf("3\n");
+}
--- a/test/structs3.d	Wed Sep 26 19:17:54 2007 +0200
+++ b/test/structs3.d	Thu Sep 27 06:03:06 2007 +0200
@@ -2,8 +2,8 @@
 
 struct S
 {
-    float l;
     char c;
+    float f;
 }
 
 struct T
@@ -14,4 +14,17 @@
 
 void main()
 {
+    T t;
+    float f = void;
+    float* fp = void;
+    {f = t.s.f;}
+    {t.s.f = 0.0;}
+    {fp = &t.s.f;}
+    {*fp = 1.0;}
+    {assert(t.s.f == 1.0);}
+    {assert(*(&t.s.f) == 1.0);}
+    {t.s.c = 'a';}
+    {assert(t.s.c == 'a');}
+    {t.l = 64;}
+    {assert(t.l == 64);}
 }