summaryrefslogtreecommitdiffstats
path: root/llvm/test
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test')
-rw-r--r--llvm/test/Transforms/SafeStack/addr-taken.ll22
-rw-r--r--llvm/test/Transforms/SafeStack/array-aligned.ll39
-rw-r--r--llvm/test/Transforms/SafeStack/array.ll38
-rw-r--r--llvm/test/Transforms/SafeStack/call.ll20
-rw-r--r--llvm/test/Transforms/SafeStack/cast.ll17
-rw-r--r--llvm/test/Transforms/SafeStack/constant-gep-call.ll26
-rw-r--r--llvm/test/Transforms/SafeStack/constant-gep.ll20
-rw-r--r--llvm/test/Transforms/SafeStack/constant-geps.ll28
-rw-r--r--llvm/test/Transforms/SafeStack/dynamic-alloca.ll21
-rw-r--r--llvm/test/Transforms/SafeStack/escape-addr-pointer.ll23
-rw-r--r--llvm/test/Transforms/SafeStack/escape-bitcast-store.ll23
-rw-r--r--llvm/test/Transforms/SafeStack/escape-bitcast-store2.ll20
-rw-r--r--llvm/test/Transforms/SafeStack/escape-call.ll16
-rw-r--r--llvm/test/Transforms/SafeStack/escape-casted-pointer.ll24
-rw-r--r--llvm/test/Transforms/SafeStack/escape-gep-call.ll20
-rw-r--r--llvm/test/Transforms/SafeStack/escape-gep-invoke.ll34
-rw-r--r--llvm/test/Transforms/SafeStack/escape-gep-negative.ll18
-rw-r--r--llvm/test/Transforms/SafeStack/escape-gep-ptrtoint.ll22
-rw-r--r--llvm/test/Transforms/SafeStack/escape-gep-store.ll23
-rw-r--r--llvm/test/Transforms/SafeStack/escape-phi-call.ll36
-rw-r--r--llvm/test/Transforms/SafeStack/escape-select-call.ll22
-rw-r--r--llvm/test/Transforms/SafeStack/escape-vector.ll21
-rw-r--r--llvm/test/Transforms/SafeStack/invoke.ll33
-rw-r--r--llvm/test/Transforms/SafeStack/no-attr.ll25
-rw-r--r--llvm/test/Transforms/SafeStack/phi-cycle.ll50
-rw-r--r--llvm/test/Transforms/SafeStack/setjmp.ll37
-rw-r--r--llvm/test/Transforms/SafeStack/setjmp2.ll42
-rw-r--r--llvm/test/Transforms/SafeStack/struct.ll41
28 files changed, 761 insertions, 0 deletions
diff --git a/llvm/test/Transforms/SafeStack/addr-taken.ll b/llvm/test/Transforms/SafeStack/addr-taken.ll
new file mode 100644
index 00000000000..0780a01fa89
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/addr-taken.ll
@@ -0,0 +1,22 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Address-of local taken (j = &a)
+; Requires protector.
+
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %retval = alloca i32, align 4
+ %a = alloca i32, align 4
+ %j = alloca i32*, align 8
+ store i32 0, i32* %retval
+ %0 = load i32, i32* %a, align 4
+ %add = add nsw i32 %0, 1
+ store i32 %add, i32* %a, align 4
+ store i32* %a, i32** %j, align 8
+ ret void
+}
+
diff --git a/llvm/test/Transforms/SafeStack/array-aligned.ll b/llvm/test/Transforms/SafeStack/array-aligned.ll
new file mode 100644
index 00000000000..4676903ec77
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/array-aligned.ll
@@ -0,0 +1,39 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; array of [16 x i8]
+
+define void @foo(i8* %a) nounwind uwtable safestack {
+entry:
+ ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
+
+ ; CHECK: %[[USST:.*]] = getelementptr i8, i8* %[[USP]], i32 -16
+
+ ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr
+
+ ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8
+ %a.addr = alloca i8*, align 8
+
+ ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -16
+ ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to [16 x i8]*
+ %buf = alloca [16 x i8], align 16
+
+ ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8
+ store i8* %a, i8** %a.addr, align 8
+
+ ; CHECK: %[[GEP:.*]] = getelementptr inbounds [16 x i8], [16 x i8]* %[[BUFPTR2]], i32 0, i32 0
+ %gep = getelementptr inbounds [16 x i8], [16 x i8]* %buf, i32 0, i32 0
+
+ ; CHECK: %[[A2:.*]] = load i8*, i8** %[[AADDR]], align 8
+ %a2 = load i8*, i8** %a.addr, align 8
+
+ ; CHECK: call i8* @strcpy(i8* %[[GEP]], i8* %[[A2]])
+ %call = call i8* @strcpy(i8* %gep, i8* %a2)
+
+ ; CHECK: store i8* %[[USP]], i8** @__safestack_unsafe_stack_ptr
+ ret void
+}
+
+declare i8* @strcpy(i8*, i8*)
diff --git a/llvm/test/Transforms/SafeStack/array.ll b/llvm/test/Transforms/SafeStack/array.ll
new file mode 100644
index 00000000000..6036bfc2c9c
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/array.ll
@@ -0,0 +1,38 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+; array [4 x i8]
+; Requires protector.
+
+define void @foo(i8* %a) nounwind uwtable safestack {
+entry:
+ ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
+
+ ; CHECK: %[[USST:.*]] = getelementptr i8, i8* %[[USP]], i32 -16
+
+ ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr
+
+ ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8
+ %a.addr = alloca i8*, align 8
+
+ ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -4
+ ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to [4 x i8]*
+ %buf = alloca [4 x i8], align 1
+
+ ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8
+ store i8* %a, i8** %a.addr, align 8
+
+ ; CHECK: %[[GEP:.*]] = getelementptr inbounds [4 x i8], [4 x i8]* %[[BUFPTR2]], i32 0, i32 0
+ %gep = getelementptr inbounds [4 x i8], [4 x i8]* %buf, i32 0, i32 0
+
+ ; CHECK: %[[A2:.*]] = load i8*, i8** %[[AADDR]], align 8
+ %a2 = load i8*, i8** %a.addr, align 8
+
+ ; CHECK: call i8* @strcpy(i8* %[[GEP]], i8* %[[A2]])
+ %call = call i8* @strcpy(i8* %gep, i8* %a2)
+
+ ; CHECK: store i8* %[[USP]], i8** @__safestack_unsafe_stack_ptr
+ ret void
+}
+
+declare i8* @strcpy(i8*, i8*)
diff --git a/llvm/test/Transforms/SafeStack/call.ll b/llvm/test/Transforms/SafeStack/call.ll
new file mode 100644
index 00000000000..ac12ec02b0b
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/call.ll
@@ -0,0 +1,20 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; no arrays / no nested arrays
+; Requires no protector.
+
+; CHECK-LABEL: @foo(
+define void @foo(i8* %a) nounwind uwtable safestack {
+entry:
+ ; CHECK-NOT: __safestack_unsafe_stack_ptr
+ %a.addr = alloca i8*, align 8
+ store i8* %a, i8** %a.addr, align 8
+ %0 = load i8*, i8** %a.addr, align 8
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %0)
+ ret void
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/cast.ll b/llvm/test/Transforms/SafeStack/cast.ll
new file mode 100644
index 00000000000..df6273a117c
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/cast.ll
@@ -0,0 +1,17 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; PtrToInt/IntToPtr Cast
+; Requires no protector.
+
+; CHECK-LABEL: @foo(
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK-NOT: __safestack_unsafe_stack_ptr
+ %a = alloca i32, align 4
+ %0 = ptrtoint i32* %a to i64
+ %1 = inttoptr i64 %0 to i32*
+ ret void
+}
diff --git a/llvm/test/Transforms/SafeStack/constant-gep-call.ll b/llvm/test/Transforms/SafeStack/constant-gep-call.ll
new file mode 100644
index 00000000000..456c1cb1596
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/constant-gep-call.ll
@@ -0,0 +1,26 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.nest = type { %struct.pair, %struct.pair }
+%struct.pair = type { i32, i32 }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Nested structure, no arrays, no address-of expressions.
+; Verify that the resulting gep-of-gep does not incorrectly trigger
+; a safe stack protector.
+; safestack attribute
+; Requires no protector.
+; CHECK-LABEL: @foo(
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK-NOT: __safestack_unsafe_stack_ptr
+ %c = alloca %struct.nest, align 4
+ %b = getelementptr inbounds %struct.nest, %struct.nest* %c, i32 0, i32 1
+ %_a = getelementptr inbounds %struct.pair, %struct.pair* %b, i32 0, i32 0
+ %0 = load i32, i32* %_a, align 4
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %0)
+ ret void
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/constant-gep.ll b/llvm/test/Transforms/SafeStack/constant-gep.ll
new file mode 100644
index 00000000000..6468a761dd5
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/constant-gep.ll
@@ -0,0 +1,20 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%class.A = type { [2 x i8] }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; [2 x i8] in a class
+; safestack attribute
+; Requires no protector.
+; CHECK-LABEL: @foo(
+define signext i8 @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK-NOT: __safestack_unsafe_stack_ptr
+ %a = alloca %class.A, align 1
+ %array = getelementptr inbounds %class.A, %class.A* %a, i32 0, i32 0
+ %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %array, i32 0, i64 0
+ %0 = load i8, i8* %arrayidx, align 1
+ ret i8 %0
+}
diff --git a/llvm/test/Transforms/SafeStack/constant-geps.ll b/llvm/test/Transforms/SafeStack/constant-geps.ll
new file mode 100644
index 00000000000..8a6f7549bb4
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/constant-geps.ll
@@ -0,0 +1,28 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.deep = type { %union.anon }
+%union.anon = type { %struct.anon }
+%struct.anon = type { %struct.anon.0 }
+%struct.anon.0 = type { %union.anon.1 }
+%union.anon.1 = type { [2 x i8] }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; [2 x i8] nested in several layers of structs and unions
+; safestack attribute
+; Requires no protector.
+; CHECK-LABEL: @foo(
+define signext i8 @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK-NOT: __safestack_unsafe_stack_ptr
+ %x = alloca %struct.deep, align 1
+ %b = getelementptr inbounds %struct.deep, %struct.deep* %x, i32 0, i32 0
+ %c = bitcast %union.anon* %b to %struct.anon*
+ %d = getelementptr inbounds %struct.anon, %struct.anon* %c, i32 0, i32 0
+ %e = getelementptr inbounds %struct.anon.0, %struct.anon.0* %d, i32 0, i32 0
+ %array = bitcast %union.anon.1* %e to [2 x i8]*
+ %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %array, i32 0, i64 0
+ %0 = load i8, i8* %arrayidx, align 1
+ ret i8 %0
+}
diff --git a/llvm/test/Transforms/SafeStack/dynamic-alloca.ll b/llvm/test/Transforms/SafeStack/dynamic-alloca.ll
new file mode 100644
index 00000000000..bfec66f82a2
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/dynamic-alloca.ll
@@ -0,0 +1,21 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Variable sized alloca
+; safestack attribute
+; Requires protector.
+define void @foo(i32 %n) nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %n.addr = alloca i32, align 4
+ %a = alloca i32*, align 8
+ store i32 %n, i32* %n.addr, align 4
+ %0 = load i32, i32* %n.addr, align 4
+ %conv = sext i32 %0 to i64
+ %1 = alloca i8, i64 %conv
+ %2 = bitcast i8* %1 to i32*
+ store i32* %2, i32** %a, align 8
+ ret void
+}
diff --git a/llvm/test/Transforms/SafeStack/escape-addr-pointer.ll b/llvm/test/Transforms/SafeStack/escape-addr-pointer.ll
new file mode 100644
index 00000000000..615d711f62c
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-addr-pointer.ll
@@ -0,0 +1,23 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of a pointer
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %a = alloca i32*, align 8
+ %b = alloca i32**, align 8
+ %call = call i32* @getp()
+ store i32* %call, i32** %a, align 8
+ store i32** %a, i32*** %b, align 8
+ %0 = load i32**, i32*** %b, align 8
+ call void @funcall2(i32** %0)
+ ret void
+}
+
+declare void @funcall2(i32**)
+declare i32* @getp()
diff --git a/llvm/test/Transforms/SafeStack/escape-bitcast-store.ll b/llvm/test/Transforms/SafeStack/escape-bitcast-store.ll
new file mode 100644
index 00000000000..9d556a6782a
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-bitcast-store.ll
@@ -0,0 +1,23 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of a local cast to a ptr of a different type
+; (e.g., int a; ... ; float *b = &a;)
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %a = alloca i32, align 4
+ %b = alloca float*, align 8
+ store i32 0, i32* %a, align 4
+ %0 = bitcast i32* %a to float*
+ store float* %0, float** %b, align 8
+ %1 = load float*, float** %b, align 8
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), float* %1)
+ ret void
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/escape-bitcast-store2.ll b/llvm/test/Transforms/SafeStack/escape-bitcast-store2.ll
new file mode 100644
index 00000000000..5f1f873f422
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-bitcast-store2.ll
@@ -0,0 +1,20 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of a local cast to a ptr of a different type (optimized)
+; (e.g., int a; ... ; float *b = &a;)
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %a = alloca i32, align 4
+ store i32 0, i32* %a, align 4
+ %0 = bitcast i32* %a to float*
+ call void @funfloat(float* %0) nounwind
+ ret void
+}
+
+declare void @funfloat(float*)
diff --git a/llvm/test/Transforms/SafeStack/escape-call.ll b/llvm/test/Transforms/SafeStack/escape-call.ll
new file mode 100644
index 00000000000..ce09780d2ea
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-call.ll
@@ -0,0 +1,16 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Passing addr-of to function call
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %b = alloca i32, align 4
+ call void @funcall(i32* %b) nounwind
+ ret void
+}
+
+declare void @funcall(i32*)
diff --git a/llvm/test/Transforms/SafeStack/escape-casted-pointer.ll b/llvm/test/Transforms/SafeStack/escape-casted-pointer.ll
new file mode 100644
index 00000000000..bf6ce1d6b2a
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-casted-pointer.ll
@@ -0,0 +1,24 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of a casted pointer
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %a = alloca i32*, align 8
+ %b = alloca float**, align 8
+ %call = call i32* @getp()
+ store i32* %call, i32** %a, align 8
+ %0 = bitcast i32** %a to float**
+ store float** %0, float*** %b, align 8
+ %1 = load float**, float*** %b, align 8
+ call void @funfloat2(float** %1)
+ ret void
+}
+
+declare void @funfloat2(float**)
+declare i32* @getp()
diff --git a/llvm/test/Transforms/SafeStack/escape-gep-call.ll b/llvm/test/Transforms/SafeStack/escape-gep-call.ll
new file mode 100644
index 00000000000..42b5dd5c1e7
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-gep-call.ll
@@ -0,0 +1,20 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.pair = type { i32, i32 }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of struct element, GEP followed by callinst.
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %c = alloca %struct.pair, align 4
+ %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i64 0, i32 1
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %y) nounwind
+ ret void
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/escape-gep-invoke.ll b/llvm/test/Transforms/SafeStack/escape-gep-invoke.ll
new file mode 100644
index 00000000000..f9803722c40
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-gep-invoke.ll
@@ -0,0 +1,34 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.pair = type { i32, i32 }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of a struct element passed into an invoke instruction.
+; (GEP followed by an invoke)
+; safestack attribute
+; Requires protector.
+define i32 @foo() uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %c = alloca %struct.pair, align 4
+ %exn.slot = alloca i8*
+ %ehselector.slot = alloca i32
+ %a = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 0
+ store i32 0, i32* %a, align 4
+ %a1 = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 0
+ invoke void @_Z3exceptPi(i32* %a1)
+ to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+ ret i32 0
+
+lpad:
+ %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ catch i8* null
+ ret i32 0
+}
+
+declare void @_Z3exceptPi(i32*)
+declare i32 @__gxx_personality_v0(...)
diff --git a/llvm/test/Transforms/SafeStack/escape-gep-negative.ll b/llvm/test/Transforms/SafeStack/escape-gep-negative.ll
new file mode 100644
index 00000000000..80d405de36d
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-gep-negative.ll
@@ -0,0 +1,18 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of a local, optimized into a GEP (e.g., &a - 12)
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %a = alloca i32, align 4
+ %add.ptr5 = getelementptr inbounds i32, i32* %a, i64 -12
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %add.ptr5) nounwind
+ ret void
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/escape-gep-ptrtoint.ll b/llvm/test/Transforms/SafeStack/escape-gep-ptrtoint.ll
new file mode 100644
index 00000000000..73a8e58fb08
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-gep-ptrtoint.ll
@@ -0,0 +1,22 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.pair = type { i32, i32 }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of struct element, GEP followed by ptrtoint.
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %c = alloca %struct.pair, align 4
+ %b = alloca i32*, align 8
+ %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1
+ %0 = ptrtoint i32* %y to i64
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 %0)
+ ret void
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/escape-gep-store.ll b/llvm/test/Transforms/SafeStack/escape-gep-store.ll
new file mode 100644
index 00000000000..7c6c0a318b1
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-gep-store.ll
@@ -0,0 +1,23 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.pair = type { i32, i32 }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of struct element. (GEP followed by store).
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %c = alloca %struct.pair, align 4
+ %b = alloca i32*, align 8
+ %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1
+ store i32* %y, i32** %b, align 8
+ %0 = load i32*, i32** %b, align 8
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32* %0)
+ ret void
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/escape-phi-call.ll b/llvm/test/Transforms/SafeStack/escape-phi-call.ll
new file mode 100644
index 00000000000..10b6c1fdce4
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-phi-call.ll
@@ -0,0 +1,36 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of in phi instruction
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %x = alloca double, align 8
+ %call = call double @testi_aux() nounwind
+ store double %call, double* %x, align 8
+ %cmp = fcmp ogt double %call, 3.140000e+00
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then: ; preds = %entry
+ %call1 = call double @testi_aux() nounwind
+ store double %call1, double* %x, align 8
+ br label %if.end4
+
+if.else: ; preds = %entry
+ %cmp2 = fcmp ogt double %call, 1.000000e+00
+ br i1 %cmp2, label %if.then3, label %if.end4
+
+if.then3: ; preds = %if.else
+ br label %if.end4
+
+if.end4: ; preds = %if.else, %if.then3, %if.then
+ %y.0 = phi double* [ null, %if.then ], [ %x, %if.then3 ], [ null, %if.else ]
+ %call5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), double* %y.0) nounwind
+ ret void
+}
+
+declare double @testi_aux()
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/escape-select-call.ll b/llvm/test/Transforms/SafeStack/escape-select-call.ll
new file mode 100644
index 00000000000..9e54dd8e140
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-select-call.ll
@@ -0,0 +1,22 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of in select instruction
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %x = alloca double, align 8
+ %call = call double @testi_aux() nounwind
+ store double %call, double* %x, align 8
+ %cmp2 = fcmp ogt double %call, 0.000000e+00
+ %y.1 = select i1 %cmp2, double* %x, double* null
+ %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), double* %y.1)
+ ret void
+}
+
+declare double @testi_aux()
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/escape-vector.ll b/llvm/test/Transforms/SafeStack/escape-vector.ll
new file mode 100644
index 00000000000..76b01c7c430
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/escape-vector.ll
@@ -0,0 +1,21 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.vec = type { <4 x i32> }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of a vector nested in a struct
+; safestack attribute
+; Requires protector.
+define void @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %c = alloca %struct.vec, align 16
+ %y = getelementptr inbounds %struct.vec, %struct.vec* %c, i64 0, i32 0
+ %add.ptr = getelementptr inbounds <4 x i32>, <4 x i32>* %y, i64 -12
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), <4 x i32>* %add.ptr) nounwind
+ ret void
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/invoke.ll b/llvm/test/Transforms/SafeStack/invoke.ll
new file mode 100644
index 00000000000..10b3f982b9d
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/invoke.ll
@@ -0,0 +1,33 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Addr-of a variable passed into an invoke instruction.
+; safestack attribute
+; Requires protector and stack restore after landing pad.
+define i32 @foo() uwtable safestack {
+entry:
+ ; CHECK: %[[SP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
+ ; CHECK: %[[STATICTOP:.*]] = getelementptr i8, i8* %[[SP]], i32 -16
+ %a = alloca i32, align 4
+ %exn.slot = alloca i8*
+ %ehselector.slot = alloca i32
+ store i32 0, i32* %a, align 4
+ invoke void @_Z3exceptPi(i32* %a)
+ to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+ ret i32 0
+
+lpad:
+ ; CHECK: landingpad
+ ; CHECK-NEXT: catch
+ %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ catch i8* null
+ ; CHECK-NEXT: store i8* %[[STATICTOP]], i8** @__safestack_unsafe_stack_ptr
+ ret i32 0
+}
+
+declare void @_Z3exceptPi(i32*)
+declare i32 @__gxx_personality_v0(...)
diff --git a/llvm/test/Transforms/SafeStack/no-attr.ll b/llvm/test/Transforms/SafeStack/no-attr.ll
new file mode 100644
index 00000000000..ca3c21ab01b
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/no-attr.ll
@@ -0,0 +1,25 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; no safestack attribute
+; Requires no protector.
+
+; CHECK: @foo
+define void @foo(i8* %a) nounwind uwtable {
+entry:
+ ; CHECK-NOT: __safestack_unsafe_stack_ptr
+ %a.addr = alloca i8*, align 8
+ %buf = alloca [16 x i8], align 16
+ store i8* %a, i8** %a.addr, align 8
+ %arraydecay = getelementptr inbounds [16 x i8], [16 x i8]* %buf, i32 0, i32 0
+ %0 = load i8*, i8** %a.addr, align 8
+ %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
+ %arraydecay1 = getelementptr inbounds [16 x i8], [16 x i8]* %buf, i32 0, i32 0
+ %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1)
+ ret void
+}
+
+declare i8* @strcpy(i8*, i8*)
+declare i32 @printf(i8*, ...)
diff --git a/llvm/test/Transforms/SafeStack/phi-cycle.ll b/llvm/test/Transforms/SafeStack/phi-cycle.ll
new file mode 100644
index 00000000000..026e88785cb
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/phi-cycle.ll
@@ -0,0 +1,50 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.small = type { i8 }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; Address-of a structure taken in a function with a loop where
+; the alloca is an incoming value to a PHI node and a use of that PHI
+; node is also an incoming value.
+; Verify that the address-of analysis does not get stuck in infinite
+; recursion when chasing the alloca through the PHI nodes.
+; Requires protector.
+define i32 @foo(i32 %arg) nounwind uwtable safestack {
+bb:
+ ; CHECK: __safestack_unsafe_stack_ptr
+ %tmp = alloca %struct.small*, align 8
+ %tmp1 = call i32 (...) @dummy(%struct.small** %tmp) nounwind
+ %tmp2 = load %struct.small*, %struct.small** %tmp, align 8
+ %tmp3 = ptrtoint %struct.small* %tmp2 to i64
+ %tmp4 = trunc i64 %tmp3 to i32
+ %tmp5 = icmp sgt i32 %tmp4, 0
+ br i1 %tmp5, label %bb6, label %bb21
+
+bb6: ; preds = %bb17, %bb
+ %tmp7 = phi %struct.small* [ %tmp19, %bb17 ], [ %tmp2, %bb ]
+ %tmp8 = phi i64 [ %tmp20, %bb17 ], [ 1, %bb ]
+ %tmp9 = phi i32 [ %tmp14, %bb17 ], [ %tmp1, %bb ]
+ %tmp10 = getelementptr inbounds %struct.small, %struct.small* %tmp7, i64 0, i32 0
+ %tmp11 = load i8, i8* %tmp10, align 1
+ %tmp12 = icmp eq i8 %tmp11, 1
+ %tmp13 = add nsw i32 %tmp9, 8
+ %tmp14 = select i1 %tmp12, i32 %tmp13, i32 %tmp9
+ %tmp15 = trunc i64 %tmp8 to i32
+ %tmp16 = icmp eq i32 %tmp15, %tmp4
+ br i1 %tmp16, label %bb21, label %bb17
+
+bb17: ; preds = %bb6
+ %tmp18 = getelementptr inbounds %struct.small*, %struct.small** %tmp, i64 %tmp8
+ %tmp19 = load %struct.small*, %struct.small** %tmp18, align 8
+ %tmp20 = add i64 %tmp8, 1
+ br label %bb6
+
+bb21: ; preds = %bb6, %bb
+ %tmp22 = phi i32 [ %tmp1, %bb ], [ %tmp14, %bb6 ]
+ %tmp23 = call i32 (...) @dummy(i32 %tmp22) nounwind
+ ret i32 undef
+}
+
+declare i32 @dummy(...)
diff --git a/llvm/test/Transforms/SafeStack/setjmp.ll b/llvm/test/Transforms/SafeStack/setjmp.ll
new file mode 100644
index 00000000000..e38bff68e94
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/setjmp.ll
@@ -0,0 +1,37 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.__jmp_buf_tag = type { [8 x i64], i32, %struct.__sigset_t }
+%struct.__sigset_t = type { [16 x i64] }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+@buf = internal global [1 x %struct.__jmp_buf_tag] zeroinitializer, align 16
+
+; setjmp/longjmp test.
+; Requires protector.
+define i32 @foo() nounwind uwtable safestack {
+entry:
+ ; CHECK: %[[SP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
+ ; CHECK: %[[STATICTOP:.*]] = getelementptr i8, i8* %[[SP]], i32 -16
+ %retval = alloca i32, align 4
+ %x = alloca i32, align 4
+ store i32 0, i32* %retval
+ store i32 42, i32* %x, align 4
+ %call = call i32 @_setjmp(%struct.__jmp_buf_tag* getelementptr inbounds ([1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* @buf, i32 0, i32 0)) returns_twice
+ ; CHECK: setjmp
+ ; CHECK-NEXT: store i8* %[[STATICTOP]], i8** @__safestack_unsafe_stack_ptr
+ %tobool = icmp ne i32 %call, 0
+ br i1 %tobool, label %if.else, label %if.then
+if.then: ; preds = %entry
+ call void @funcall(i32* %x)
+ br label %if.end
+if.else: ; preds = %entry
+ call i32 (...) @dummy()
+ br label %if.end
+if.end: ; preds = %if.else, %if.then
+ ret i32 0
+}
+
+declare i32 @_setjmp(%struct.__jmp_buf_tag*)
+declare void @funcall(i32*)
+declare i32 @dummy(...)
diff --git a/llvm/test/Transforms/SafeStack/setjmp2.ll b/llvm/test/Transforms/SafeStack/setjmp2.ll
new file mode 100644
index 00000000000..65fd920d63d
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/setjmp2.ll
@@ -0,0 +1,42 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.__jmp_buf_tag = type { [8 x i64], i32, %struct.__sigset_t }
+%struct.__sigset_t = type { [16 x i64] }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+@buf = internal global [1 x %struct.__jmp_buf_tag] zeroinitializer, align 16
+
+; setjmp/longjmp test with dynamically sized array.
+; Requires protector.
+; CHECK: @foo(i32 %[[ARG:.*]])
+define i32 @foo(i32 %size) nounwind uwtable safestack {
+entry:
+ ; CHECK: %[[DYNPTR:.*]] = alloca i8*
+ ; CHECK-NEXT: %[[SP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
+ ; CHECK-NEXT: store i8* %[[SP]], i8** %[[DYNPTR]]
+
+ ; CHECK-NEXT: %[[ZEXT:.*]] = zext i32 %[[ARG]] to i64
+ ; CHECK-NEXT: %[[MUL:.*]] = mul i64 %[[ZEXT]], 4
+ ; CHECK-NEXT: %[[SP2:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
+ ; CHECK-NEXT: %[[PTRTOINT:.*]] = ptrtoint i8* %[[SP2]] to i64
+ ; CHECK-NEXT: %[[SUB:.*]] = sub i64 %[[PTRTOINT]], %[[MUL]]
+ ; CHECK-NEXT: %[[AND:.*]] = and i64 %[[SUB]], -16
+ ; CHECK-NEXT: %[[INTTOPTR:.*]] = inttoptr i64 %[[AND]] to i8*
+ ; CHECK-NEXT: store i8* %[[INTTOPTR]], i8** @__safestack_unsafe_stack_ptr
+ ; CHECK-NEXT: store i8* %[[INTTOPTR]], i8** %unsafe_stack_dynamic_ptr
+ ; CHECK-NEXT: %[[ALLOCA:.*]] = inttoptr i64 %[[SUB]] to i32*
+ %a = alloca i32, i32 %size
+
+ ; CHECK: setjmp
+ ; CHECK-NEXT: %[[LOAD:.*]] = load i8*, i8** %[[DYNPTR]]
+ ; CHECK-NEXT: store i8* %[[LOAD]], i8** @__safestack_unsafe_stack_ptr
+ %call = call i32 @_setjmp(%struct.__jmp_buf_tag* getelementptr inbounds ([1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* @buf, i32 0, i32 0)) returns_twice
+
+ ; CHECK: call void @funcall(i32* %[[ALLOCA]])
+ call void @funcall(i32* %a)
+ ret i32 0
+}
+
+declare i32 @_setjmp(%struct.__jmp_buf_tag*)
+declare void @funcall(i32*)
diff --git a/llvm/test/Transforms/SafeStack/struct.ll b/llvm/test/Transforms/SafeStack/struct.ll
new file mode 100644
index 00000000000..12a0085a2cc
--- /dev/null
+++ b/llvm/test/Transforms/SafeStack/struct.ll
@@ -0,0 +1,41 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+%struct.foo = type { [16 x i8] }
+
+@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
+
+; struct { [16 x i8] }
+
+define void @foo(i8* %a) nounwind uwtable safestack {
+entry:
+ ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
+
+ ; CHECK: %[[USST:.*]] = getelementptr i8, i8* %[[USP]], i32 -16
+
+ ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr
+
+ ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8
+ %a.addr = alloca i8*, align 8
+
+ ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -16
+ ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to %struct.foo*
+ %buf = alloca %struct.foo, align 1
+
+ ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8
+ store i8* %a, i8** %a.addr, align 8
+
+ ; CHECK: %[[GEP:.*]] = getelementptr inbounds %struct.foo, %struct.foo* %[[BUFPTR2]], i32 0, i32 0, i32 0
+ %gep = getelementptr inbounds %struct.foo, %struct.foo* %buf, i32 0, i32 0, i32 0
+
+ ; CHECK: %[[A:.*]] = load i8*, i8** %[[AADDR]], align 8
+ %a2 = load i8*, i8** %a.addr, align 8
+
+ ; CHECK: call i8* @strcpy(i8* %[[GEP]], i8* %[[A]])
+ %call = call i8* @strcpy(i8* %gep, i8* %a2)
+
+ ; CHECK: store i8* %[[USP]], i8** @__safestack_unsafe_stack_ptr
+ ret void
+}
+
+declare i8* @strcpy(i8*, i8*)
OpenPOWER on IntegriCloud