Merge pull request #1821 from LemonBoy/slit

Check StructLiteralExp elements in isConstLiteral.
This commit is contained in:
kinke 2016-10-18 10:21:21 +02:00 committed by GitHub
commit ec6483f67e
4 changed files with 60 additions and 19 deletions

View file

@ -496,16 +496,37 @@ Expression *indexArrayLiteral(ArrayLiteralExp *ale, unsigned idx) {
////////////////////////////////////////////////////////////////////////////////
bool isConstLiteral(ArrayLiteralExp *ale) {
// FIXME: This is overly pessemistic, isConst() always returns 0 e.g. for
// StructLiteralExps. Thus, we waste optimization potential (GitHub #506).
for (size_t i = 0; i < ale->elements->dim; ++i) {
// We have to check specifically for '1', as SymOffExp is classified as
// '2' and the address of a local variable is not an LLVM constant.
if (indexArrayLiteral(ale, i)->isConst() != 1) {
return false;
bool isConstLiteral(Expression *e) {
// We have to check the return value of isConst specifically for '1',
// as SymOffExp is classified as '2' and the address of a local variable is
// not an LLVM constant.
//
// Examine the ArrayLiteralExps and the StructLiteralExps element by element
// as isConst always returns 0 on those.
switch (e->op) {
case TOKarrayliteral: {
auto ale = static_cast<ArrayLiteralExp *>(e);
for (auto el : *ale->elements) {
if (!isConstLiteral(el ? el : ale->basis))
return false;
}
} break;
case TOKstructliteral: {
auto sle = static_cast<StructLiteralExp *>(e);
if (sle->sd->isNested())
return false;
for (auto el : *sle->elements) {
if (el && !isConstLiteral(el))
return false;
}
} break;
default:
if (e->isConst() != 1)
return false;
}
return true;
}

View file

@ -42,7 +42,7 @@ LLConstant *DtoConstSlice(LLConstant *dim, LLConstant *ptr,
Expression *indexArrayLiteral(ArrayLiteralExp *ale, unsigned idx);
/// Returns whether the array literal can be evaluated to a (LLVM) constant.
bool isConstLiteral(ArrayLiteralExp *ale);
bool isConstLiteral(Expression *e);
/// Returns the constant for the given array literal expression.
llvm::Constant *arrayLiteralToConst(IRState *p, ArrayLiteralExp *ale);

View file

@ -0,0 +1,27 @@
// RUN: %ldc -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
// RUN: %ldc -run %s
struct S0 { uint x; }
struct S1 { S0 y; this(this) { y.x = 1; } }
struct S2 { S1[3] z; }
struct C0 { int *x; }
void testNested() {
int x;
// The 'x' here is accessed via the nested context pointer
struct N1 { ~this() { ++x; } }
struct N0 { N1[3] x; }
{ N0 n; }
assert(x == 3);
}
// CHECK: @.immutablearray = internal constant [1 x { [3 x { { i32 } }] }] [{ [3 x { { i32 } }] } { [3 x { { i32 } }] [{ { i32 } } { { i32 } { i32 42 } }, { { i32 } } { { i32 } { i32 43 } }, { { i32 } } { { i32 } { i32 44 } }] }] ; [#uses = 1]
void main () {
// CHECK: store %const_struct.S2* bitcast ([1 x { [3 x { { i32 } }] }]* @.immutablearray to %const_struct.S2*), %const_struct.S2** %2
immutable S2[] xyz = [ { [ { { 42 } }, { { 43 } }, { { 44 } } ] } ];
// CHECK: %.gc_mem = call {{{.*}}} @_d_newarrayU(%object.TypeInfo* bitcast (%"typeid(immutable(C0[]))"* @{{.*}} to %object.TypeInfo*), i{{32|64}} 3)
immutable C0[] zyx = [ { new int(42) }, { null }, { null } ];
testNested();
}

View file

@ -108,16 +108,9 @@ struct Container { S s; }
void hierarchyOfLiterals()
{
// CHECK: %sa = alloca [1 x %in_place_construct.Container]
// CHECK: %1 = getelementptr inbounds {{.*}}[1 x %in_place_construct.Container]* %sa, i32 0, i32 0
// CHECK: %2 = getelementptr inbounds {{.*}}%in_place_construct.Container* %1, i32 0, i32 0
// CHECK: %3 = getelementptr inbounds {{.*}}%in_place_construct.S* %2, i32 0, i32 0
// CHECK: store i64 11, i64* %3
// CHECK: %4 = getelementptr inbounds {{.*}}%in_place_construct.S* %2, i32 0, i32 1
// CHECK: store i64 12, i64* %4
// CHECK: %5 = getelementptr inbounds {{.*}}%in_place_construct.S* %2, i32 0, i32 2
// CHECK: store i64 13, i64* %5
// CHECK: %6 = getelementptr inbounds {{.*}}%in_place_construct.S* %2, i32 0, i32 3
// CHECK: store i64 14, i64* %6
// CHECK: %1 = bitcast [1 x %in_place_construct.Container]* %sa to [1 x { { i64, i64, i64, i64 } }]*
// CHECK: store [{{.*}}]* %1
// CHECK: ret void
Container[1] sa = [ Container(S(11, 12, 13, 14)) ];
}