llvm.org GIT mirror llvm / 114baee
Add the IR attribute 'sspstrong'. SSPStrong applies a heuristic to insert stack protectors in these situations: * A Protector is required for functions which contain an array, regardless of type or length. * A Protector is required for functions which contain a structure/union which contains an array, regardless of type or length. Note, there is no limit to the depth of nesting. * A protector is required when the address of a local variable (i.e., stack based variable) is exposed. (E.g., such as through a local whose address is taken as part of the RHS of an assignment or a local whose address is taken as part of a function argument.) This patch implements the SSPString attribute to be equivalent to SSPRequired. This will change in a subsequent patch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173230 91177308-0d34-0410-b5e6-96231b3b80d8 Bill Wendling 6 years ago
14 changed file(s) with 863 addition(s) and 51 deletion(s). Raw diff Collapse all Expand all
836836
837837 If a function that has an ``sspreq`` attribute is inlined into a
838838 function that doesn't have an ``sspreq`` attribute or which has an
839 ``ssp`` attribute, then the resulting function will have an
840 ``sspreq`` attribute.
839 ``ssp`` or ``sspstrong`` attribute, then the resulting function will have
840 an ``sspreq`` attribute.
841 ``sspstrong``
842 This attribute indicates that the function should emit a stack smashing
843 protector. Currently this attribute has the same effect as
844 ``sspreq``. This overrides the ``ssp`` function attribute.
845
846 If a function that has an ``sspstrong`` attribute is inlined into a
847 function that doesn't have an ``sspstrong`` attribute, then the
848 resulting function will have an ``sspstrong`` attribute.
841849 ``uwtable``
842850 This attribute indicates that the ABI being targeted requires that
843851 an unwind table entry be produce for this function even if we can
8989 ///< alignstack=(1))
9090 StackProtect, ///< Stack protection.
9191 StackProtectReq, ///< Stack protection required.
92 StackProtectStrong, ///< Strong Stack protection.
9293 StructRet, ///< Hidden pointer to structure to return
9394 UWTable, ///< Function must be in a unwind table
9495 ZExt, ///< Zero extended before/after call
462463 .removeAttribute(Attribute::OptimizeForSize)
463464 .removeAttribute(Attribute::StackProtect)
464465 .removeAttribute(Attribute::StackProtectReq)
466 .removeAttribute(Attribute::StackProtectStrong)
465467 .removeAttribute(Attribute::NoRedZone)
466468 .removeAttribute(Attribute::NoImplicitFloat)
467469 .removeAttribute(Attribute::Naked)
172172 LLVMUWTable = 1 << 30,
173173 LLVMNonLazyBind = 1 << 31
174174
175 /* FIXME: This attribute is currently not included in the C API as
175 /* FIXME: These attributes are currently not included in the C API as
176176 a temporary measure until the API/ABI impact to the C API is understood
177177 and the path forward agreed upon.
178 LLVMAddressSafety = 1ULL << 32
178 LLVMAddressSafety = 1ULL << 32,
179 LLVMStackProtectStrongAttribute = 1ULL<<33
179180 */
180181 } LLVMAttribute;
181182
548548 KEYWORD(optsize);
549549 KEYWORD(ssp);
550550 KEYWORD(sspreq);
551 KEYWORD(sspstrong);
551552 KEYWORD(noredzone);
552553 KEYWORD(noimplicitfloat);
553554 KEYWORD(naked);
955955 case lltok::kw_returns_twice: B.addAttribute(Attribute::ReturnsTwice); break;
956956 case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break;
957957 case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break;
958 case lltok::kw_sspstrong: B.addAttribute(Attribute::StackProtectStrong); break;
958959 case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break;
959960 case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break;
960961
10491050 case lltok::kw_readonly: case lltok::kw_inlinehint:
10501051 case lltok::kw_alwaysinline: case lltok::kw_optsize:
10511052 case lltok::kw_ssp: case lltok::kw_sspreq:
1052 case lltok::kw_noredzone: case lltok::kw_noimplicitfloat:
1053 case lltok::kw_naked: case lltok::kw_nonlazybind:
1054 case lltok::kw_address_safety: case lltok::kw_minsize:
1055 case lltok::kw_alignstack: case lltok::kw_align:
1056 case lltok::kw_noduplicate:
1053 case lltok::kw_sspstrong: case lltok::kw_noimplicitfloat:
1054 case lltok::kw_noredzone: case lltok::kw_naked:
1055 case lltok::kw_nonlazybind: case lltok::kw_address_safety:
1056 case lltok::kw_minsize: case lltok::kw_alignstack:
1057 case lltok::kw_align: case lltok::kw_noduplicate:
10571058 HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute");
10581059 break;
10591060 }
109109 kw_optsize,
110110 kw_ssp,
111111 kw_sspreq,
112 kw_sspstrong,
112113 kw_noredzone,
113114 kw_noimplicitfloat,
114115 kw_naked,
140140 Attribute::StackProtectReq))
141141 return true;
142142
143 // FIXME: Dummy SSP-strong implementation. Default to required until
144 // strong heuristic is implemented.
145 if (F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
146 Attribute::StackProtectStrong))
147 return true;
148
143149 if (!F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
144150 Attribute::StackProtect))
145151 return false;
205205 Result += "ssp ";
206206 if (hasAttribute(Attribute::StackProtectReq))
207207 Result += "sspreq ";
208 if (hasAttribute(Attribute::StackProtectStrong))
209 Result += "sspstrong ";
208210 if (hasAttribute(Attribute::NoRedZone))
209211 Result += "noredzone ";
210212 if (hasAttribute(Attribute::NoImplicitFloat))
486488 case Attribute::AddressSafety: return 1ULL << 32;
487489 case Attribute::MinSize: return 1ULL << 33;
488490 case Attribute::NoDuplicate: return 1ULL << 34;
491 case Attribute::StackProtectStrong: return 1ULL << 35;
489492 }
490493 llvm_unreachable("Unsupported attribute type");
491494 }
498498 HANDLE_ATTR(OptimizeForSize);
499499 HANDLE_ATTR(StackProtect);
500500 HANDLE_ATTR(StackProtectReq);
501 HANDLE_ATTR(StackProtectStrong);
501502 HANDLE_ATTR(NoCapture);
502503 HANDLE_ATTR(NoRedZone);
503504 HANDLE_ATTR(NoImplicitFloat);
7171 typedef DenseMap >
7272 InlinedArrayAllocasTy;
7373
74 /// \brief If the inlined function had a higher stack protection level than the
75 /// calling function, then bump up the caller's stack protection level.
76 static void AdjustCallerSSPLevel(Function *Caller, Function *Callee) {
77 // If upgrading the SSP attribute, clear out the old SSP Attributes first.
78 // Having multiple SSP attributes doesn't actually hurt, but it adds useless
79 // clutter to the IR.
80 AttrBuilder B;
81 B.addAttribute(Attribute::StackProtect)
82 .addAttribute(Attribute::StackProtectStrong);
83 AttributeSet OldSSPAttr = AttributeSet::get(Caller->getContext(),
84 AttributeSet::FunctionIndex,
85 B);
86 AttributeSet CallerAttr = Caller->getAttributes(),
87 CalleeAttr = Callee->getAttributes();
88
89 if (CalleeAttr.hasAttribute(AttributeSet::FunctionIndex,
90 Attribute::StackProtectReq)) {
91 Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
92 Caller->addFnAttr(Attribute::StackProtectReq);
93 } else if (CalleeAttr.hasAttribute(AttributeSet::FunctionIndex,
94 Attribute::StackProtectStrong) &&
95 !CallerAttr.hasAttribute(AttributeSet::FunctionIndex,
96 Attribute::StackProtectReq)) {
97 Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
98 Caller->addFnAttr(Attribute::StackProtectStrong);
99 } else if (CalleeAttr.hasAttribute(AttributeSet::FunctionIndex,
100 Attribute::StackProtect) &&
101 !CallerAttr.hasAttribute(AttributeSet::FunctionIndex,
102 Attribute::StackProtectReq) &&
103 !CallerAttr.hasAttribute(AttributeSet::FunctionIndex,
104 Attribute::StackProtectStrong))
105 Caller->addFnAttr(Attribute::StackProtect);
106 }
107
74108 /// InlineCallIfPossible - If it is possible to inline the specified call site,
75109 /// do so and update the CallGraph for this operation.
76110 ///
90124 if (!InlineFunction(CS, IFI, InsertLifetime))
91125 return false;
92126
93 // If the inlined function had a higher stack protection level than the
94 // calling function, then bump up the caller's stack protection level.
95 if (Callee->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
96 Attribute::StackProtectReq))
97 Caller->addFnAttr(Attribute::StackProtectReq);
98 else if (Callee->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
99 Attribute::StackProtect) &&
100 !Caller->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
101 Attribute::StackProtectReq))
102 Caller->addFnAttr(Attribute::StackProtect);
127 AdjustCallerSSPLevel(Caller, Callee);
103128
104129 // Look at all of the allocas that we inlined through this call site. If we
105130 // have already inlined other allocas through other calls into this function,
None ; RUN: llc -mtriple=i386-pc-linux-gnu < %s -o - | grep %gs:
1 ; RUN: llc -mtriple=x86_64-pc-linux-gnu < %s -o - | grep %fs:
2 ; RUN: llc -code-model=kernel -mtriple=x86_64-pc-linux-gnu < %s -o - | grep %gs:
3 ; RUN: llc -mtriple=x86_64-apple-darwin < %s -o - | grep "__stack_chk_guard"
4 ; RUN: llc -mtriple=x86_64-apple-darwin < %s -o - | grep "__stack_chk_fail"
5
6 @"\01LC" = internal constant [11 x i8] c"buf == %s\0A\00" ; <[11 x i8]*> [#uses=1]
7
8 define void @test(i8* %a) nounwind ssp {
9 entry:
10 %a_addr = alloca i8* ; [#uses=2]
11 %buf = alloca [8 x i8] ; <[8 x i8]*> [#uses=2]
12 %"alloca point" = bitcast i32 0 to i32 ; [#uses=0]
13 store i8* %a, i8** %a_addr
14 %buf1 = bitcast [8 x i8]* %buf to i8* ; [#uses=1]
15 %0 = load i8** %a_addr, align 4 ; [#uses=1]
16 %1 = call i8* @strcpy(i8* %buf1, i8* %0) nounwind ; [#uses=0]
17 %buf2 = bitcast [8 x i8]* %buf to i8* ; [#uses=1]
18 %2 = call i32 (i8*, ...)* @printf(i8* getelementptr ([11 x i8]* @"\01LC", i32 0, i32 0), i8* %buf2) nounwind ; [#uses=0]
19 br label %return
20
21 return: ; preds = %entry
22 ret void
23 }
24
25 declare i8* @strcpy(i8*, i8*) nounwind
26
27 declare i32 @printf(i8*, ...) nounwind
0 ; RUN: llc -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-I386 %s
1 ; RUN: llc -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-X64 %s
2 ; RUN: llc -code-model=kernel -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-KERNEL-X64 %s
3 ; RUN: llc -mtriple=x86_64-apple-darwin < %s -o - | FileCheck --check-prefix=DARWIN-X64 %s
4 ; FIXME: Update and expand test when strong heuristic is implemented.
5
6 %struct.foo = type { [16 x i8] }
7 %struct.foo.0 = type { [4 x i8] }
8
9 @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
10
11 ; test1a: array of [16 x i8]
12 ; no ssp attribute
13 ; Requires no protector.
14 define void @test1a(i8* %a) nounwind uwtable {
15 entry:
16 ; LINUX-I386: test1a:
17 ; LINUX-I386-NOT: calll __stack_chk_fail
18 ; LINUX-I386: .cfi_endproc
19
20 ; LINUX-X64: test1a:
21 ; LINUX-X64-NOT: callq __stack_chk_fail
22 ; LINUX-X64: .cfi_endproc
23
24 ; LINUX-KERNEL-X64: test1a:
25 ; LINUX-KERNEL-X64-NOT: callq __stack_chk_fail
26 ; LINUX-KERNEL-X64: .cfi_endproc
27
28 ; DARWIN-X64: test1a:
29 ; DARWIN-X64-NOT: callq ___stack_chk_fail
30 ; DARWIN-X64: .cfi_endproc
31 %a.addr = alloca i8*, align 8
32 %buf = alloca [16 x i8], align 16
33 store i8* %a, i8** %a.addr, align 8
34 %arraydecay = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
35 %0 = load i8** %a.addr, align 8
36 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
37 %arraydecay1 = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
38 %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1)
39 ret void
40 }
41
42 ; test1b: array of [16 x i8]
43 ; ssp attribute
44 ; Requires protector.
45 define void @test1b(i8* %a) nounwind uwtable ssp {
46 entry:
47 ; LINUX-I386: test1b:
48 ; LINUX-I386: mov{{l|q}} %gs:
49 ; LINUX-I386: calll __stack_chk_fail
50
51 ; LINUX-X64: test1b:
52 ; LINUX-X64: mov{{l|q}} %fs:
53 ; LINUX-X64: callq __stack_chk_fail
54
55 ; LINUX-KERNEL-X64: test1b:
56 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
57 ; LINUX-KERNEL-X64: callq __stack_chk_fail
58
59 ; DARWIN-X64: test1b:
60 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
61 ; DARWIN-X64: callq ___stack_chk_fail
62 %a.addr = alloca i8*, align 8
63 %buf = alloca [16 x i8], align 16
64 store i8* %a, i8** %a.addr, align 8
65 %arraydecay = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
66 %0 = load i8** %a.addr, align 8
67 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
68 %arraydecay1 = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
69 %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1)
70 ret void
71 }
72
73 ; test1c: array of [16 x i8]
74 ; sspstrong attribute
75 ; Requires protector.
76 define void @test1c(i8* %a) nounwind uwtable sspstrong {
77 entry:
78 ; LINUX-I386: test1c:
79 ; LINUX-I386: mov{{l|q}} %gs:
80 ; LINUX-I386: calll __stack_chk_fail
81
82 ; LINUX-X64: test1c:
83 ; LINUX-X64: mov{{l|q}} %fs:
84 ; LINUX-X64: callq __stack_chk_fail
85
86 ; LINUX-KERNEL-X64: test1c:
87 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
88 ; LINUX-KERNEL-X64: callq __stack_chk_fail
89
90 ; DARWIN-X64: test1c:
91 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
92 ; DARWIN-X64: callq ___stack_chk_fail
93 %a.addr = alloca i8*, align 8
94 %buf = alloca [16 x i8], align 16
95 store i8* %a, i8** %a.addr, align 8
96 %arraydecay = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
97 %0 = load i8** %a.addr, align 8
98 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
99 %arraydecay1 = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
100 %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1)
101 ret void
102 }
103
104 ; test1d: array of [16 x i8]
105 ; sspreq attribute
106 ; Requires protector.
107 define void @test1d(i8* %a) nounwind uwtable sspreq {
108 entry:
109 ; LINUX-I386: test1d:
110 ; LINUX-I386: mov{{l|q}} %gs:
111 ; LINUX-I386: calll __stack_chk_fail
112
113 ; LINUX-X64: test1d:
114 ; LINUX-X64: mov{{l|q}} %fs:
115 ; LINUX-X64: callq __stack_chk_fail
116
117 ; LINUX-KERNEL-X64: test1d:
118 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
119 ; LINUX-KERNEL-X64: callq __stack_chk_fail
120
121 ; DARWIN-X64: test1d:
122 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
123 ; DARWIN-X64: callq ___stack_chk_fail
124 %a.addr = alloca i8*, align 8
125 %buf = alloca [16 x i8], align 16
126 store i8* %a, i8** %a.addr, align 8
127 %arraydecay = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
128 %0 = load i8** %a.addr, align 8
129 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
130 %arraydecay1 = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
131 %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1)
132 ret void
133 }
134
135 ; test2a: struct { [16 x i8] }
136 ; no ssp attribute
137 ; Requires no protector.
138 define void @test2a(i8* %a) nounwind uwtable {
139 entry:
140 ; LINUX-I386: test2a:
141 ; LINUX-I386-NOT: calll __stack_chk_fail
142 ; LINUX-I386: .cfi_endproc
143
144 ; LINUX-X64: test2a:
145 ; LINUX-X64-NOT: callq __stack_chk_fail
146 ; LINUX-X64: .cfi_endproc
147
148 ; LINUX-KERNEL-X64: test2a:
149 ; LINUX-KERNEL-X64-NOT: callq __stack_chk_fail
150 ; LINUX-KERNEL-X64: .cfi_endproc
151
152 ; DARWIN-X64: test2a:
153 ; DARWIN-X64-NOT: callq ___stack_chk_fail
154 ; DARWIN-X64: .cfi_endproc
155 %a.addr = alloca i8*, align 8
156 %b = alloca %struct.foo, align 1
157 store i8* %a, i8** %a.addr, align 8
158 %buf = getelementptr inbounds %struct.foo* %b, i32 0, i32 0
159 %arraydecay = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
160 %0 = load i8** %a.addr, align 8
161 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
162 %buf1 = getelementptr inbounds %struct.foo* %b, i32 0, i32 0
163 %arraydecay2 = getelementptr inbounds [16 x i8]* %buf1, i32 0, i32 0
164 %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay2)
165 ret void
166 }
167
168 ; test2b: struct { [16 x i8] }
169 ; ssp attribute
170 ; Requires protector.
171 define void @test2b(i8* %a) nounwind uwtable ssp {
172 entry:
173 ; LINUX-I386: test2b:
174 ; LINUX-I386: mov{{l|q}} %gs:
175 ; LINUX-I386: calll __stack_chk_fail
176
177 ; LINUX-X64: test2b:
178 ; LINUX-X64: mov{{l|q}} %fs:
179 ; LINUX-X64: callq __stack_chk_fail
180
181 ; LINUX-KERNEL-X64: test2b:
182 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
183 ; LINUX-KERNEL-X64: callq __stack_chk_fail
184
185 ; DARWIN-X64: test2b:
186 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
187 ; DARWIN-X64: callq ___stack_chk_fail
188 %a.addr = alloca i8*, align 8
189 %b = alloca %struct.foo, align 1
190 store i8* %a, i8** %a.addr, align 8
191 %buf = getelementptr inbounds %struct.foo* %b, i32 0, i32 0
192 %arraydecay = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
193 %0 = load i8** %a.addr, align 8
194 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
195 %buf1 = getelementptr inbounds %struct.foo* %b, i32 0, i32 0
196 %arraydecay2 = getelementptr inbounds [16 x i8]* %buf1, i32 0, i32 0
197 %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay2)
198 ret void
199 }
200
201 ; test2c: struct { [16 x i8] }
202 ; sspstrong attribute
203 ; Requires protector.
204 define void @test2c(i8* %a) nounwind uwtable sspstrong {
205 entry:
206 ; LINUX-I386: test2c:
207 ; LINUX-I386: mov{{l|q}} %gs:
208 ; LINUX-I386: calll __stack_chk_fail
209
210 ; LINUX-X64: test2c:
211 ; LINUX-X64: mov{{l|q}} %fs:
212 ; LINUX-X64: callq __stack_chk_fail
213
214 ; LINUX-KERNEL-X64: test2c:
215 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
216 ; LINUX-KERNEL-X64: callq __stack_chk_fail
217
218 ; DARWIN-X64: test2c:
219 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
220 ; DARWIN-X64: callq ___stack_chk_fail
221 %a.addr = alloca i8*, align 8
222 %b = alloca %struct.foo, align 1
223 store i8* %a, i8** %a.addr, align 8
224 %buf = getelementptr inbounds %struct.foo* %b, i32 0, i32 0
225 %arraydecay = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
226 %0 = load i8** %a.addr, align 8
227 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
228 %buf1 = getelementptr inbounds %struct.foo* %b, i32 0, i32 0
229 %arraydecay2 = getelementptr inbounds [16 x i8]* %buf1, i32 0, i32 0
230 %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay2)
231 ret void
232 }
233
234 ; test2d: struct { [16 x i8] }
235 ; sspreq attribute
236 ; Requires protector.
237 define void @test2d(i8* %a) nounwind uwtable sspreq {
238 entry:
239 ; LINUX-I386: test2d:
240 ; LINUX-I386: mov{{l|q}} %gs:
241 ; LINUX-I386: calll __stack_chk_fail
242
243 ; LINUX-X64: test2d:
244 ; LINUX-X64: mov{{l|q}} %fs:
245 ; LINUX-X64: callq __stack_chk_fail
246
247 ; LINUX-KERNEL-X64: test2d:
248 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
249 ; LINUX-KERNEL-X64: callq __stack_chk_fail
250
251 ; DARWIN-X64: test2d:
252 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
253 ; DARWIN-X64: callq ___stack_chk_fail
254 %a.addr = alloca i8*, align 8
255 %b = alloca %struct.foo, align 1
256 store i8* %a, i8** %a.addr, align 8
257 %buf = getelementptr inbounds %struct.foo* %b, i32 0, i32 0
258 %arraydecay = getelementptr inbounds [16 x i8]* %buf, i32 0, i32 0
259 %0 = load i8** %a.addr, align 8
260 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
261 %buf1 = getelementptr inbounds %struct.foo* %b, i32 0, i32 0
262 %arraydecay2 = getelementptr inbounds [16 x i8]* %buf1, i32 0, i32 0
263 %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay2)
264 ret void
265 }
266
267 ; test3a: array of [4 x i8]
268 ; no ssp attribute
269 ; Requires no protector.
270 define void @test3a(i8* %a) nounwind uwtable {
271 entry:
272 ; LINUX-I386: test3a:
273 ; LINUX-I386-NOT: calll __stack_chk_fail
274 ; LINUX-I386: .cfi_endproc
275
276 ; LINUX-X64: test3a:
277 ; LINUX-X64-NOT: callq __stack_chk_fail
278 ; LINUX-X64: .cfi_endproc
279
280 ; LINUX-KERNEL-X64: test3a:
281 ; LINUX-KERNEL-X64-NOT: callq __stack_chk_fail
282 ; LINUX-KERNEL-X64: .cfi_endproc
283
284 ; DARWIN-X64: test3a:
285 ; DARWIN-X64-NOT: callq ___stack_chk_fail
286 ; DARWIN-X64: .cfi_endproc
287 %a.addr = alloca i8*, align 8
288 %buf = alloca [4 x i8], align 1
289 store i8* %a, i8** %a.addr, align 8
290 %arraydecay = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
291 %0 = load i8** %a.addr, align 8
292 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
293 %arraydecay1 = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
294 %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1)
295 ret void
296 }
297
298 ; test3b: array [4 x i8]
299 ; ssp attribute
300 ; Requires no protector.
301 define void @test3b(i8* %a) nounwind uwtable ssp {
302 entry:
303 ; LINUX-I386: test3b:
304 ; LINUX-I386-NOT: calll __stack_chk_fail
305 ; LINUX-I386: .cfi_endproc
306
307 ; LINUX-X64: test3b:
308 ; LINUX-X64-NOT: callq __stack_chk_fail
309 ; LINUX-X64: .cfi_endproc
310
311 ; LINUX-KERNEL-X64: test3b:
312 ; LINUX-KERNEL-X64-NOT: callq __stack_chk_fail
313 ; LINUX-KERNEL-X64: .cfi_endproc
314
315 ; DARWIN-X64: test3b:
316 ; DARWIN-X64-NOT: callq ___stack_chk_fail
317 ; DARWIN-X64: .cfi_endproc
318 %a.addr = alloca i8*, align 8
319 %buf = alloca [4 x i8], align 1
320 store i8* %a, i8** %a.addr, align 8
321 %arraydecay = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
322 %0 = load i8** %a.addr, align 8
323 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
324 %arraydecay1 = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
325 %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1)
326 ret void
327 }
328
329 ; test3c: array of [4 x i8]
330 ; sspstrong attribute
331 ; Requires protector.
332 define void @test3c(i8* %a) nounwind uwtable sspstrong {
333 entry:
334 ; LINUX-I386: test3c:
335 ; LINUX-I386: mov{{l|q}} %gs:
336 ; LINUX-I386: calll __stack_chk_fail
337
338 ; LINUX-X64: test3c:
339 ; LINUX-X64: mov{{l|q}} %fs:
340 ; LINUX-X64: callq __stack_chk_fail
341
342 ; LINUX-KERNEL-X64: test3c:
343 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
344 ; LINUX-KERNEL-X64: callq __stack_chk_fail
345
346 ; DARWIN-X64: test3c:
347 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
348 ; DARWIN-X64: callq ___stack_chk_fail
349 %a.addr = alloca i8*, align 8
350 %buf = alloca [4 x i8], align 1
351 store i8* %a, i8** %a.addr, align 8
352 %arraydecay = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
353 %0 = load i8** %a.addr, align 8
354 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
355 %arraydecay1 = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
356 %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1)
357 ret void
358 }
359
360 ; test3d: array of [4 x i8]
361 ; sspreq attribute
362 ; Requires protector.
363 define void @test3d(i8* %a) nounwind uwtable sspreq {
364 entry:
365 ; LINUX-I386: test3d:
366 ; LINUX-I386: mov{{l|q}} %gs:
367 ; LINUX-I386: calll __stack_chk_fail
368
369 ; LINUX-X64: test3d:
370 ; LINUX-X64: mov{{l|q}} %fs:
371 ; LINUX-X64: callq __stack_chk_fail
372
373 ; LINUX-KERNEL-X64: test3d:
374 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
375 ; LINUX-KERNEL-X64: callq __stack_chk_fail
376
377 ; DARWIN-X64: test3d:
378 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
379 ; DARWIN-X64: callq ___stack_chk_fail
380 %a.addr = alloca i8*, align 8
381 %buf = alloca [4 x i8], align 1
382 store i8* %a, i8** %a.addr, align 8
383 %arraydecay = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
384 %0 = load i8** %a.addr, align 8
385 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
386 %arraydecay1 = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
387 %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1)
388 ret void
389 }
390
391 ; test4a: struct { [4 x i8] }
392 ; no ssp attribute
393 ; Requires no protector.
394 define void @test4a(i8* %a) nounwind uwtable {
395 entry:
396 ; LINUX-I386: test4a:
397 ; LINUX-I386-NOT: calll __stack_chk_fail
398 ; LINUX-I386: .cfi_endproc
399
400 ; LINUX-X64: test4a:
401 ; LINUX-X64-NOT: callq __stack_chk_fail
402 ; LINUX-X64: .cfi_endproc
403
404 ; LINUX-KERNEL-X64: test4a:
405 ; LINUX-KERNEL-X64-NOT: callq __stack_chk_fail
406 ; LINUX-KERNEL-X64: .cfi_endproc
407
408 ; DARWIN-X64: test4a:
409 ; DARWIN-X64-NOT: callq ___stack_chk_fail
410 ; DARWIN-X64: .cfi_endproc
411 %a.addr = alloca i8*, align 8
412 %b = alloca %struct.foo.0, align 1
413 store i8* %a, i8** %a.addr, align 8
414 %buf = getelementptr inbounds %struct.foo.0* %b, i32 0, i32 0
415 %arraydecay = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
416 %0 = load i8** %a.addr, align 8
417 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
418 %buf1 = getelementptr inbounds %struct.foo.0* %b, i32 0, i32 0
419 %arraydecay2 = getelementptr inbounds [4 x i8]* %buf1, i32 0, i32 0
420 %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay2)
421 ret void
422 }
423
424 ; test4b: struct { [4 x i8] }
425 ; ssp attribute
426 ; Requires no protector.
427 define void @test4b(i8* %a) nounwind uwtable ssp {
428 entry:
429 ; LINUX-I386: test4b:
430 ; LINUX-I386-NOT: calll __stack_chk_fail
431 ; LINUX-I386: .cfi_endproc
432
433 ; LINUX-X64: test4b:
434 ; LINUX-X64-NOT: callq __stack_chk_fail
435 ; LINUX-X64: .cfi_endproc
436
437 ; LINUX-KERNEL-X64: test4b:
438 ; LINUX-KERNEL-X64-NOT: callq __stack_chk_fail
439 ; LINUX-KERNEL-X64: .cfi_endproc
440
441 ; DARWIN-X64: test4b:
442 ; DARWIN-X64-NOT: callq ___stack_chk_fail
443 ; DARWIN-X64: .cfi_endproc
444 %a.addr = alloca i8*, align 8
445 %b = alloca %struct.foo.0, align 1
446 store i8* %a, i8** %a.addr, align 8
447 %buf = getelementptr inbounds %struct.foo.0* %b, i32 0, i32 0
448 %arraydecay = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
449 %0 = load i8** %a.addr, align 8
450 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
451 %buf1 = getelementptr inbounds %struct.foo.0* %b, i32 0, i32 0
452 %arraydecay2 = getelementptr inbounds [4 x i8]* %buf1, i32 0, i32 0
453 %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay2)
454 ret void
455 }
456
457 ; test4c: struct { [4 x i8] }
458 ; sspstrong attribute
459 ; Requires protector.
460 define void @test4c(i8* %a) nounwind uwtable sspstrong {
461 entry:
462 ; LINUX-I386: test4c:
463 ; LINUX-I386: mov{{l|q}} %gs:
464 ; LINUX-I386: calll __stack_chk_fail
465
466 ; LINUX-X64: test4c:
467 ; LINUX-X64: mov{{l|q}} %fs:
468 ; LINUX-X64: callq __stack_chk_fail
469
470 ; LINUX-KERNEL-X64: test4c:
471 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
472 ; LINUX-KERNEL-X64: callq __stack_chk_fail
473
474 ; DARWIN-X64: test4c:
475 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
476 ; DARWIN-X64: callq ___stack_chk_fail
477 %a.addr = alloca i8*, align 8
478 %b = alloca %struct.foo.0, align 1
479 store i8* %a, i8** %a.addr, align 8
480 %buf = getelementptr inbounds %struct.foo.0* %b, i32 0, i32 0
481 %arraydecay = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
482 %0 = load i8** %a.addr, align 8
483 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
484 %buf1 = getelementptr inbounds %struct.foo.0* %b, i32 0, i32 0
485 %arraydecay2 = getelementptr inbounds [4 x i8]* %buf1, i32 0, i32 0
486 %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay2)
487 ret void
488 }
489
490 ; test4d: struct { [4 x i8] }
491 ; sspreq attribute
492 ; Requires protector.
493 define void @test4d(i8* %a) nounwind uwtable sspreq {
494 entry:
495 ; LINUX-I386: test4d:
496 ; LINUX-I386: mov{{l|q}} %gs:
497 ; LINUX-I386: calll __stack_chk_fail
498
499 ; LINUX-X64: test4d:
500 ; LINUX-X64: mov{{l|q}} %fs:
501 ; LINUX-X64: callq __stack_chk_fail
502
503 ; LINUX-KERNEL-X64: test4d:
504 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
505 ; LINUX-KERNEL-X64: callq __stack_chk_fail
506
507 ; DARWIN-X64: test4d:
508 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
509 ; DARWIN-X64: callq ___stack_chk_fail
510 %a.addr = alloca i8*, align 8
511 %b = alloca %struct.foo.0, align 1
512 store i8* %a, i8** %a.addr, align 8
513 %buf = getelementptr inbounds %struct.foo.0* %b, i32 0, i32 0
514 %arraydecay = getelementptr inbounds [4 x i8]* %buf, i32 0, i32 0
515 %0 = load i8** %a.addr, align 8
516 %call = call i8* @strcpy(i8* %arraydecay, i8* %0)
517 %buf1 = getelementptr inbounds %struct.foo.0* %b, i32 0, i32 0
518 %arraydecay2 = getelementptr inbounds [4 x i8]* %buf1, i32 0, i32 0
519 %call3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay2)
520 ret void
521 }
522
523 ; test5a: no arrays / no nested arrays
524 ; no ssp attribute
525 ; Requires no protector.
526 define void @test5a(i8* %a) nounwind uwtable {
527 entry:
528 ; LINUX-I386: test5a:
529 ; LINUX-I386-NOT: calll __stack_chk_fail
530 ; LINUX-I386: .cfi_endproc
531
532 ; LINUX-X64: test5a:
533 ; LINUX-X64-NOT: callq __stack_chk_fail
534 ; LINUX-X64: .cfi_endproc
535
536 ; LINUX-KERNEL-X64: test5a:
537 ; LINUX-KERNEL-X64-NOT: callq __stack_chk_fail
538 ; LINUX-KERNEL-X64: .cfi_endproc
539
540 ; DARWIN-X64: test5a:
541 ; DARWIN-X64-NOT: callq ___stack_chk_fail
542 ; DARWIN-X64: .cfi_endproc
543 %a.addr = alloca i8*, align 8
544 store i8* %a, i8** %a.addr, align 8
545 %0 = load i8** %a.addr, align 8
546 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %0)
547 ret void
548 }
549
550 ; test5b: no arrays / no nested arrays
551 ; ssp attribute
552 ; Requires no protector.
553 define void @test5b(i8* %a) nounwind uwtable ssp {
554 entry:
555 ; LINUX-I386: test5b:
556 ; LINUX-I386-NOT: calll __stack_chk_fail
557 ; LINUX-I386: .cfi_endproc
558
559 ; LINUX-X64: test5b:
560 ; LINUX-X64-NOT: callq __stack_chk_fail
561 ; LINUX-X64: .cfi_endproc
562
563 ; LINUX-KERNEL-X64: test5b:
564 ; LINUX-KERNEL-X64-NOT: callq __stack_chk_fail
565 ; LINUX-KERNEL-X64: .cfi_endproc
566
567 ; DARWIN-X64: test5b:
568 ; DARWIN-X64-NOT: callq ___stack_chk_fail
569 ; DARWIN-X64: .cfi_endproc
570 %a.addr = alloca i8*, align 8
571 store i8* %a, i8** %a.addr, align 8
572 %0 = load i8** %a.addr, align 8
573 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %0)
574 ret void
575 }
576
577 ; test5c: no arrays / no nested arrays
578 ; sspstrong attribute
579 ; Requires protector.
580 ; FIXME: Once strong heuristic is implemented, this should _not_ require
581 ; a protector
582 define void @test5c(i8* %a) nounwind uwtable sspstrong {
583 entry:
584 ; LINUX-I386: test5c:
585 ; LINUX-I386: mov{{l|q}} %gs:
586 ; LINUX-I386: calll __stack_chk_fail
587
588 ; LINUX-X64: test5c:
589 ; LINUX-X64: mov{{l|q}} %fs:
590 ; LINUX-X64: callq __stack_chk_fail
591
592 ; LINUX-KERNEL-X64: test5c:
593 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
594 ; LINUX-KERNEL-X64: callq __stack_chk_fail
595
596 ; DARWIN-X64: test5c:
597 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
598 ; DARWIN-X64: callq ___stack_chk_fail
599 %a.addr = alloca i8*, align 8
600 store i8* %a, i8** %a.addr, align 8
601 %0 = load i8** %a.addr, align 8
602 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %0)
603 ret void
604 }
605
606 ; test5d: no arrays / no nested arrays
607 ; sspreq attribute
608 ; Requires protector.
609 define void @test5d(i8* %a) nounwind uwtable sspreq {
610 entry:
611 ; LINUX-I386: test5d:
612 ; LINUX-I386: mov{{l|q}} %gs:
613 ; LINUX-I386: calll __stack_chk_fail
614
615 ; LINUX-X64: test5d:
616 ; LINUX-X64: mov{{l|q}} %fs:
617 ; LINUX-X64: callq __stack_chk_fail
618
619 ; LINUX-KERNEL-X64: test5d:
620 ; LINUX-KERNEL-X64: mov{{l|q}} %gs:
621 ; LINUX-KERNEL-X64: callq __stack_chk_fail
622
623 ; DARWIN-X64: test5d:
624 ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard
625 ; DARWIN-X64: callq ___stack_chk_fail
626 %a.addr = alloca i8*, align 8
627 store i8* %a, i8** %a.addr, align 8
628 %0 = load i8** %a.addr, align 8
629 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i8* %0)
630 ret void
631 }
632
633 declare i8* @strcpy(i8*, i8*)
634 declare i32 @printf(i8*, ...)
0 ; RUN: opt -inline %s -S | FileCheck %s
1 ; Ensure SSP attributes are propagated correctly when inlining.
2
3 @.str = private unnamed_addr constant [11 x i8] c"fun_nossp\0A\00", align 1
4 @.str1 = private unnamed_addr constant [9 x i8] c"fun_ssp\0A\00", align 1
5 @.str2 = private unnamed_addr constant [15 x i8] c"fun_sspstrong\0A\00", align 1
6 @.str3 = private unnamed_addr constant [12 x i8] c"fun_sspreq\0A\00", align 1
7
8 ; These first four functions (@fun_sspreq, @fun_sspstrong, @fun_ssp, @fun_nossp)
9 ; are used by the remaining functions to ensure that the SSP attributes are
10 ; propagated correctly. The caller should have its SSP attribute set as:
11 ; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as:
12 ; sspreq > sspstrong > ssp > [no ssp]
13 define internal void @fun_sspreq() nounwind uwtable sspreq {
14 entry:
15 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([12 x i8]* @.str3, i32 0, i32 0))
16 ret void
17 }
18
19 define internal void @fun_sspstrong() nounwind uwtable sspstrong {
20 entry:
21 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str2, i32 0, i32 0))
22 ret void
23 }
24
25 define internal void @fun_ssp() nounwind uwtable ssp {
26 entry:
27 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str1, i32 0, i32 0))
28 ret void
29 }
30
31 define internal void @fun_nossp() nounwind uwtable {
32 entry:
33 %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str, i32 0, i32 0))
34 ret void
35 }
36
37 ; Tests start below
38
39 define void @inline_req_req() nounwind uwtable sspreq {
40 entry:
41 ; CHECK: @inline_req_req() nounwind uwtable sspreq
42 call void @fun_sspreq()
43 ret void
44 }
45
46 define void @inline_req_strong() nounwind uwtable sspstrong {
47 entry:
48 ; CHECK: @inline_req_strong() nounwind uwtable sspreq
49 call void @fun_sspreq()
50 ret void
51 }
52
53 define void @inline_req_ssp() nounwind uwtable ssp {
54 entry:
55 ; CHECK: @inline_req_ssp() nounwind uwtable sspreq
56 call void @fun_sspreq()
57 ret void
58 }
59
60 define void @inline_req_nossp() nounwind uwtable {
61 entry:
62 ; CHECK: @inline_req_nossp() nounwind uwtable sspreq
63 call void @fun_sspreq()
64 ret void
65 }
66
67 define void @inline_strong_req() nounwind uwtable sspreq {
68 entry:
69 ; CHECK: @inline_strong_req() nounwind uwtable sspreq
70 call void @fun_sspstrong()
71 ret void
72 }
73
74
75 define void @inline_strong_strong() nounwind uwtable sspstrong {
76 entry:
77 ; CHECK: @inline_strong_strong() nounwind uwtable sspstrong
78 call void @fun_sspstrong()
79 ret void
80 }
81
82 define void @inline_strong_ssp() nounwind uwtable ssp {
83 entry:
84 ; CHECK: @inline_strong_ssp() nounwind uwtable sspstrong
85 call void @fun_sspstrong()
86 ret void
87 }
88
89 define void @inline_strong_nossp() nounwind uwtable {
90 entry:
91 ; CHECK: @inline_strong_nossp() nounwind uwtable sspstrong
92 call void @fun_sspstrong()
93 ret void
94 }
95
96 define void @inline_ssp_req() nounwind uwtable sspreq {
97 entry:
98 ; CHECK: @inline_ssp_req() nounwind uwtable sspreq
99 call void @fun_ssp()
100 ret void
101 }
102
103
104 define void @inline_ssp_strong() nounwind uwtable sspstrong {
105 entry:
106 ; CHECK: @inline_ssp_strong() nounwind uwtable sspstrong
107 call void @fun_ssp()
108 ret void
109 }
110
111 define void @inline_ssp_ssp() nounwind uwtable ssp {
112 entry:
113 ; CHECK: @inline_ssp_ssp() nounwind uwtable ssp
114 call void @fun_ssp()
115 ret void
116 }
117
118 define void @inline_ssp_nossp() nounwind uwtable {
119 entry:
120 ; CHECK: @inline_ssp_nossp() nounwind uwtable ssp
121 call void @fun_ssp()
122 ret void
123 }
124
125 define void @inline_nossp_req() nounwind uwtable sspreq {
126 entry:
127 ; CHECK: @inline_nossp_req() nounwind uwtable sspreq
128 call void @fun_nossp()
129 ret void
130 }
131
132
133 define void @inline_nossp_strong() nounwind uwtable sspstrong {
134 entry:
135 ; CHECK: @inline_nossp_strong() nounwind uwtable sspstrong
136 call void @fun_nossp()
137 ret void
138 }
139
140 define void @inline_nossp_ssp() nounwind uwtable ssp {
141 entry:
142 ; CHECK: @inline_nossp_ssp() nounwind uwtable ssp
143 call void @fun_nossp()
144 ret void
145 }
146
147 define void @inline_nossp_nossp() nounwind uwtable {
148 entry:
149 ; CHECK: @inline_nossp_nossp() nounwind uwtable
150 call void @fun_nossp()
151 ret void
152 }
153
154 declare i32 @printf(i8*, ...)
8989 readonly
9090 ssp
9191 sspreq
92 sspstrong
9293
9394
9495 float
5050 syn keyword llvmKeyword nounwind optsize personality private protected
5151 syn keyword llvmKeyword ptx_device ptx_kernel readnone readonly release
5252 syn keyword llvmKeyword returns_twice section seq_cst sideeffect signext
53 syn keyword llvmKeyword singlethread spir_func spir_kernel sret ssp sspreq tail
54 syn keyword llvmKeyword target thread_local to triple unnamed_addr unordered
55 syn keyword llvmKeyword uwtable volatile weak weak_odr x86_fastcallcc
56 syn keyword llvmKeyword x86_stdcallcc x86_thiscallcc zeroext
53 syn keyword llvmKeyword singlethread spir_func spir_kernel sret ssp sspreq
54 syn keyword llvmKeyword sspstrong tail target thread_local to triple
55 syn keyword llvmKeyword unnamed_addr unordered uwtable volatile weak weak_odr
56 syn keyword llvmKeyword x86_fastcallcc x86_stdcallcc x86_thiscallcc zeroext
5757
5858 " Obsolete keywords.
5959 syn keyword llvmError getresult begin end