changeset 175:c44e6a711885 trunk

[svn r191] Fixed: array literals did not support all type/storage combinations. Fixed: with expression had broke somewhere along the way.
author lindquist
date Wed, 07 May 2008 00:01:13 +0200
parents 16e676ae5ab4
children a074a5ff709c
files gen/statements.cpp gen/toir.cpp ir/irsymbol.cpp ir/irsymbol.h test/arrays.d test/arrays13.d test/arrays4.d test/arrays7.d test/arrays8.d test/with1.d
diffstat 10 files changed, 78 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/gen/statements.cpp	Tue May 06 18:36:46 2008 +0200
+++ b/gen/statements.cpp	Wed May 07 00:01:13 2008 +0200
@@ -1053,8 +1053,9 @@
     assert(body);
 
     DValue* e = exp->toElem(p);
+    assert(!wthis->ir.isSet());
+    wthis->ir.irLocal = new IrLocal(wthis);
     wthis->ir.irLocal->value = e->getRVal();
-    delete e;
 
     body->toIR(p);
 }
--- a/gen/toir.cpp	Tue May 06 18:36:46 2008 +0200
+++ b/gen/toir.cpp	Wed May 07 00:01:13 2008 +0200
@@ -2550,66 +2550,76 @@
     Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    Type* ty = DtoDType(type);
