[pkg-d-commits] [ldc] 100/211: Check StructLiteralExp elements in isConstLiteral.
Matthias Klumpp
mak at moszumanska.debian.org
Sun Apr 23 22:36:13 UTC 2017
This is an automated email from the git hooks/post-receive script.
mak pushed a commit to annotated tag v1.1.0
in repository ldc.
commit 517f9095a4a67aa6c987843a4f5a34ba84464b78
Author: LemonBoy <thatlemon at gmail.com>
Date: Mon Oct 10 16:06:08 2016 +0200
Check StructLiteralExp elements in isConstLiteral.
---
gen/arrays.cpp | 35 ++++++++++++++++++++++++++++-------
gen/arrays.h | 2 +-
tests/codegen/const_struct.d | 27 +++++++++++++++++++++++++++
tests/codegen/in_place_construct.d | 13 +++----------
4 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/gen/arrays.cpp b/gen/arrays.cpp
index a21b8e4..476f79f 100644
--- a/gen/arrays.cpp
+++ b/gen/arrays.cpp
@@ -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) {
+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;
}
diff --git a/gen/arrays.h b/gen/arrays.h
index ef89fb5..3aa939b 100644
--- a/gen/arrays.h
+++ b/gen/arrays.h
@@ -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);
diff --git a/tests/codegen/const_struct.d b/tests/codegen/const_struct.d
new file mode 100644
index 0000000..cf23628
--- /dev/null
+++ b/tests/codegen/const_struct.d
@@ -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();
+}
diff --git a/tests/codegen/in_place_construct.d b/tests/codegen/in_place_construct.d
index e40d1ec..23fb944 100644
--- a/tests/codegen/in_place_construct.d
+++ b/tests/codegen/in_place_construct.d
@@ -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)) ];
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-d/ldc.git
More information about the pkg-d-commits
mailing list