mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 08:01:11 +03:00
Use the regular LL type for all init symbols and most globals
There's no <Type>_init type for aggregates (structs and classes) anymore, effectively eliminating a *lot* of named LLVM types, some bitcasts as well as replacements of globals etc. To get there, it was even required to use the regular type for compatible literals too, otherwise structs embedded as fields in other aggregates had an anonymous type (well, the LLVM constant for the field initializer had) and so the container initializer wasn't compatible with the regular type anymore. What was also necessary was a fix wrt. static arrays of bools (LLVM constant of type `[N x i1]` vs. `[N x i8]` for regular type). I also had to change the initializer for `char[2][3] x = 0xff` from `[6 x i8]` to `[3 x [2 x i8]]`, i.e., NOT flattening multi-dimensional inits from a scalar. So only literals with overlapping (union) fields and an explicit initializer initializing dominated non-alias union fields should still have a mismatching anonymous type - i.e., very, very few cases.
This commit is contained in:
parent
e6537ba4dc
commit
ab1432ed06
8 changed files with 164 additions and 71 deletions
|
@ -1099,48 +1099,73 @@ LLConstant *DtoConstExpInit(Loc &loc, Type *targetType, Expression *exp) {
|
|||
LOG_SCOPE
|
||||
|
||||
LLConstant *val = toConstElem(exp, gIR);
|
||||
Type *baseValType = exp->type->toBasetype();
|
||||
Type *baseTargetType = targetType->toBasetype();
|
||||
|
||||
// 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
|
||||
// explicitly lower 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();
|
||||
LLType *llType = val->getType();
|
||||
LLType *targetLLType = DtoMemType(baseTargetType);
|
||||
|
||||
if (expBase->equals(targetBase) && targetBase->ty != Tbool) {
|
||||
// shortcut for zeros
|
||||
if (val->isNullValue())
|
||||
return llvm::Constant::getNullValue(targetLLType);
|
||||
|
||||
if (llType == targetLLType)
|
||||
return val;
|
||||
|
||||
// extend i1 to i8
|
||||
if (llType == LLType::getInt1Ty(gIR->context())) {
|
||||
llType = LLType::getInt8Ty(gIR->context());
|
||||
val = llvm::ConstantExpr::getZExt(val, llType);
|
||||
|
||||
if (llType == targetLLType)
|
||||
return val;
|
||||
}
|
||||
|
||||
if (baseTargetType->ty == Tsarray) {
|
||||
Logger::println("Building constant array initializer from scalar.");
|
||||
|
||||
assert(baseValType->size() > 0);
|
||||
const auto numTotalVals = baseTargetType->size() / baseValType->size();
|
||||
assert(baseTargetType->size() % baseValType->size() == 0);
|
||||
|
||||
// may be a multi-dimensional array init, e.g., `char[2][3] x = 0xff`
|
||||
baseValType = stripModifiers(baseValType);
|
||||
LLSmallVector<size_t, 4> dims; // { 3, 2 }
|
||||
for (auto t = baseTargetType; t->ty == Tsarray;) {
|
||||
dims.push_back(static_cast<TypeSArray *>(t)->dim->toUInteger());
|
||||
auto elementType = stripModifiers(t->nextOf()->toBasetype());
|
||||
if (elementType->equals(baseValType))
|
||||
break;
|
||||
t = elementType;
|
||||
}
|
||||
|
||||
size_t product = 1;
|
||||
for (size_t i = dims.size(); i--;) {
|
||||
product *= dims[i];
|
||||
auto at = llvm::ArrayType::get(val->getType(), dims[i]);
|
||||
LLSmallVector<llvm::Constant *, 16> elements(dims[i], val);
|
||||
val = llvm::ConstantArray::get(at, elements);
|
||||
}
|
||||
|
||||
assert(product == numTotalVals);
|
||||
return val;
|
||||
}
|
||||
|
||||
llvm::Type *llType = val->getType();
|
||||
llvm::Type *targetLLType = DtoMemType(targetBase);
|
||||
if (llType == targetLLType) {
|
||||
Logger::println("Matching LLVM types, ignoring frontend glitch.");
|
||||
return val;
|
||||
}
|
||||
if (baseTargetType->ty == Tvector) {
|
||||
Logger::println("Building constant vector initializer from scalar.");
|
||||
|
||||
if (targetBase->ty == Tsarray) {
|
||||
Logger::println("Building constant array initializer to single value.");
|
||||
|
||||
assert(expBase->size() > 0);
|
||||
d_uns64 elemCount = targetBase->size() / expBase->size();
|
||||
assert(targetBase->size() % expBase->size() == 0);
|
||||
|
||||
std::vector<llvm::Constant *> initVals(elemCount, val);
|
||||
return llvm::ConstantArray::get(llvm::ArrayType::get(llType, elemCount),
|
||||
initVals);
|
||||
}
|
||||
|
||||
if (targetBase->ty == Tvector) {
|
||||
Logger::println("Building vector initializer from scalar.");
|
||||
|
||||
TypeVector *tv = static_cast<TypeVector *>(targetBase);
|
||||
TypeVector *tv = static_cast<TypeVector *>(baseTargetType);
|
||||
assert(tv->basetype->ty == Tsarray);
|
||||
dinteger_t elemCount =
|
||||
static_cast<TypeSArray *>(tv->basetype)->dim->toInteger();
|
||||
|
@ -1154,10 +1179,9 @@ LLConstant *DtoConstExpInit(Loc &loc, Type *targetType, Expression *exp) {
|
|||
llvm::IntegerType *source = llvm::cast<llvm::IntegerType>(llType);
|
||||
llvm::IntegerType *target = llvm::cast<llvm::IntegerType>(targetLLType);
|
||||
|
||||
assert(
|
||||
target->getBitWidth() > source->getBitWidth() &&
|
||||
"On initializer "
|
||||
"integer type mismatch, the target should be wider than the source.");
|
||||
assert(target->getBitWidth() > source->getBitWidth() &&
|
||||
"On initializer integer type mismatch, the target should be wider "
|
||||
"than the source.");
|
||||
return llvm::ConstantExpr::getZExtOrBitCast(val, target);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue