changeset 64:b688ad419f8c trunk

[svn r68] Added support for multi-dimensional static arrays. Several bugfixes to array support.
author lindquist
date Thu, 25 Oct 2007 12:09:13 +0200
parents 2c39b5292cf3
children d4a678905d5e
files gen/arrays.c gen/arrays.h gen/toir.c gen/toobj.c lphobos/internal/arrays.d test/multiarr1.d test/multiarr2.d test/multiarr3.d test/multiarr4.d
diffstat 9 files changed, 140 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/gen/arrays.c	Thu Oct 25 10:05:21 2007 +0200
+++ b/gen/arrays.c	Thu Oct 25 12:09:13 2007 +0200
@@ -143,24 +143,53 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+typedef const llvm::Type* constLLVMTypeP;
+
+static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty)
+{
+    if (llvm::isa<llvm::ArrayType>(pt)) {
+        size_t n = checkRectArrayInit(pt->getContainedType(0), finalty);
+        size_t ne = llvm::cast<llvm::ArrayType>(pt)->getNumElements();
+        if (n) return n * ne;
+        return ne;
+    }
+    finalty = pt;
+    return 0;
+}
+
 void LLVM_DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
 {
-    const llvm::Type* t = ptr->getType()->getContainedType(0);
+    const llvm::Type* pt = ptr->getType()->getContainedType(0);
+    const llvm::Type* t = val->getType();
+    const llvm::Type* finalTy;
+    if (size_t arrsz = checkRectArrayInit(pt, finalTy)) {
+        assert(finalTy == t);
+        llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(dim);
+        assert(c);
+        dim = llvm::ConstantExpr::getMul(c, LLVM_DtoConstSize_t(arrsz));
+        ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp");
+    }
+    else if (llvm::isa<llvm::StructType>(t)) {
+        assert(0);
+    }
+    else {
+        assert(t == pt);
+    }
 
     std::vector<llvm::Value*> args;
     args.push_back(ptr);
     args.push_back(dim);
     args.push_back(val);
-    
+
     const char* funcname = NULL;
-    
+
     if (llvm::isa<llvm::PointerType>(t)) {
         funcname = "_d_array_init_pointer";
-        
+
         const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
         if (args[0]->getType() != dstty)
             args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb());
-        
+
         const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty);
         if (args[2]->getType() != valty)
             args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb());
@@ -187,6 +216,7 @@
         funcname = "_d_array_init_double";
     }
     else {
+        Logger::cout() << *ptr->getType() << " = " << *val->getType() << '\n';
         assert(0);
     }
 
@@ -607,3 +637,21 @@
     llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
     return b;
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Constant* LLVM_DtoConstantStaticArray(const llvm::Type* t, llvm::Constant* c)
+{
+    assert(llvm::isa<llvm::ArrayType>(t));
+    const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(t);
+
+    if (llvm::isa<llvm::ArrayType>(at->getElementType()))
+    {
+        c = LLVM_DtoConstantStaticArray(at->getElementType(), c);
+    }
+    else {
+        assert(at->getElementType() == c->getType());
+    }
+    std::vector<llvm::Constant*> initvals;
+    initvals.resize(at->getNumElements(), c);
+    return llvm::ConstantArray::get(at, initvals);
+}
--- a/gen/arrays.h	Thu Oct 25 10:05:21 2007 +0200
+++ b/gen/arrays.h	Thu Oct 25 12:09:13 2007 +0200
@@ -6,6 +6,7 @@
 
 llvm::Constant* LLVM_DtoConstArrayInitializer(ArrayInitializer* si);
 llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr);
+llvm::Constant* LLVM_DtoConstantStaticArray(const llvm::Type* t, llvm::Constant* c);
 
 void LLVM_DtoArrayCopy(elem* dst, elem* src);
 void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r);
--- a/gen/toir.c	Thu Oct 25 10:05:21 2007 +0200
+++ b/gen/toir.c	Thu Oct 25 12:09:13 2007 +0200
@@ -1458,32 +1458,41 @@
             vdt->sym->offsetToIndex(t->next, offset, dst);
             llvm::Value* ptr = llvalue;
             assert(ptr);
