mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 19:36:06 +03:00
Merge pull request #1821 from LemonBoy/slit
Check StructLiteralExp elements in isConstLiteral.
This commit is contained in:
commit
ec6483f67e
4 changed files with 60 additions and 19 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
27
tests/codegen/const_struct.d
Normal file
27
tests/codegen/const_struct.d
Normal 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();
|
||||
}
|
|
@ -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)) ];
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue