changeset 502:837af2a63564

Fixed problems constant multidimensional static array initializers.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Wed, 13 Aug 2008 15:43:13 +0200
parents ba7f06832d1c
children 7148a3f2b44b
files gen/llvmhelpers.cpp gen/llvmhelpers.h
diffstat 2 files changed, 75 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/gen/llvmhelpers.cpp	Tue Aug 12 00:56:09 2008 +0200
+++ b/gen/llvmhelpers.cpp	Wed Aug 13 15:43:13 2008 +0200
@@ -961,6 +961,9 @@
     llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(vd->ir.irGlobal->value);
     if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl))
     {
+        Logger::println("setting initializer");
+        Logger::cout() << "global: " << *gvar << '\n';
+        Logger::cout() << "init:   " << *_init << '\n';
         gvar->setInitializer(_init);
         // do debug info
         if (global.params.symdebug)
@@ -1258,22 +1261,7 @@
     if (!init)
     {
         Logger::println("const default initializer for %s", type->toChars());
-
-        if(type->ty == Tsarray)
-        {
-            Logger::println("type is a static array, building constant array initializer");
-            TypeSArray* arrtype = (TypeSArray*)type;
-            Type* elemtype = type->next;
-
-            integer_t arraydim;
-            arraydim = arrtype->dim->toInteger();
-
-            std::vector<LLConstant*> inits(arraydim, elemtype->defaultInit()->toConstElem(gIR));
-            const LLArrayType* arrty = LLArrayType::get(DtoType(elemtype),arraydim);
-            _init = LLConstantArray::get(arrty, inits);
-        }
-        else
-            _init = type->defaultInit()->toConstElem(gIR);
+        _init = DtoDefaultInit(type);
     }
     else if (ExpInitializer* ex = init->isExpInitializer())
     {
@@ -1396,6 +1384,74 @@
     return 0;
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+
+static LLConstant* expand_to_sarray(Type *base, Expression* exp)
+{
+    Logger::println("building type %s from expression (%s) of type %s", base->toChars(), exp->toChars(), exp->type->toChars());
+    const LLType* dstTy = DtoType(base);
+    Logger::cout() << "final llvm type requested: " << *dstTy << '\n';
+    
+    LLConstant* val = exp->toConstElem(gIR);
+    
+    Type* expbase = exp->type->toBasetype();
+    Type* t = base;
+    
+    LLSmallVector<size_t, 4> dims;
+
+    while(1)
+    {
+        if (t->equals(expbase))
+            break;
+        assert(t->ty == Tsarray);
+        TypeSArray* tsa = (TypeSArray*)t;
+        dims.push_back(tsa->dim->toInteger());
+        assert(t->next);
+        t = t->next->toBasetype();
+    }
+    
+    size_t i = dims.size();
+    assert(i);
+
+    std::vector<LLConstant*> inits;
+    while (i--)
+    {
+        const LLArrayType* arrty = LLArrayType::get(val->getType(), dims[i]);
+        inits.clear();
+        inits.insert(inits.end(), dims[i], val);
+        val = LLConstantArray::get(arrty, inits);
+    }
+    
+    return val;
+}
+
+LLConstant* DtoDefaultInit(Type* type)
+{
+    Expression* exp = type->defaultInit();
+    
+    Type* expbase = exp->type->toBasetype();
+    Type* base = type->toBasetype();
+    
+    // if not the same basetypes, we won't get the same llvm types either
+    if (!expbase->equals(base))
+    {
+        if (base->ty == Tsarray)
+        {
+            Logger::println("type is a static array, building constant array initializer from single value");
+            return expand_to_sarray(base, exp);
+        }
+        else
+        {
+            error("cannot yet convert default initializer %s from type %s to %s", exp->toChars(), exp->type->toChars(), type->toChars());
+            fatal();
+        }
+        assert(0);
+        
+    }
+    
+    return exp->toConstElem(gIR);
+}
+
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
--- a/gen/llvmhelpers.h	Tue Aug 12 00:56:09 2008 +0200
+++ b/gen/llvmhelpers.h	Wed Aug 13 15:43:13 2008 +0200
@@ -105,6 +105,9 @@
 /// Converts any value to a boolean (llvm i1)
 LLValue* DtoBoolean(Loc& loc, DValue* dval);
 
+/// get the default initializer of the type
+LLConstant* DtoDefaultInit(Type* t);
+
 ////////////////////////////////////////////
 // gen/tocall.cpp stuff below
 ////////////////////////////////////////////