[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