-    const llvm::Type* t = DtoType(ty);
-    Logger::cout() << "array literal has llvm type: " << *t << '\n';
-
-    llvm::Value* mem = 0;
-    bool inplace_slice = false;
-
-    if (!p->topexp() || p->topexp()->e2 != this) {
-        assert(DtoDType(type)->ty == Tsarray);
-        mem = new llvm::AllocaInst(t,"arrayliteral",p->topallocapoint());
+    // D types
+    Type* arrayType = type->toBasetype();
+    Type* elemType = arrayType->nextOf()->toBasetype();
+
+    // is dynamic ?
+    bool dyn = (arrayType->ty == Tarray);
+    // length
+    size_t len = elements->dim;
+    // store into slice?
+    bool sliceInPlace = false;
+
+    // llvm target type
+    const llvm::Type* llType = DtoType(arrayType);
+    Logger::cout() << (dyn?"dynamic":"static") << " array literal with length " << len << " of D type: '" << arrayType->toChars() << "' has llvm type: '" << *llType << "'\n";
+
+    // llvm storage type
+    const llvm::Type* llStoType = llvm::ArrayType::get(DtoType(elemType), len);
+    Logger::cout() << "llvm storage type: '" << *llStoType << "'\n";
+
+    // dst pointer
+    llvm::Value* dstMem = 0;
+
+    // rvalue of assignment
+    if (p->topexp() && p->topexp()->e2 == this)
+    {
+        DValue* topval = p->topexp()->v;
+        // slice assignment (copy)
+        if (DSliceValue* s = topval->isSlice())
+        {
+            dstMem = s->ptr;
+            sliceInPlace = true;
+            assert(s->len == NULL);
+        }
+        // static array assignment
+        else if (topval->getType()->toBasetype()->ty == Tsarray)
+        {
+            dstMem = topval->getLVal();
+        }
+        // otherwise we still need to alloca storage
     }
-    else if (p->topexp()->e2 == this) {
-        DValue* tlv = p->topexp()->v;
-        if (DSliceValue* sv = tlv->isSlice()) {
-            assert(sv->len == 0);
-            mem = sv->ptr;
-            inplace_slice = true;
-        }
-        else {
-            mem = p->topexp()->v->getLVal();
-        }
-        assert(mem);
-        if (!isaPointer(mem->getType()) ||
-            !isaArray(mem->getType()->getContainedType(0)))
-        {
-            assert(!inplace_slice);
-            assert(ty->ty == Tarray);
-            // we need to give this array literal storage
-            const llvm::ArrayType* arrty = llvm::ArrayType::get(DtoType(ty->next), elements->dim);
-            mem = new llvm::AllocaInst(arrty, "arrayliteral", p->topallocapoint());
-        }
+
+    // alloca storage if not found already
+    if (!dstMem)
+    {
+        dstMem = new llvm::AllocaInst(llStoType, "arrayliteral", p->topallocapoint());
     }
-    else
-    assert(0);
-
-    Logger::cout() << "array literal mem: " << *mem << '\n';
-
-    for (unsigned i=0; i<elements->dim; ++i)
+    Logger::cout() << "using dest mem: " << *dstMem << '\n';
+
+    // store elements
+    for (size_t i=0; i<len; ++i)
     {
         Expression* expr = (Expression*)elements->data[i];
-        llvm::Value* elemAddr = DtoGEPi(mem,0,i,"tmp",p->scopebb());
+        llvm::Value* elemAddr = DtoGEPi(dstMem,0,i,"tmp",p->scopebb());
+
+        // emulate assignment
         DVarValue* vv = new DVarValue(expr->type, elemAddr, true);
         p->exps.push_back(IRExp(NULL, expr, vv));
         DValue* e = expr->toElem(p);
         p->exps.pop_back();
-
         DImValue* im = e->isIm();
         if (!im || !im->inPlace()) {
             DtoAssign(vv, e);
         }
     }
 
-    if (ty->ty == Tsarray || (ty->ty == Tarray && inplace_slice))
-        return new DImValue(type, mem, true);
-    else if (ty->ty == Tarray)
-        return new DSliceValue(type, DtoConstSize_t(elements->dim), DtoGEPi(mem,0,0,"tmp"));
-    else {
-        assert(0);
-        return 0;
-    }
+    // return storage directly ?
+    if (!dyn || (dyn && sliceInPlace))
+        return new DImValue(type, dstMem, true);
+    // wrap in a slice
+    return new DSliceValue(type, DtoConstSize_t(len), DtoGEPi(dstMem,0,0,"tmp"));
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/ir/irsymbol.cpp	Tue May 06 18:36:46 2008 +0200
+++ b/ir/irsymbol.cpp	Wed May 07 00:01:13 2008 +0200
@@ -51,6 +51,11 @@
     irField = NULL;
 }
 
+bool IrDsymbol::isSet()
+{
+    return (irStruct || irFunc || irGlobal || irLocal || irField);
+}
+
 IrVar* IrDsymbol::getIrVar()
 {
     assert(irGlobal || irLocal || irField);
--- a/ir/irsymbol.h	Tue May 06 18:36:46 2008 +0200
+++ b/ir/irsymbol.h	Wed May 07 00:01:13 2008 +0200
@@ -47,6 +47,8 @@
     IrField* irField;
     IrVar* getIrVar();
     llvm::Value*& getIrValue();
+
+    bool isSet();
 };
 
 #endif
--- a/test/arrays.d	Tue May 06 18:36:46 2008 +0200
+++ b/test/arrays.d	Wed May 07 00:01:13 2008 +0200
@@ -1,3 +1,5 @@
+extern(C) int printf(char*, ...);
+
 void integer()
 {
     auto arr = new int[16];
--- a/test/arrays13.d	Tue May 06 18:36:46 2008 +0200
+++ b/test/arrays13.d	Wed May 07 00:01:13 2008 +0200
@@ -1,8 +1,10 @@
 module arrays13;
 
+extern(C) int printf(char*, ...);
+
 void main()
 {
-    string a = "hello";
+    char[] a = "hello";
 
     assert(a >  "hel");
     assert(a >= "hel");
--- a/test/arrays4.d	Tue May 06 18:36:46 2008 +0200
+++ b/test/arrays4.d	Wed May 07 00:01:13 2008 +0200
@@ -1,5 +1,5 @@
 module arrays4;
-import std.stdio;
+
 void main()
 {
     int[] arr;
@@ -10,5 +10,4 @@
     assert(arr.length == 2);
     assert(arr[0] == 3);
     assert(arr[1] == 5);
-    writefln(arr);
 }
--- a/test/arrays7.d	Tue May 06 18:36:46 2008 +0200
+++ b/test/arrays7.d	Wed May 07 00:01:13 2008 +0200
@@ -1,5 +1,7 @@
 module arrays7;
 
+extern(C) int printf(char*, ...);
+
 pragma(LLVM_internal, "notypeinfo")
 struct S
 {
--- a/test/arrays8.d	Tue May 06 18:36:46 2008 +0200
+++ b/test/arrays8.d	Wed May 07 00:01:13 2008 +0200
@@ -1,5 +1,7 @@
 module arrays8;
 
+extern(C) int printf(char*, ...);
+
 void main()
 {
     char[] a = "hello ";
--- a/test/with1.d	Tue May 06 18:36:46 2008 +0200
+++ b/test/with1.d	Wed May 07 00:01:13 2008 +0200
@@ -10,6 +10,8 @@
     with(s)
     {
         i = 0;
-        f = 3.4;
+        f = 3.5;
     }
+    assert(s.i == 0);
+    assert(s.f == 3.5);
 }