# HG changeset patch # User Tomas Lindquist Olsen # Date 1218634993 -7200 # Node ID 837af2a63564f1692821a1e80c0a5b9855daa7b9 # Parent ba7f06832d1c478fa3a473b7b7fac897ca1aeee2 Fixed problems constant multidimensional static array initializers. diff -r ba7f06832d1c -r 837af2a63564 gen/llvmhelpers.cpp --- 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(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 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 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 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); +} + ////////////////////////////////////////////////////////////////////////////////////////// diff -r ba7f06832d1c -r 837af2a63564 gen/llvmhelpers.h --- 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 ////////////////////////////////////////////