changeset 76:9e1bd80a7e98 trunk

[svn r80] Fixed union literals
author lindquist
date Wed, 31 Oct 2007 07:24:02 +0100
parents ab8f5ec40a14
children 714057ff2dbb
files gen/toir.c test/union4.d test/union5.d
diffstat 3 files changed, 96 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/gen/toir.c	Wed Oct 31 04:55:48 2007 +0100
+++ b/gen/toir.c	Wed Oct 31 07:24:02 2007 +0100
@@ -1667,36 +1667,52 @@
     LOG_SCOPE;
     elem* e = new elem;
 
-    llvm::Value* sptr = 0;
-
-    // if there is no lval, this is probably a temporary struct literal. correct?
+    llvm::Value* sptr;
+    const llvm::Type* llt = LLVM_DtoType(type);
+
+    // temporary struct literal
     if (!p->topexp() || p->topexp()->e2 != this)
     {
-        sptr = new llvm::AllocaInst(LLVM_DtoType(type),"tmpstructliteral",p->topallocapoint());
+        sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint());
         e->mem = sptr;
         e->type = elem::VAR;
     }
     // already has memory
-    else if (p->topexp()->e2 == this)
+    else
     {
+        assert(p->topexp()->e2 == this);
         sptr = p->topexp()->v;
     }
-    else
-    assert(0);
-
-    assert(sptr);
-
-    llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    if (sd->isUnionDeclaration()) {
-        Logger::println("num elements = %d", elements->dim);
-        //assert(elements->dim == 1);
-        Expression* vx = (Expression*)elements->data[0];
-        assert(vx);
-
-        Type* vxtype = LLVM_DtoDType(vx->type);
-        const llvm::Type* llvxty = llvm::PointerType::get(LLVM_DtoType(vxtype));
-        llvm::Value* arrptr = p->ir->CreateBitCast(sptr, llvxty, "tmp");
+
+    // num elements in literal
+    unsigned n = elements->dim;
+
+    // unions might have different types for each literal
+    if (sd->llvmHasUnions) {
+        // build the type of the literal
+        std::vector<const llvm::Type*> tys;
+        for (unsigned i=0; i<n; ++i) {
+            Expression* vx = (Expression*)elements->data[i];
+            if (!vx) continue;
+            tys.push_back(LLVM_DtoType(vx->type));
+        }
+        const llvm::StructType* t = llvm::StructType::get(tys);
+        if (t != llt) {
+            assert(gTargetData->getTypeSize(t) == gTargetData->getTypeSize(llt));
+            sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp");
+            Logger::cout() << "sptr type is now: " << *t << '\n';
+        }
+    }
+
+    // build
+    unsigned j = 0;
+    for (unsigned i=0; i<n; ++i)
+    {
+        Expression* vx = (Expression*)elements->data[i];
+        if (!vx) continue;
+
+        Logger::cout() << "getting index " << j << " of " << *sptr << '\n';
+        llvm::Value* arrptr = LLVM_DtoGEPi(sptr,0,j,"tmp",p->scopebb());
 
         p->exps.push_back(IRExp(NULL,vx,arrptr));
         elem* ve = vx->toElem(p);
@@ -1705,36 +1721,13 @@
         if (!ve->inplace) {
             llvm::Value* val = ve->getValue();
             Logger::cout() << *val << " | " << *arrptr << '\n';
+
+            Type* vxtype = LLVM_DtoDType(vx->type);
             LLVM_DtoAssign(vxtype, arrptr, val);
         }
         delete ve;
-    }
-    else {
-        unsigned n = elements->dim;
-        for (unsigned i=0; i<n; ++i)
-        {
-            llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
-            llvm::Value* arrptr = LLVM_DtoGEP(sptr,zero,offset,"tmp",p->scopebb());
-
-            Expression* vx = (Expression*)elements->data[i];
-            if (vx != 0) {
-                p->exps.push_back(IRExp(NULL,vx,arrptr));
-                elem* ve = vx->toElem(p);
-                p->exps.pop_back();
-
-                if (!ve->inplace) {
-                    llvm::Value* val = ve->getValue();
-                    Logger::cout() << *val << " | " << *arrptr << '\n';
-
-                    Type* vxtype = LLVM_DtoDType(vx->type);
-                    LLVM_DtoAssign(vxtype, arrptr, val);
-                }
-                delete ve;
-            }
-            else {
-                assert(0);
-            }
-        }
+
+        j++;
     }
 
     e->inplace = true;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/union4.d	Wed Oct 31 07:24:02 2007 +0100
@@ -0,0 +1,16 @@
+module union4;
+
+pragma(LLVM_internal, "notypeinfo")
+union U {
+    struct { float x,y,z; }
+    float[3] xyz;
+}
+
+void main() {
+    const float[3] a = [1f,2,3];
+    U u = U(1,2,3);
+    assert(u.xyz == a);
+    assert(u.x == 1);
+    assert(u.y == 2);
+    assert(u.z == 3);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/union5.d	Wed Oct 31 07:24:02 2007 +0100
@@ -0,0 +1,39 @@
+module union5;
+
+pragma(LLVM_internal, "notypeinfo")
+{
+    union S
+    {
+        T t;
+        U u;
+        uint i;
+        struct {
+            ushort sl,sh;
+        }
+    }
+
+    struct T
+    {
+        int i;
+    }
+
+    struct U
+    {
+        float f;
+    }
+}
+
+void main()
+{
+    S s;
+    assert(s.t.i == 0);
+    assert(s.u.f == 0);
+    s.t.i = -1;
+    assert(s.i == 0xFFFF_FFFF);
+    float f = 3.1415;
+    s.u.f = f;
+    uint pi = *cast(uint*)&f;
+    assert(s.i == pi);
+    assert(s.sl == (pi&0xFFFF));
+    assert(s.sh == (pi>>>16));
+}