[pkg-d-commits] [ldc] 13/149: Back off on what we consider as "constant literals": (some) dynamic array literals are not-const because they are expected to be newly allocated. (#1927)
Matthias Klumpp
mak at moszumanska.debian.org
Sun Apr 23 22:36:53 UTC 2017
This is an automated email from the git hooks/post-receive script.
mak pushed a commit to annotated tag v1.2.0
in repository ldc.
commit 0f2d594ae56a87b95053a052e1bbdfb825733177
Author: Johan Engelen <jbc.engelen at gmail.com>
Date: Tue Dec 20 11:26:25 2016 +0100
Back off on what we consider as "constant literals": (some) dynamic array literals are not-const because they are expected to be newly allocated. (#1927)
Resolves #1924
---
gen/arrays.cpp | 15 +++++--
gen/arrays.h | 5 ++-
gen/toir.cpp | 2 +-
tests/codegen/array_literal_gh1924.d | 83 ++++++++++++++++++++++++++++++++++++
4 files changed, 100 insertions(+), 5 deletions(-)
diff --git a/gen/arrays.cpp b/gen/arrays.cpp
index da87788..4e9a12c 100644
--- a/gen/arrays.cpp
+++ b/gen/arrays.cpp
@@ -496,7 +496,7 @@ Expression *indexArrayLiteral(ArrayLiteralExp *ale, unsigned idx) {
////////////////////////////////////////////////////////////////////////////////
-bool isConstLiteral(Expression *e) {
+bool isConstLiteral(Expression *e, bool immutableType) {
// 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.
@@ -506,8 +506,17 @@ bool isConstLiteral(Expression *e) {
switch (e->op) {
case TOKarrayliteral: {
auto ale = static_cast<ArrayLiteralExp *>(e);
+
+ if (!immutableType) {
+ // If dynamic array: assume not constant because the array is expected to
+ // be newly allocated. See GH 1924.
+ Type *arrayType = ale->type->toBasetype();
+ if (arrayType->ty == Tarray)
+ return false;
+ }
+
for (auto el : *ale->elements) {
- if (!isConstLiteral(el ? el : ale->basis))
+ if (!isConstLiteral(el ? el : ale->basis, immutableType))
return false;
}
} break;
@@ -517,7 +526,7 @@ bool isConstLiteral(Expression *e) {
if (sle->sd->isNested())
return false;
for (auto el : *sle->elements) {
- if (el && !isConstLiteral(el))
+ if (el && !isConstLiteral(el, immutableType))
return false;
}
} break;
diff --git a/gen/arrays.h b/gen/arrays.h
index 3aa939b..f8cddf3 100644
--- a/gen/arrays.h
+++ b/gen/arrays.h
@@ -42,7 +42,10 @@ 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(Expression *e);
+/// immutableType indicates whether the literal is used to initialize an
+/// immutable type, in which case allocated dynamic arrays are considered
+/// constant too.
+bool isConstLiteral(Expression *e, bool immutableType = false);
/// Returns the constant for the given array literal expression.
llvm::Constant *arrayLiteralToConst(IRState *p, ArrayLiteralExp *ale);
diff --git a/gen/toir.cpp b/gen/toir.cpp
index c6ecd29..e2fe773 100644
--- a/gen/toir.cpp
+++ b/gen/toir.cpp
@@ -2253,7 +2253,7 @@ public:
result = new DSliceValue(e->type, DtoConstSize_t(0),
getNullPtr(getPtrToType(llElemType)));
} else if (dyn) {
- if (arrayType->isImmutable() && isConstLiteral(e)) {
+ if (arrayType->isImmutable() && isConstLiteral(e, true)) {
llvm::Constant *init = arrayLiteralToConst(p, e);
auto global = new llvm::GlobalVariable(
gIR->module, init->getType(), true,
diff --git a/tests/codegen/array_literal_gh1924.d b/tests/codegen/array_literal_gh1924.d
new file mode 100644
index 0000000..88b8b85
--- /dev/null
+++ b/tests/codegen/array_literal_gh1924.d
@@ -0,0 +1,83 @@
+// RUN: %ldc -c -O3 -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
+// RUN: %ldc -d-version=RUN -run %s
+
+// CHECK-LABEL: define{{.*}} @{{.*}}simple2d
+auto simple2d()
+{
+ // CHECK: _d_newarrayU
+ // CHECK: _d_newarrayU
+ // CHECK-NOT: _d_newarrayU
+ // CHECK: ret {
+ return [[1.0]];
+}
+
+// CHECK-LABEL: define{{.*}} @{{.*}}make3d
+auto make3d()
+{
+ // CHECK: _d_newarrayU
+ // CHECK: _d_newarrayU
+ // CHECK-NOT: _d_newarrayU
+ int[][1][] a = [[[1]]];
+ // CHECK: ret {
+ return a;
+}
+
+struct S
+{
+ auto arr = [[321]];
+}
+
+// CHECK-LABEL: define{{.*}} @{{.*}}makeS
+auto makeS()
+{
+ // CHECK: _d_newarrayU
+ // CHECK: _d_newarrayU
+ // CHECK-NOT: _d_newarrayU
+ // CHECK: ret
+ return S();
+}
+
+mixin template A()
+{
+ auto a = [1, 2, 3];
+ auto b = [[1, 2, 3]];
+}
+
+version (RUN)
+{
+ void main()
+ {
+ {
+ auto a = simple2d();
+ auto b = simple2d();
+ assert(a.ptr !is b.ptr);
+ assert(a[0].ptr !is b[0].ptr);
+ }
+ {
+ auto a = make3d();
+ auto b = make3d();
+ assert(a.ptr !is b.ptr);
+ assert(a[0].ptr !is b[0].ptr);
+ }
+ {
+ enum e = [[1.0]];
+ auto a = e;
+ auto b = e;
+ assert(a.ptr !is b.ptr);
+ assert(a[0].ptr !is b[0].ptr);
+ }
+ {
+ auto a = makeS();
+ auto b = makeS();
+ assert(a.arr.ptr !is b.arr.ptr);
+ assert(a.arr[0].ptr !is b.arr[0].ptr);
+ }
+ {
+ mixin A!() a0;
+ mixin A!() a1;
+ assert(a0.a.ptr !is a1.a.ptr);
+ assert(a0.b.ptr !is a1.b.ptr);
+ assert(a0.b[0].ptr !is a1.b[0].ptr);
+ }
+ }
+}
--
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