xref: /aosp_15_r20/external/llvm/test/Transforms/SafeStack/call.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
3*9880d681SAndroid Build Coastguard Worker
4*9880d681SAndroid Build Coastguard Worker@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
5*9880d681SAndroid Build Coastguard Worker
6*9880d681SAndroid Build Coastguard Worker; no arrays / no nested arrays
7*9880d681SAndroid Build Coastguard Worker; Requires no protector.
8*9880d681SAndroid Build Coastguard Worker
9*9880d681SAndroid Build Coastguard Workerdefine void @foo(i8* %a) nounwind uwtable safestack {
10*9880d681SAndroid Build Coastguard Workerentry:
11*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @foo(
12*9880d681SAndroid Build Coastguard Worker  ; CHECK-NOT: __safestack_unsafe_stack_ptr
13*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
14*9880d681SAndroid Build Coastguard Worker  %a.addr = alloca i8*, align 8
15*9880d681SAndroid Build Coastguard Worker  store i8* %a, i8** %a.addr, align 8
16*9880d681SAndroid Build Coastguard Worker  %0 = load i8*, i8** %a.addr, align 8
17*9880d681SAndroid Build Coastguard Worker  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %0)
18*9880d681SAndroid Build Coastguard Worker  ret void
19*9880d681SAndroid Build Coastguard Worker}
20*9880d681SAndroid Build Coastguard Worker
21*9880d681SAndroid Build Coastguard Workerdeclare i32 @printf(i8*, ...)
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Workertarget datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
24*9880d681SAndroid Build Coastguard Workertarget triple = "x86_64-unknown-linux-gnu"
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Workerdefine void @call_memset(i64 %len) safestack {
27*9880d681SAndroid Build Coastguard Workerentry:
28*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_memset
29*9880d681SAndroid Build Coastguard Worker  ; CHECK: @__safestack_unsafe_stack_ptr
30*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
31*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
32*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 0
33*9880d681SAndroid Build Coastguard Worker  call void @llvm.memset.p0i8.i64(i8* %arraydecay, i8 1, i64 %len, i32 1, i1 false)
34*9880d681SAndroid Build Coastguard Worker  ret void
35*9880d681SAndroid Build Coastguard Worker}
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Workerdefine void @call_constant_memset() safestack {
38*9880d681SAndroid Build Coastguard Workerentry:
39*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_constant_memset
40*9880d681SAndroid Build Coastguard Worker  ; CHECK-NOT: @__safestack_unsafe_stack_ptr
41*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
42*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
43*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 2
44*9880d681SAndroid Build Coastguard Worker  call void @llvm.memset.p0i8.i64(i8* %arraydecay, i8 1, i64 7, i32 1, i1 false)
45*9880d681SAndroid Build Coastguard Worker  ret void
46*9880d681SAndroid Build Coastguard Worker}
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Workerdefine void @call_constant_overflow_memset() safestack {
49*9880d681SAndroid Build Coastguard Workerentry:
50*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_constant_overflow_memset
51*9880d681SAndroid Build Coastguard Worker  ; CHECK: @__safestack_unsafe_stack_ptr
52*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
53*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
54*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 7
55*9880d681SAndroid Build Coastguard Worker  call void @llvm.memset.p0i8.i64(i8* %arraydecay, i8 1, i64 5, i32 1, i1 false)
56*9880d681SAndroid Build Coastguard Worker  ret void
57*9880d681SAndroid Build Coastguard Worker}
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Workerdefine void @call_constant_underflow_memset() safestack {
60*9880d681SAndroid Build Coastguard Workerentry:
61*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_constant_underflow_memset
62*9880d681SAndroid Build Coastguard Worker  ; CHECK: @__safestack_unsafe_stack_ptr
63*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
64*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
65*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr [10 x i8], [10 x i8]* %q, i32 0, i32 -1
66*9880d681SAndroid Build Coastguard Worker  call void @llvm.memset.p0i8.i64(i8* %arraydecay, i8 1, i64 3, i32 1, i1 false)
67*9880d681SAndroid Build Coastguard Worker  ret void
68*9880d681SAndroid Build Coastguard Worker}
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker; Readnone nocapture -> safe
71*9880d681SAndroid Build Coastguard Workerdefine void @call_readnone(i64 %len) safestack {
72*9880d681SAndroid Build Coastguard Workerentry:
73*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_readnone
74*9880d681SAndroid Build Coastguard Worker  ; CHECK-NOT: @__safestack_unsafe_stack_ptr
75*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
76*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
77*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 0
78*9880d681SAndroid Build Coastguard Worker  call void @readnone(i8* %arraydecay)
79*9880d681SAndroid Build Coastguard Worker  ret void
80*9880d681SAndroid Build Coastguard Worker}
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker; Arg0 is readnone, arg1 is not. Pass alloca ptr as arg0 -> safe
83*9880d681SAndroid Build Coastguard Workerdefine void @call_readnone0_0(i64 %len) safestack {
84*9880d681SAndroid Build Coastguard Workerentry:
85*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_readnone0_0
86*9880d681SAndroid Build Coastguard Worker  ; CHECK-NOT: @__safestack_unsafe_stack_ptr
87*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
88*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
89*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 0
90*9880d681SAndroid Build Coastguard Worker  call void @readnone0(i8* %arraydecay, i8* zeroinitializer)
91*9880d681SAndroid Build Coastguard Worker  ret void
92*9880d681SAndroid Build Coastguard Worker}
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker; Arg0 is readnone, arg1 is not. Pass alloca ptr as arg1 -> unsafe
95*9880d681SAndroid Build Coastguard Workerdefine void @call_readnone0_1(i64 %len) safestack {
96*9880d681SAndroid Build Coastguard Workerentry:
97*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_readnone0_1
98*9880d681SAndroid Build Coastguard Worker  ; CHECK: @__safestack_unsafe_stack_ptr
99*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
100*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
101*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 0
102*9880d681SAndroid Build Coastguard Worker  call void @readnone0(i8 *zeroinitializer, i8* %arraydecay)
103*9880d681SAndroid Build Coastguard Worker  ret void
104*9880d681SAndroid Build Coastguard Worker}
105*9880d681SAndroid Build Coastguard Worker
106*9880d681SAndroid Build Coastguard Worker; Readonly nocapture -> unsafe
107*9880d681SAndroid Build Coastguard Workerdefine void @call_readonly(i64 %len) safestack {
108*9880d681SAndroid Build Coastguard Workerentry:
109*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_readonly
110*9880d681SAndroid Build Coastguard Worker  ; CHECK: @__safestack_unsafe_stack_ptr
111*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
112*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
113*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 0
114*9880d681SAndroid Build Coastguard Worker  call void @readonly(i8* %arraydecay)
115*9880d681SAndroid Build Coastguard Worker  ret void
116*9880d681SAndroid Build Coastguard Worker}
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker; Readonly nocapture -> unsafe
119*9880d681SAndroid Build Coastguard Workerdefine void @call_arg_readonly(i64 %len) safestack {
120*9880d681SAndroid Build Coastguard Workerentry:
121*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_arg_readonly
122*9880d681SAndroid Build Coastguard Worker  ; CHECK: @__safestack_unsafe_stack_ptr
123*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
124*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
125*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 0
126*9880d681SAndroid Build Coastguard Worker  call void @arg_readonly(i8* %arraydecay)
127*9880d681SAndroid Build Coastguard Worker  ret void
128*9880d681SAndroid Build Coastguard Worker}
129*9880d681SAndroid Build Coastguard Worker
130*9880d681SAndroid Build Coastguard Worker; Readwrite nocapture -> unsafe
131*9880d681SAndroid Build Coastguard Workerdefine void @call_readwrite(i64 %len) safestack {
132*9880d681SAndroid Build Coastguard Workerentry:
133*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_readwrite
134*9880d681SAndroid Build Coastguard Worker  ; CHECK: @__safestack_unsafe_stack_ptr
135*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
136*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
137*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 0
138*9880d681SAndroid Build Coastguard Worker  call void @readwrite(i8* %arraydecay)
139*9880d681SAndroid Build Coastguard Worker  ret void
140*9880d681SAndroid Build Coastguard Worker}
141*9880d681SAndroid Build Coastguard Worker
142*9880d681SAndroid Build Coastguard Worker; Captures the argument -> unsafe
143*9880d681SAndroid Build Coastguard Workerdefine void @call_capture(i64 %len) safestack {
144*9880d681SAndroid Build Coastguard Workerentry:
145*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_capture
146*9880d681SAndroid Build Coastguard Worker  ; CHECK: @__safestack_unsafe_stack_ptr
147*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
148*9880d681SAndroid Build Coastguard Worker  %q = alloca [10 x i8], align 1
149*9880d681SAndroid Build Coastguard Worker  %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %q, i32 0, i32 0
150*9880d681SAndroid Build Coastguard Worker  call void @capture(i8* %arraydecay)
151*9880d681SAndroid Build Coastguard Worker  ret void
152*9880d681SAndroid Build Coastguard Worker}
153*9880d681SAndroid Build Coastguard Worker
154*9880d681SAndroid Build Coastguard Worker; Lifetime intrinsics are always safe.
155*9880d681SAndroid Build Coastguard Workerdefine void @call_lifetime(i32* %p) {
156*9880d681SAndroid Build Coastguard Worker  ; CHECK-LABEL: define void @call_lifetime
157*9880d681SAndroid Build Coastguard Worker  ; CHECK-NOT: @__safestack_unsafe_stack_ptr
158*9880d681SAndroid Build Coastguard Worker  ; CHECK: ret void
159*9880d681SAndroid Build Coastguard Workerentry:
160*9880d681SAndroid Build Coastguard Worker  %q = alloca [100 x i8], align 16
161*9880d681SAndroid Build Coastguard Worker  %0 = bitcast [100 x i8]* %q to i8*
162*9880d681SAndroid Build Coastguard Worker  call void @llvm.lifetime.start(i64 100, i8* %0)
163*9880d681SAndroid Build Coastguard Worker  call void @llvm.lifetime.end(i64 100, i8* %0)
164*9880d681SAndroid Build Coastguard Worker  ret void
165*9880d681SAndroid Build Coastguard Worker}
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Workerdeclare void @readonly(i8* nocapture) readonly
168*9880d681SAndroid Build Coastguard Workerdeclare void @arg_readonly(i8* readonly nocapture)
169*9880d681SAndroid Build Coastguard Workerdeclare void @readwrite(i8* nocapture)
170*9880d681SAndroid Build Coastguard Workerdeclare void @capture(i8* readnone) readnone
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Workerdeclare void @readnone(i8* nocapture) readnone
173*9880d681SAndroid Build Coastguard Workerdeclare void @readnone0(i8* nocapture readnone, i8* nocapture)
174*9880d681SAndroid Build Coastguard Worker
175*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind argmemonly
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.lifetime.start(i64, i8* nocapture) nounwind argmemonly
178*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.lifetime.end(i64, i8* nocapture) nounwind argmemonly
179