-            e->mem = LLVM_DtoGEP(ptr,dst,"tmp",p->scopebb());
+            e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
             e->type = elem::VAL;
             e->field = true;
         }
         else if (vdtype->ty == Tsarray) {
-            /*e = new elem;
-            llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-            e->val = new llvm::GetElementPtrInst(vd->llvmValue,idx0,idx0,"tmp",p->scopebb());*/
             e = new elem;
-            llvm::Value* idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-            //llvm::Value* idx1 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-            e->mem = LLVM_DtoGEP(llvalue,idx0,idx0,"tmp",p->scopebb());
+            assert(llvalue);
             e->arg = llvalue;
             e->type = elem::VAL;
+
+            const llvm::Type* llt = LLVM_DtoType(t);
+            llvm::Value* off = 0;
+            if (offset != 0) {
+                Logger::println("offset = %d\n", offset);
+            }
+            if (llvalue->getType() != llt) {
+                e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
+                if (offset != 0)
+                    e->mem = LLVM_DtoGEPi(e->mem, offset, "tmp");
+            }
+            else {
+                assert(offset == 0);
+                e->mem = LLVM_DtoGEPi(llvalue,0,0,"tmp");
+            }
         }
         else if (offset == 0) {
             e = new elem;
+            e->type = elem::VAL;
             assert(llvalue);
             e->mem = llvalue;
+
             const llvm::Type* llt = LLVM_DtoType(t);
             if (llvalue->getType() != llt) {
-                Logger::cout() << "llt is:" << *llt << '\n';
-                //const llvm::PointerType* vpty = llvm::PointerType::get(llvm::Type::Int8Ty);
                 e->mem = p->ir->CreateBitCast(e->mem, llt, "tmp");
             }
-            e->type = elem::VAL;
         }
         else {
             assert(0);
@@ -2009,6 +2018,7 @@
 
     if (t->isintegral() || t->ty == Tpointer)
     {
+        Logger::println("integral or pointer");
         llvm::ICmpInst::Predicate cmpop;
         switch(op)
         {
@@ -2025,6 +2035,7 @@
     }
     else if (t->isfloating())
     {
+        Logger::println("floating");
         llvm::FCmpInst::Predicate cmpop;
         switch(op)
         {
@@ -2041,14 +2052,17 @@
     }
     else if (t->ty == Tsarray)
     {
+        Logger::println("static array");
         e->val = LLVM_DtoStaticArrayCompare(op,l->mem,r->mem);
     }
     else if (t->ty == Tarray)
     {
+        Logger::println("dynamic array");
         e->val = LLVM_DtoDynArrayCompare(op,l->mem,r->mem);
     }
     else if (t->ty == Tdelegate)
     {
+        Logger::println("delegate");
         e->val = LLVM_DtoCompareDelegate(op,l->mem,r->mem);
     }
     else
--- a/gen/toobj.c	Thu Oct 25 10:05:21 2007 +0200
+++ b/gen/toobj.c	Thu Oct 25 12:09:13 2007 +0200
@@ -35,6 +35,7 @@
 #include "gen/elem.h"
 #include "gen/logger.h"
 #include "gen/tollvm.h"
+#include "gen/arrays.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
@@ -546,15 +547,7 @@
                 // array single value init
                 else if (llvm::isa<llvm::ArrayType>(_type))
                 {
-                    const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(_type);
-                    if (at->getElementType() == _init->getType()) {
-                        std::vector<llvm::Constant*> initvals;
-                        initvals.resize(at->getNumElements(), _init);
-                        _init = llvm::ConstantArray::get(at, initvals);
-                    }
-                    else {
-                        assert(0);
-                    }
+                    _init = LLVM_DtoConstantStaticArray(_type, _init);
                 }
                 else {
                     Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
@@ -562,6 +555,7 @@
                 }
             }
 
+            Logger::cout() << "final init = " << *_init << '\n';
             gvar->setInitializer(_init);
         }
 
--- a/lphobos/internal/arrays.d	Thu Oct 25 10:05:21 2007 +0200
+++ b/lphobos/internal/arrays.d	Thu Oct 25 12:09:13 2007 +0200
@@ -1,7 +1,16 @@
 module internal.arrays;
 
+private import llvm.intrinsic;
+
 extern(C):
 
+int memcmp(void*,void*,size_t);
+
+version(LLVM64)
+alias llvm_memcpy_i64 llvm_memcpy;
+else
+alias llvm_memcpy_i32 llvm_memcpy;
+
 // per-element array init routines
 
 void _d_array_init_i1(bool* a, size_t n, bool v)
@@ -68,8 +77,17 @@
         *p++ = v;
 }
 
+void _d_array_init(void* a, size_t na, void* v, size_t nv)
+{
+    auto p = a;
+    auto end = a + na*nv;
+    while (p !is end) {
+        llvm_memcpy(p,v,nv,0);
+        p += nv;
+    }
+}
+
 // array comparison routines
-int memcmp(void*,void*,size_t);
 
 bool _d_static_array_eq(void* lhs, void* rhs, size_t bytesize)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/multiarr1.d	Thu Oct 25 12:09:13 2007 +0200
@@ -0,0 +1,10 @@
+module multiarr1;
+
+void main()
+{
+    int[16][16] a;
+    a[10][13] = 42;
+    assert(a[0][0] == 0);
+    assert(a[10][13] == 42);
+    {assert(*((cast(int*)a)+10*16+13) == 42);}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/multiarr2.d	Thu Oct 25 12:09:13 2007 +0200
@@ -0,0 +1,7 @@
+module multiarr2;
+
+void main()
+{
+    static float[1][2][3] arr;
+    assert(arr[2][1][0] !<>= float.nan);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/multiarr3.d	Thu Oct 25 12:09:13 2007 +0200
@@ -0,0 +1,10 @@
+module multiarr3;
+
+void main()
+{
+    static int[2][2] arr = [[1,2],[3,4]];
+    assert(arr[0][0] == 1);
+    assert(arr[0][1] == 2);
+    assert(arr[1][0] == 3);
+    assert(arr[1][1] == 4);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/multiarr4.d	Thu Oct 25 12:09:13 2007 +0200
@@ -0,0 +1,13 @@
+module multiarr4;
+
+void main()
+{
+    char[][] a;
+    a.length = 2;
+    a[0] = "hello";
+    a[1] = "world";
+    foreach(v;a)
+    {
+        printf("%.*s\n", v.length, v.ptr);
+    }
+}