Zext i1 constants for scalar Boolean struct fields to i8

This commit is contained in:
Martin 2016-10-23 15:14:52 +02:00
parent ab1432ed06
commit 10b0261200
6 changed files with 34 additions and 33 deletions

View file

@ -1120,17 +1120,14 @@ LLConstant *DtoConstExpInit(Loc &loc, Type *targetType, Expression *exp) {
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.");

View file

@ -590,7 +590,11 @@ public:
const size_t nexprs = e->elements->dim;
for (size_t i = 0; i < nexprs; i++) {
if ((*e->elements)[i]) {
varInits[e->sd->fields[i]] = toConstElem((*e->elements)[i]);
LLConstant *c = toConstElem((*e->elements)[i]);
// extend i1 to i8
if (c->getType() == LLType::getInt1Ty(p->context()))
c = llvm::ConstantExpr::getZExt(c, LLType::getInt8Ty(p->context()));
varInits[e->sd->fields[i]] = c;
}
}

View file

@ -60,7 +60,6 @@ llvm::cl::opt<bool> checkPrintf(
llvm::cl::ZeroOrMore);
bool walkPostorder(Expression *e, StoppableVisitor *v);
extern LLConstant *get_default_initializer(VarDeclaration *vd);
////////////////////////////////////////////////////////////////////////////////
@ -158,7 +157,7 @@ static void write_struct_literal(Loc loc, LLValue *mem, StructDeclaration *sd,
} else {
IF_LOG Logger::println("using default initializer");
LOG_SCOPE
DConstValue val(vd->type, get_default_initializer(vd));
DConstValue val(vd->type, IrAggr::getDefaultInitializer(vd));
DtoAssign(loc, &field, &val, TOKblit);
}

View file

@ -98,23 +98,18 @@ add_zeros(llvm::SmallVectorImpl<llvm::Constant *> &constants,
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// helper function that returns the static default initializer of a variable
LLConstant *get_default_initializer(VarDeclaration *vd) {
if (vd->_init) {
LLConstant *IrAggr::getDefaultInitializer(VarDeclaration *field) {
if (field->_init) {
// Issue 9057 workaround caused by issue 14666 fix, see DMD upstream
// commit 069f570005.
if (vd->sem < Semantic2Done && vd->_scope) {
vd->semantic2(vd->_scope);
if (field->sem < Semantic2Done && field->_scope) {
field->semantic2(field->_scope);
}
return DtoConstInitializer(vd->_init->loc, vd->type, vd->_init);
return DtoConstInitializer(field->_init->loc, field->type, field->_init);
}
if (vd->type->size(vd->loc) == 0) {
// We need to be able to handle void[0] struct members even if void has
// no default initializer.
return llvm::ConstantPointerNull::get(DtoPtrToType(vd->type));
}
return DtoConstExpInit(vd->loc, vd->type, vd->type->defaultInit(vd->loc));
return DtoConstExpInit(field->loc, field->type,
field->type->defaultInit(field->loc));
}
// return a constant array of type arrTypeD initialized with a constant value,
@ -252,7 +247,7 @@ void IrAggr::addFieldInitializers(
const auto explicitIt = explicitInitializers.find(field);
llvm::Constant *init = (explicitIt != explicitInitializers.end()
? explicitIt->second
: get_default_initializer(field));
: getDefaultInitializer(field));
constants[baseLLFieldIndex + fieldIndex] =
FillSArrayDims(field->type, init);

View file

@ -48,6 +48,11 @@ struct IrAggr {
//////////////////////////////////////////////////////////////////////////
// Returns the static default initializer of a field.
static llvm::Constant *getDefaultInitializer(VarDeclaration *field);
//////////////////////////////////////////////////////////////////////////
/// Create the __initZ symbol lazily.
llvm::GlobalVariable *getInitSymbol();
/// Builds the __initZ initializer constant lazily.

View file

@ -8,16 +8,17 @@ struct S
char c; // default initializer: 0xff
uint ui;
bool[2] bools; // make sure the 2 bools are extended to 2 bytes
char[2][4] multidim; // multidimensional init based on a single 0xff char
bool b = true; // scalar bool too
char[2][1] multidim; // multidimensional init based on a single 0xff char
}
// CHECK-DAG: %union.S = type { i8, [3 x i8], i32, [2 x i8], [4 x [2 x i8]], [2 x i8] }
// CHECK-DAG: @_D5union1S6__initZ = constant %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, [4 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF"], [2 x i8] zeroinitializer }
// CHECK-DAG: %union.S = type { i8, [3 x i8], i32, [2 x i8], i8, [1 x [2 x i8]], [3 x i8] }
// CHECK-DAG: @_D5union1S6__initZ = constant %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, i8 1, [1 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF"], [3 x i8] zeroinitializer }
// CHECK-DAG: @_D5union8defaultSS5union1S = global %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, [4 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF"], [2 x i8] zeroinitializer }
// CHECK-DAG: @_D5union8defaultSS5union1S = global %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, i8 1, [1 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF"], [3 x i8] zeroinitializer }
__gshared S defaultS;
// CHECK-DAG: @_D5union9explicitSS5union1S = global %union.S { i8 3, [3 x i8] zeroinitializer, i32 56, [2 x i8] c"\00\01", [4 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF"], [2 x i8] zeroinitializer }
__gshared S explicitS = S(3, 56, [false, true] /* implicit multidim */);
// CHECK-DAG: @_D5union9explicitSS5union1S = global %union.S { i8 3, [3 x i8] zeroinitializer, i32 56, [2 x i8] c"\00\01", i8 0, [1 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF"], [3 x i8] zeroinitializer }
__gshared S explicitS = S(3, 56, [false, true], false /* implicit multidim */);
struct SWithUnion
@ -43,16 +44,16 @@ struct SWithUnion
this.ui2 = ui2;
}
}
// CHECK-DAG: %union.SWithUnion = type { i8, [3 x i8], %union.S, i8, [1 x i8], i16, i32, i64 }
// CHECK-DAG: @_D5union10SWithUnion6__initZ = constant %union.SWithUnion { i8 -1, [3 x i8] zeroinitializer, %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, [4 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF"], [2 x i8] zeroinitializer }, i8 6, [1 x i8] zeroinitializer, i16 33, i32 84, i64 666 }
// CHECK-DAG: %union.SWithUnion = type { i8, [3 x i8], %union.S, [4 x i8], i8, [1 x i8], i16, i32, i64 }
// CHECK-DAG: @_D5union10SWithUnion6__initZ = constant %union.SWithUnion { i8 -1, [3 x i8] zeroinitializer, %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, i8 1, [1 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF"], [3 x i8] zeroinitializer }, [4 x i8] zeroinitializer, i8 6, [1 x i8] zeroinitializer, i16 33, i32 84, i64 666 }
// CHECK-DAG: @_D5union17defaultSWithUnionS5union10SWithUnion = global %union.SWithUnion { i8 -1, [3 x i8] zeroinitializer, %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, [4 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF"], [2 x i8] zeroinitializer }, i8 6, [1 x i8] zeroinitializer, i16 33, i32 84, i64 666 }
// CHECK-DAG: @_D5union17defaultSWithUnionS5union10SWithUnion = global %union.SWithUnion { i8 -1, [3 x i8] zeroinitializer, %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, i8 1, [1 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF"], [3 x i8] zeroinitializer }, [4 x i8] zeroinitializer, i8 6, [1 x i8] zeroinitializer, i16 33, i32 84, i64 666 }
__gshared SWithUnion defaultSWithUnion;
// CHECK-DAG: @_D5union28explicitCompatibleSWithUnionS5union10SWithUnion = global %union.SWithUnion { i8 -1, [3 x i8] zeroinitializer, %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, [4 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF"], [2 x i8] zeroinitializer }, i8 53, [1 x i8] zeroinitializer, i16 33, i32 84, i64 666 }
// CHECK-DAG: @_D5union28explicitCompatibleSWithUnionS5union10SWithUnion = global %union.SWithUnion { i8 -1, [3 x i8] zeroinitializer, %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, i8 1, [1 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF"], [3 x i8] zeroinitializer }, [4 x i8] zeroinitializer, i8 53, [1 x i8] zeroinitializer, i16 33, i32 84, i64 666 }
__gshared SWithUnion explicitCompatibleSWithUnion = SWithUnion(53);
// When using the 2nd constructor, a dominated union field (ui1) is initialized.
// The regular LL type can thus not be used, an anonymous one is used instead.
// CHECK-DAG: @_D5union30explicitIncompatibleSWithUnionS5union10SWithUnion = global { i8, [3 x i8], %union.S, i32, i32, i64 } { i8 -1, [3 x i8] zeroinitializer, %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, [4 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF", [2 x i8] c"\FF\FF"], [2 x i8] zeroinitializer }, i32 23, i32 256, i64 666 }
// CHECK-DAG: @_D5union30explicitIncompatibleSWithUnionS5union10SWithUnion = global { i8, [3 x i8], %union.S, [4 x i8], i32, i32, i64 } { i8 -1, [3 x i8] zeroinitializer, %union.S { i8 -1, [3 x i8] zeroinitializer, i32 0, [2 x i8] zeroinitializer, i8 1, [1 x [2 x i8]] {{\[}}[2 x i8] c"\FF\FF"], [3 x i8] zeroinitializer }, [4 x i8] zeroinitializer, i32 23, i32 256, i64 666 }
__gshared SWithUnion explicitIncompatibleSWithUnion = SWithUnion(23, 256);