1 # RUN: llc -mtriple="i386-pc-windows-msvc" -run-pass=stack-coloring %s -o - | FileCheck %s
3 # There is a problem with the exception handler, we found in windows, when set
4 # LifetimeStartOnFirstUse=true for stack-coloring in default. Take the following
7 #// Compile with "clang-cl -m32 -O2 -EHs test.cpp"
8 #__attribute__((noinline,nothrow,weak)) void escape(int *p) { }
15 # // if "object" and "exp" are assigned to the same slot,
16 # // this assign will corrupt "exp".
21 #inline void throwit() { throw 999; }
29 # // "exp" is written by the OS when the "throw" occurs.
30 # // Then the destructor is called, and the store-assign
31 # // clobbers the value of "exp".
32 # // The dereference of "exp" (with value 9999) causes a crash.
33 # // All these done in libruntime, so it is hard to check in IR.
44 ## Make sure that o.i not merge with exp.i
46 # CHECK: id: 2, name: o.i, type: default, offset: 0, size: 4, alignment: 4,
47 # CHECK: id: 3, name: exp.i, type: default, offset: 0, size: 4, alignment: 4,
49 ## Make sure that %stack.3.exp.i not replaced with %stack.2.o.i
50 # CHECK: bb.3.catch.i (landing-pad, ehfunclet-entry):
51 # CHECK: %7:gr32 = MOV32rm %stack.3.exp.i, 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from %ir.exp.i)
54 ; ModuleID = 'test-pre-stc.mir'
55 source_filename = "test.cpp"
56 target datalayout = "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-a:0:32-S32"
58 %rtti.TypeDescriptor2 = type { ptr, ptr, [3 x i8] }
59 %eh.CatchableType = type { i32, ptr, i32, i32, i32, i32, ptr }
60 %eh.CatchableTypeArray.1 = type { i32, [1 x ptr] }
61 %eh.ThrowInfo = type { i32, ptr, ptr, ptr }
62 %CXXExceptionRegistration = type { ptr, %EHRegistrationNode, i32 }
63 %EHRegistrationNode = type { ptr, ptr }
64 %struct.object = type { i32 }
66 $"_R0H@8" = comdat any
68 $"_CT_R0H@84" = comdat any
74 @v__3HC = dso_local global i32 0, align 4
75 @"_7type_info__6B@" = external constant ptr
76 @"_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { ptr @"_7type_info__6B@", ptr null, [3 x i8] c".H\00" }, comdat
77 @"_CT_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, ptr @"_R0H@8", i32 0, i32 -1, i32 0, i32 4, ptr null }, section ".xdata", comdat
78 @_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x ptr] [ptr @"_CT_R0H@84"] }, section ".xdata", comdat
79 @_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, ptr null, ptr null, ptr @_CTA1H }, section ".xdata", comdat
81 ; Function Attrs: noinline nounwind sspstrong
82 define weak dso_local void @"escape__YAXPAH@Z"(ptr %p) local_unnamed_addr #0 {
87 ; Function Attrs: norecurse sspstrong
88 define dso_local i32 @main() local_unnamed_addr #1 personality i32 (...)* @__CxxFrameHandler3 {
90 %0 = alloca %CXXExceptionRegistration, align 4
91 %1 = bitcast ptr %0 to ptr
92 call void @llvm.x86.seh.ehregnode(ptr %1)
93 %2 = call ptr @llvm.stacksave()
94 %3 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 0
95 store ptr %2, ptr %3, align 4
96 %4 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 2
97 store i32 -1, ptr %4, align 4
98 %5 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 1
99 %6 = getelementptr inbounds %EHRegistrationNode, ptr %5, i32 0, i32 1
100 store ptr @"__ehhandler$main", ptr %6, align 4
101 %7 = load ptr, ptr addrspace(257) null, align 4
102 %8 = getelementptr inbounds %EHRegistrationNode, ptr %5, i32 0, i32 0
103 store ptr %7, ptr %8, align 4
104 store ptr %5, ptr addrspace(257) null, align 4
105 %tmp.i.i = alloca i32, align 4
106 %o.i = alloca %struct.object, align 4
107 %zx = alloca ptr, align 4
108 %exp.i = alloca ptr, align 4
109 %9 = bitcast ptr %exp.i to ptr
110 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %9)
111 %10 = bitcast ptr %o.i to ptr
112 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %10) #7
113 %i.i.i1 = bitcast ptr %o.i to ptr
114 store i32 1, ptr %i.i.i1, align 4
115 %11 = bitcast ptr %tmp.i.i to ptr
116 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %11)
117 store i32 999, ptr %tmp.i.i, align 4
118 %12 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 2
119 store i32 1, ptr %12, align 4
120 invoke void @_CxxThrowException(ptr nonnull %11, ptr nonnull @_TI1H) #8
121 to label %.noexc.i unwind label %ehcleanup.i
123 .noexc.i: ; preds = %entry
126 ehcleanup.i: ; preds = %entry
127 %13 = cleanuppad within none []
128 %14 = bitcast ptr %o.i to ptr
129 %15 = bitcast ptr %o.i to ptr
130 store i32 9999, ptr %14, align 4
131 call void @"escape__YAXPAH@Z"(ptr nonnull %14) #7 [ "funclet"(token %13) ]
132 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %15) #7
133 cleanupret from %13 unwind label %catch.dispatch.i
135 catch.dispatch.i: ; preds = %ehcleanup.i
136 %16 = catchswitch within none [label %catch.i] unwind to caller
138 catch.i: ; preds = %catch.dispatch.i
139 %17 = catchpad within %16 [ptr @"_R0H@8", i32 8, ptr %exp.i]
140 %18 = load ptr, ptr %exp.i, align 4
141 %19 = load i32, ptr %18, align 4
142 store atomic volatile i32 %19, ptr @v__3HC release, align 4
143 catchret from %17 to label %func__YAXXZ.exit
145 func__YAXXZ.exit: ; preds = %catch.i
146 %20 = bitcast ptr %exp.i to ptr
147 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %20)
148 %21 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 1
149 %22 = getelementptr inbounds %EHRegistrationNode, ptr %21, i32 0, i32 0
150 %23 = load ptr, ptr %22, align 4
151 store ptr %23, ptr addrspace(257) null, align 4
155 ; Function Attrs: argmemonly nofree nosync nounwind willreturn
156 declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2
158 ; Function Attrs: nofree
159 declare dso_local i32 @__CxxFrameHandler3(...) #3
161 ; Function Attrs: argmemonly nofree nosync nounwind willreturn
162 declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2
164 ; Function Attrs: nofree
165 declare dso_local x86_stdcallcc void @_CxxThrowException(ptr, ptr) local_unnamed_addr #3
167 declare i32 @_setjmp3(ptr, i32, ...)
169 ; Function Attrs: nofree nosync nounwind willreturn
170 declare ptr @llvm.stacksave() #4
172 define internal i32 @"__ehhandler$main"(ptr %0, ptr %1, ptr %2, ptr %3) #5 {
174 %4 = call ptr @llvm.x86.seh.lsda(ptr @main)
175 %5 = tail call i32 @__CxxFrameHandler3(ptr inreg %4, ptr %0, ptr %1, ptr %2, ptr %3)
179 ; Function Attrs: nounwind readnone
180 declare ptr @llvm.x86.seh.lsda(ptr) #6
182 declare x86_stdcallcc void @__CxxLongjmpUnwind(ptr)
184 ; Function Attrs: nounwind
185 declare void @llvm.x86.seh.ehregnode(ptr) #7
187 attributes #0 = { noinline nounwind sspstrong "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
188 attributes #1 = { norecurse sspstrong "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
189 attributes #2 = { argmemonly nofree nosync nounwind willreturn }
190 attributes #3 = { nofree }
191 attributes #4 = { nofree nosync nounwind willreturn }
192 attributes #5 = { "safeseh" }
193 attributes #6 = { nounwind readnone }
194 attributes #7 = { nounwind }
195 attributes #8 = { noreturn }
197 !llvm.linker.options = !{!0, !1, !2}
198 !llvm.module.flags = !{!3, !4}
201 !0 = !{!"/DEFAULTLIB:libcmt.lib"}
202 !1 = !{!"/DEFAULTLIB:libmmt.lib"}
203 !2 = !{!"/DEFAULTLIB:oldnames.lib"}
204 !3 = !{i32 1, !"NumRegisterParameters", i32 0}
205 !4 = !{i32 1, !"wchar_size", i32 2}
206 !5 = !{!"Intel(R) oneAPI DPC++ Compiler Pro 2021.1 (YYYY.x.0.MMDD)"}
210 name: 'escape__YAXPAH@Z'
212 exposesReturnsTwice: false
214 regBankSelected: false
217 tracksRegLiveness: true
222 isFrameAddressTaken: false
223 isReturnAddressTaken: false
232 maxCallFrameSize: 4294967295
233 cvBytesOfCalleeSavedRegisters: 0
234 hasOpaqueSPAdjustment: false
236 hasMustTailInVarArgFunc: false
241 - { id: 0, type: default, offset: 0, size: 4, alignment: 4, stack-id: default,
242 isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
243 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
246 debugValueSubstitutions: []
248 machineFunctionInfo: {}
257 exposesReturnsTwice: false
259 regBankSelected: false
262 tracksRegLiveness: true
265 - { id: 0, class: gr32, preferred-register: '' }
266 - { id: 1, class: gr32, preferred-register: '' }
267 - { id: 2, class: gr32, preferred-register: '' }
268 - { id: 3, class: gr32, preferred-register: '' }
269 - { id: 4, class: gr32, preferred-register: '' }
270 - { id: 5, class: gr32, preferred-register: '' }
271 - { id: 6, class: gr32, preferred-register: '' }
272 - { id: 7, class: gr32, preferred-register: '' }
273 - { id: 8, class: gr32, preferred-register: '' }
274 - { id: 9, class: gr32, preferred-register: '' }
275 - { id: 10, class: gr32, preferred-register: '' }
278 isFrameAddressTaken: false
279 isReturnAddressTaken: false
288 maxCallFrameSize: 4294967295
289 cvBytesOfCalleeSavedRegisters: 0
290 hasOpaqueSPAdjustment: true
292 hasMustTailInVarArgFunc: false
298 - { id: 0, name: zx, type: default, offset: 0, size: 16, alignment: 4,
299 stack-id: default, callee-saved-register: '', callee-saved-restored: true,
300 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
301 - { id: 1, name: tmp.i.i, type: default, offset: 0, size: 4, alignment: 4,
302 stack-id: default, callee-saved-register: '', callee-saved-restored: true,
303 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
304 - { id: 2, name: o.i, type: default, offset: 0, size: 4, alignment: 4,
305 stack-id: default, callee-saved-register: '', callee-saved-restored: true,
306 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
307 - { id: 3, name: exp.i, type: default, offset: 0, size: 4, alignment: 4,
308 stack-id: default, callee-saved-register: '', callee-saved-restored: true,
309 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
311 debugValueSubstitutions: []
313 machineFunctionInfo: {}
316 successors: %bb.1(0x7ffff800), %bb.2(0x00000800)
319 MOV32mr %stack.0.zx, 1, $noreg, 0, $noreg, %0 :: (store (s32) into %ir.3)
320 MOV32mi %stack.0.zx, 1, $noreg, 12, $noreg, -1 :: (store (s32) into %ir.4)
321 %1:gr32 = nuw LEA32r %stack.0.zx, 1, $noreg, 4, $noreg
322 MOV32mi %stack.0.zx, 1, $noreg, 8, $noreg, @"__ehhandler$main" :: (store (s32) into %ir.6)
323 %2:gr32 = MOV32rm $noreg, 1, $noreg, 0, $fs :: (load (s32) from `ptr addrspace(257) null`, addrspace 257)
324 MOV32mr %stack.0.zx, 1, $noreg, 4, $noreg, killed %2 :: (store (s32) into %ir.8)
325 MOV32mr $noreg, 1, $noreg, 0, $fs, killed %1 :: (store (s32) into `ptr addrspace(257) null`, addrspace 257)
326 MOV32mi %stack.2.o.i, 1, $noreg, 0, $noreg, 1 :: (store (s32) into %ir.i.i.i1)
327 MOV32mi %stack.1.tmp.i.i, 1, $noreg, 0, $noreg, 999 :: (store (s32) into %ir.tmp.i.i)
328 MOV32mi %stack.0.zx, 1, $noreg, 12, $noreg, 1 :: (store (s32) into %ir.12)
329 ADJCALLSTACKDOWN32 8, 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp
331 %4:gr32 = LEA32r %stack.1.tmp.i.i, 1, $noreg, 0, $noreg
332 MOV32mr %3, 1, $noreg, 0, $noreg, killed %4 :: (store (s32) into stack)
333 MOV32mi %3, 1, $noreg, 4, $noreg, @_TI1H :: (store (s32) into stack + 4)
334 CALLpcrel32 @_CxxThrowException, csr_noregs, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp
335 ADJCALLSTACKUP32 8, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp
342 bb.2.ehcleanup.i (landing-pad, ehfunclet-entry):
343 successors: %bb.3(0x80000000)
345 MOV32mi %stack.2.o.i, 1, $noreg, 0, $noreg, 9999 :: (store (s32) into %ir.14)
346 ADJCALLSTACKDOWN32 4, 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp
348 %6:gr32 = LEA32r %stack.2.o.i, 1, $noreg, 0, $noreg
349 MOV32mr %5, 1, $noreg, 0, $noreg, killed %6 :: (store (s32) into stack)
350 CALLpcrel32 @"escape__YAXPAH@Z", csr_32, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp
351 ADJCALLSTACKUP32 4, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp
354 bb.3.catch.i (landing-pad, ehfunclet-entry):
355 successors: %bb.4(0x80000000)
357 %7:gr32 = MOV32rm %stack.3.exp.i, 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from %ir.exp.i)
358 %8:gr32 = MOV32rm killed %7, 1, $noreg, 0, $noreg :: (load (s32) from %ir.18)
359 MOV32mr $noreg, 1, $noreg, @v__3HC, $noreg, killed %8 :: (volatile store release (s32) into @v__3HC)
360 CATCHRET %bb.4, %bb.0
362 bb.4.catch.i (landing-pad):
363 successors: %bb.5(0x80000000)
367 bb.5.func__YAXXZ.exit:
368 %9:gr32 = MOV32rm %stack.0.zx, 1, $noreg, 4, $noreg :: (dereferenceable load (s32) from %ir.22)
369 MOV32mr $noreg, 1, $noreg, 0, $fs, killed %9 :: (store (s32) into `ptr addrspace(257) null`, addrspace 257)
370 %10:gr32 = MOV32r0 implicit-def dead $eflags
376 name: '__ehhandler$main'
378 exposesReturnsTwice: false
380 regBankSelected: false
383 tracksRegLiveness: true
386 - { id: 0, class: gr32, preferred-register: '' }
389 isFrameAddressTaken: false
390 isReturnAddressTaken: false
399 maxCallFrameSize: 4294967295
400 cvBytesOfCalleeSavedRegisters: 0
401 hasOpaqueSPAdjustment: false
403 hasMustTailInVarArgFunc: false
408 - { id: 0, type: default, offset: 0, size: 4, alignment: 4, stack-id: default,
409 isImmutable: false, isAliased: false, callee-saved-register: '',
410 callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
411 debug-info-location: '' }
412 - { id: 1, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
413 isImmutable: false, isAliased: false, callee-saved-register: '',
414 callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
415 debug-info-location: '' }
416 - { id: 2, type: default, offset: 8, size: 4, alignment: 4, stack-id: default,
417 isImmutable: false, isAliased: false, callee-saved-register: '',
418 callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
419 debug-info-location: '' }
420 - { id: 3, type: default, offset: 12, size: 4, alignment: 4, stack-id: default,
421 isImmutable: false, isAliased: false, callee-saved-register: '',
422 callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
423 debug-info-location: '' }
426 debugValueSubstitutions: []
428 machineFunctionInfo: {}
431 %0:gr32 = MOV32ri <mcsymbol L__ehtable$main>
433 TCRETURNdi @__CxxFrameHandler3, 0, csr_32, implicit $esp, implicit $ssp, implicit $eax