summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGen/captured-statements-nested.c
diff options
context:
space:
mode:
authorBen Langmuir <ben.langmuir@intel.com>2013-05-09 19:17:11 +0000
committerBen Langmuir <ben.langmuir@intel.com>2013-05-09 19:17:11 +0000
commit3b4c30b7e77edb76da538fb4989957a219c6438f (patch)
treecf67400674bb8e2328ec34116fc3261b1d46840c /clang/test/CodeGen/captured-statements-nested.c
parent00681dc1f070496b2b0ddbd260e01b3e290ae9fd (diff)
downloadbcm5719-llvm-3b4c30b7e77edb76da538fb4989957a219c6438f.tar.gz
bcm5719-llvm-3b4c30b7e77edb76da538fb4989957a219c6438f.zip
CodeGen for CapturedStmts
EmitCapturedStmt creates a captured struct containing all of the captured variables, and then emits a call to the outlined function. This is similar in principle to EmitBlockLiteral. GenerateCapturedFunction actually produces the outlined function. It is based on GenerateBlockFunction, but is much simpler. The function type is determined by the parameters that are in the CapturedDecl. Some changes have been added to this patch that were reviewed as part of the serialization patch and moving the parameters to the captured decl. Differential Revision: http://llvm-reviews.chandlerc.com/D640 llvm-svn: 181536
Diffstat (limited to 'clang/test/CodeGen/captured-statements-nested.c')
-rw-r--r--clang/test/CodeGen/captured-statements-nested.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/clang/test/CodeGen/captured-statements-nested.c b/clang/test/CodeGen/captured-statements-nested.c
new file mode 100644
index 00000000000..d8ec74692ad
--- /dev/null
+++ b/clang/test/CodeGen/captured-statements-nested.c
@@ -0,0 +1,126 @@
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o %t
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK1
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK2
+
+struct A {
+ int a;
+ float b;
+ char c;
+};
+
+void test_nest_captured_stmt(int param) {
+ int w;
+ // CHECK1: %struct.anon{{.*}} = type { i32*, i32* }
+ // CHECK1: %struct.anon{{.*}} = type { i32*, i32*, i32**, i32* }
+ // CHECK1: [[T:%struct.anon.*]] = type { i32*, i32*, %struct.A*, i32**, i32* }
+ #pragma clang __debug captured
+ {
+ int x;
+ int *y = &w;
+ #pragma clang __debug captured
+ {
+ struct A z;
+ #pragma clang __debug captured
+ {
+ w = x = z.a = 1;
+ *y = param;
+ z.b = 0.1f;
+ z.c = 'c';
+
+ // CHECK1: define internal void @__captured_stmt{{.*}}([[T]]
+ //
+ // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2
+ // CHECK1-NEXT: load %struct.A**
+ // CHECK1-NEXT: getelementptr inbounds %struct.A*
+ // CHECK1-NEXT: store i32 1
+ //
+ // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 1
+ // CHECK1-NEXT: load i32**
+ // CHECK1-NEXT: store i32 1
+ //
+ // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 0
+ // CHECK1-NEXT: load i32**
+ // CHECK1-NEXT: store i32 1
+ //
+ // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 4
+ // CHECK1-NEXT: load i32**
+ // CHECK1-NEXT: load i32*
+ // CHECK1-NEXT: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 3
+ // CHECK1-NEXT: load i32***
+ // CHECK1-NEXT: load i32**
+ // CHECK1-NEXT: store i32
+ //
+ // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2
+ // CHECK1-NEXT: load %struct.A**
+ // CHECK1-NEXT: getelementptr inbounds %struct.A*
+ // CHECK1-NEXT: store float
+ //
+ // CHECK1: getelementptr inbounds [[T]]* {{.*}}, i32 0, i32 2
+ // CHECK1-NEXT: load %struct.A**
+ // CHECK1-NEXT: getelementptr inbounds %struct.A*
+ // CHECK1-NEXT: store i8 99
+ }
+ }
+ }
+}
+
+void test_nest_block() {
+ __block int x;
+ int y;
+ ^{
+ int z;
+ x = z;
+ #pragma clang __debug captured
+ {
+ z = y; // OK
+ }
+ }();
+
+ // CHECK2: define internal void @{{.*}}test_nest_block_block_invoke
+ //
+ // CHECK2: [[Z:%[0-9a-z_]*]] = alloca i32
+ // CHECK2: alloca %struct.anon{{.*}}
+ //
+ // CHECK2: store i32
+ // CHECK2: store i32* [[Z]]
+ //
+ // CHECK2: getelementptr inbounds %struct.anon
+ // CHECK2-NEXT: getelementptr inbounds
+ // CHECK2-NEXT: store i32*
+ //
+ // CHECK2: call void @__captured_stmt
+
+ int a;
+ #pragma clang __debug captured
+ {
+ __block int b;
+ int c;
+ __block int d;
+ ^{
+ b = a;
+ b = c;
+ b = d;
+ }();
+ }
+
+ // CHECK2: alloca %struct.__block_byref_b
+ // CHECK2-NEXT: [[C:%[0-9a-z_]*]] = alloca i32
+ // CHECK2-NEXT: alloca %struct.__block_byref_d
+ //
+ // CHECK2: bitcast %struct.__block_byref_b*
+ // CHECK2-NEXT: store i8*
+ //
+ // CHECK2: [[CapA:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i32 0, i32 7
+ //
+ // CHECK2: getelementptr inbounds %struct.anon{{.*}}, i32 0, i32 0
+ // CHECK2: load i32**
+ // CHECK2: load i32*
+ // CHECK2: store i32 {{.*}}, i32* [[CapA]]
+ //
+ // CHECK2: [[CapC:%[0-9a-z_.]*]] = getelementptr inbounds {{.*}}, i32 0, i32 8
+ // CHECK2-NEXT: [[Val:%[0-9a-z_]*]] = load i32* [[C]]
+ // CHECK2-NEXT: store i32 [[Val]], i32* [[CapC]]
+ //
+ // CHECK2: bitcast %struct.__block_byref_d*
+ // CHECK2-NEXT: store i8*
+}
OpenPOWER on IntegriCloud