diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index c36d5641..ad4a1849 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -985,51 +985,6 @@ void DtoResolveDsymbol(Dsymbol* dsym) } } -////////////////////////////////////////////////////////////////////////////////////////// - -void DtoConstInitGlobal(VarDeclaration* vd) -{ - vd->codegen(Type::sir); - - if (vd->ir.initialized) return; - vd->ir.initialized = gIR->dmodule; - - Logger::println("DtoConstInitGlobal(%s) @ %s", vd->toChars(), vd->loc.toChars()); - LOG_SCOPE; - - // build the initializer - LLConstant* initVal = DtoConstInitializer(vd->loc, vd->type, vd->init); - - // set the initializer if appropriate - IrGlobal* glob = vd->ir.irGlobal; - llvm::GlobalVariable* gvar = llvm::cast(glob->value); - - //if (LLStructType *st = isaStruct(glob->type)) { - // st->setBody(initVal); - //} - - assert(!glob->constInit); - glob->constInit = initVal; - - // assign the initializer - if (!(vd->storage_class & STCextern) && mustDefineSymbol(vd)) - { - if (Logger::enabled()) - { - Logger::println("setting initializer"); - Logger::cout() << "global: " << *gvar << '\n'; -#if 0 - Logger::cout() << "init: " << *initVal << '\n'; -#endif - } - - gvar->setInitializer(initVal); - - // do debug info - DtoDwarfGlobalVariable(gvar, vd); - } -} - /****************************************************************************************/ /*//////////////////////////////////////////////////////////////////////////////////////// // DECLARATION EXP HELPER @@ -1116,7 +1071,15 @@ void DtoVarDeclaration(VarDeclaration* vd) if (Logger::enabled()) Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n'; - DtoInitializer(vd->ir.irLocal->value, vd->init); // TODO: Remove altogether? + if (vd->init) + { + if (ExpInitializer* ex = vd->init->isExpInitializer()) + { + // TODO: Refactor this so that it doesn't look like toElem has no effect. + Logger::println("expression initializer"); + ex->exp->toElem(gIR); + } + } Lexit: /* Mark the point of construction of a variable that needs to be destructed. @@ -1345,51 +1308,11 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init) ////////////////////////////////////////////////////////////////////////////////////////// -DValue* DtoInitializer(LLValue* target, Initializer* init) +static LLConstant* expand_to_sarray(Type* targetType, Type* initType, LLConstant* initConst) { - if (!init) - return 0; - - if (ExpInitializer* ex = init->isExpInitializer()) - { - Logger::println("expression initializer"); - assert(ex->exp); - return ex->exp->toElem(gIR); - } - else if (init->isArrayInitializer()) - { - // TODO: do nothing ? - } - else if (init->isVoidInitializer()) - { - // do nothing - } - else if (init->isStructInitializer()) - { - // TODO: again nothing ? - } - else - { - llvm_unreachable("Unknown initializer type."); - } - - 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()); - LLType* dstTy = DtoType(base); - if (Logger::enabled()) - Logger::cout() << "final llvm type requested: " << *dstTy << '\n'; - - LLConstant* val = exp->toConstElem(gIR); - - Type* expbase = stripModifiers(exp->type->toBasetype()); - Logger::println("expbase: %s", expbase->toChars()); - Type* t = base->toBasetype(); + Type* expbase = stripModifiers(initType); + IF_LOG Logger::println("expbase: %s", expbase->toChars()); + Type* t = targetType; LLSmallVector dims; @@ -1411,56 +1334,93 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp) std::vector inits; while (i--) { - LLArrayType* arrty = LLArrayType::get(val->getType(), dims[i]); + LLArrayType* arrty = LLArrayType::get(initConst->getType(), dims[i]); inits.clear(); - inits.insert(inits.end(), dims[i], val); - val = LLConstantArray::get(arrty, inits); + inits.insert(inits.end(), dims[i], initConst); + initConst = LLConstantArray::get(arrty, inits); } - return val; + return initConst; } -LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp) +LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp) { - Type* expbase = stripModifiers(exp->type->toBasetype())->merge(); - Type* base = stripModifiers(type->toBasetype())->merge(); + IF_LOG Logger::println("DtoConstExpInit(targetType = %s, exp = %s)", + targetType->toChars(), exp->toChars()); + LOG_SCOPE - // if not the same basetypes, we won't get the same llvm types either - if (!expbase->equals(base)) + LLConstant* val = exp->toConstElem(gIR); + + // The situation here is a bit tricky: In an ideal world, we would always + // have val->getType() == DtoType(targetType). But there are two reasons + // why this is not true. One is that the LLVM type system cannot represent + // all the C types, leading to differences in types being necessary e.g. for + // union initializers. The second is that the frontend actually does not + // explicitly lowers things like initializing an array/vector with a scalar + // constant, or since 2.061 sometimes does not get implicit conversions for + // integers right. However, we cannot just rely on the actual Types being + // equal if there are no rewrites to do because of – as usual – AST + // inconsistency bugs. + + Type* expBase = stripModifiers(exp->type->toBasetype())->merge(); + Type* targetBase = stripModifiers(targetType->toBasetype())->merge(); + + if (expBase->equals(targetBase)) { - if (base->ty == Tsarray) - { - if (base->nextOf()->toBasetype()->ty == Tvoid) { - error(loc, "static arrays of voids have no default initializer"); - fatal(); - } - Logger::println("type is a static array, building constant array initializer to single value"); - return expand_to_sarray(base, exp); - } - - if (base->ty == Tvector) - { - LLConstant* val = exp->toConstElem(gIR); - - TypeVector* tv = (TypeVector*)base; - assert(tv->basetype->ty == Tsarray); - dinteger_t elemCount = - static_cast(tv->basetype)->dim->toInteger(); - -#if LDC_LLVM_VER == 300 - std::vector Elts(elemCount, val); - return llvm::ConstantVector::get(Elts); -#else - return llvm::ConstantVector::getSplat(elemCount, val); -#endif - } - - error(loc, "LDC internal error: cannot yet convert default initializer %s of type %s to %s", - exp->toChars(), exp->type->toChars(), type->toChars()); - llvm_unreachable("Unsupported default initializer."); + Logger::println("Matching D types, nothing left to do."); + return val; } - return exp->toConstElem(gIR); + llvm::Type* llType = val->getType(); + llvm::Type* targetLLType = DtoType(targetBase); + if (llType == targetLLType) + { + Logger::println("Matching LLVM types, ignoring frontend glitch."); + return val; + } + + if (targetBase->ty == Tsarray) + { + if (targetBase->nextOf()->toBasetype()->ty == Tvoid) { + error(loc, "static arrays of voids have no default initializer"); + fatal(); + } + Logger::println("Building constant array initializer to single value."); + return expand_to_sarray(targetBase, expBase, val); + } + + if (targetBase->ty == Tvector) + { + Logger::println("Building vector initializer from scalar."); + + TypeVector* tv = static_cast(targetBase); + assert(tv->basetype->ty == Tsarray); + dinteger_t elemCount = + static_cast(tv->basetype)->dim->toInteger(); + +#if LDC_LLVM_VER == 300 + std::vector Elts(elemCount, val); + return llvm::ConstantVector::get(Elts); +#else + return llvm::ConstantVector::getSplat(elemCount, val); +#endif + } + + if (llType->isIntegerTy() && targetLLType->isIntegerTy()) + { + // This should really be fixed in the frontend. + Logger::println("Fixing up unresolved implicit integer conversion."); + + llvm::IntegerType* source = llvm::cast(llType); + llvm::IntegerType* target = llvm::cast(targetLLType); + + assert(target->getBitWidth() > source->getBitWidth() && "On initializer " + "integer type mismatch, the target should be wider than the source."); + return llvm::ConstantExpr::getZExtOrBitCast(val, target); + } + + Logger::println("Unhandled type mismatch, giving up."); + return val; } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index efd37be2..fc807b7d 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -108,9 +108,6 @@ TemplateInstance* DtoIsTemplateInstance(Dsymbol* s, bool checkLiteralOwner = fal /// Dispatches as appropriate. void DtoResolveDsymbol(Dsymbol* dsym); -/// Generates the constant initializer for a global variable. -void DtoConstInitGlobal(VarDeclaration* vd); - // declaration inside a declarationexp void DtoVarDeclaration(VarDeclaration* var); DValue* DtoDeclarationExp(Dsymbol* declaration); @@ -118,8 +115,7 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr = 0); // initializer helpers LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init); -LLConstant* DtoConstExpInit(Loc loc, Type* t, Expression* exp); -DValue* DtoInitializer(LLValue* target, Initializer* init); +LLConstant* DtoConstExpInit(Loc loc, Type* targetType, Expression* exp); // getting typeinfo of type, base=true casts to object.TypeInfo LLConstant* DtoTypeInfoOf(Type* ty, bool base=true); diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 7ee870da..2d8d874e 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 7ee870da26b38c32b98b7ca7fafd755f1f43be40 +Subproject commit 2d8d874e2a33cea9d9fd751f9c2baab5e8ccc992