437 lines · plain
1# RUN: llc -mtriple="i386-pc-windows-msvc" -run-pass=stack-coloring %s -o - | FileCheck %s2# RUN: llc -mtriple="i386-pc-windows-msvc" -passes=stack-coloring %s -o - | FileCheck %s3 4# There is a problem with the exception handler, we found in windows, when set5# LifetimeStartOnFirstUse=true for stack-coloring in default. Take the following6# case for example:7#8#// Compile with "clang-cl -m32 -O2 -EHs test.cpp"9#__attribute__((noinline,nothrow,weak)) void escape(int *p) { }10#struct object {11# int i;12# object() {13# i = 1;14# }15# ~object() {16# // if "object" and "exp" are assigned to the same slot,17# // this assign will corrupt "exp".18# i = 9999;19# escape(&i);20# }21#};22#inline void throwit() { throw 999; }23#24#volatile int v;25#inline void func() {26# try {27# object o;28# throwit();29# }30# // "exp" is written by the OS when the "throw" occurs.31# // Then the destructor is called, and the store-assign32# // clobbers the value of "exp".33# // The dereference of "exp" (with value 9999) causes a crash.34# // All these done in libruntime, so it is hard to check in IR.35# catch (int &exp) {36# v = exp;37# }38#}39#40#int main() {41# func();42# return 0;43#}44 45## Make sure that o.i not merge with exp.i46# CHECK: stack:47# CHECK: id: 2, name: o.i, type: default, offset: 0, size: 4, alignment: 4,48# CHECK: id: 3, name: exp.i, type: default, offset: 0, size: 4, alignment: 4,49 50## Make sure that %stack.3.exp.i not replaced with %stack.2.o.i51# CHECK: bb.3.catch.i (landing-pad, ehfunclet-entry):52# CHECK: %7:gr32 = MOV32rm %stack.3.exp.i, 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from %ir.exp.i)53 54--- |55 ; ModuleID = 'test-pre-stc.mir'56 source_filename = "test.cpp"57 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 59 %rtti.TypeDescriptor2 = type { ptr, ptr, [3 x i8] }60 %eh.CatchableType = type { i32, ptr, i32, i32, i32, i32, ptr }61 %eh.CatchableTypeArray.1 = type { i32, [1 x ptr] }62 %eh.ThrowInfo = type { i32, ptr, ptr, ptr }63 %CXXExceptionRegistration = type { ptr, %EHRegistrationNode, i32 }64 %EHRegistrationNode = type { ptr, ptr }65 %struct.object = type { i32 }66 67 $"_R0H@8" = comdat any68 69 $"_CT_R0H@84" = comdat any70 71 $_CTA1H = comdat any72 73 $_TI1H = comdat any74 75 @v__3HC = dso_local global i32 0, align 476 @"_7type_info__6B@" = external constant ptr77 @"_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { ptr @"_7type_info__6B@", ptr null, [3 x i8] c".H\00" }, comdat78 @"_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", comdat79 @_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x ptr] [ptr @"_CT_R0H@84"] }, section ".xdata", comdat80 @_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, ptr null, ptr null, ptr @_CTA1H }, section ".xdata", comdat81 82 ; Function Attrs: noinline nounwind sspstrong83 define weak dso_local void @"escape__YAXPAH@Z"(ptr %p) local_unnamed_addr #0 {84 entry:85 ret void86 }87 88 ; Function Attrs: norecurse sspstrong89 define dso_local i32 @main() local_unnamed_addr #1 personality i32 (...)* @__CxxFrameHandler3 {90 entry:91 %0 = alloca %CXXExceptionRegistration, align 492 %1 = bitcast ptr %0 to ptr93 call void @llvm.x86.seh.ehregnode(ptr %1)94 %2 = call ptr @llvm.stacksave()95 %3 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 096 store ptr %2, ptr %3, align 497 %4 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 298 store i32 -1, ptr %4, align 499 %5 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 1100 %6 = getelementptr inbounds %EHRegistrationNode, ptr %5, i32 0, i32 1101 store ptr @"__ehhandler$main", ptr %6, align 4102 %7 = load ptr, ptr addrspace(257) null, align 4103 %8 = getelementptr inbounds %EHRegistrationNode, ptr %5, i32 0, i32 0104 store ptr %7, ptr %8, align 4105 store ptr %5, ptr addrspace(257) null, align 4106 %tmp.i.i = alloca i32, align 4107 %o.i = alloca %struct.object, align 4108 %zx = alloca ptr, align 4109 %exp.i = alloca ptr, align 4110 %9 = bitcast ptr %exp.i to ptr111 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %9)112 %10 = bitcast ptr %o.i to ptr113 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %10) #7114 %i.i.i1 = bitcast ptr %o.i to ptr115 store i32 1, ptr %i.i.i1, align 4116 %11 = bitcast ptr %tmp.i.i to ptr117 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %11)118 store i32 999, ptr %tmp.i.i, align 4119 %12 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 2120 store i32 1, ptr %12, align 4121 invoke void @_CxxThrowException(ptr nonnull %11, ptr nonnull @_TI1H) #8122 to label %.noexc.i unwind label %ehcleanup.i123 124 .noexc.i: ; preds = %entry125 unreachable126 127 ehcleanup.i: ; preds = %entry128 %13 = cleanuppad within none []129 %14 = bitcast ptr %o.i to ptr130 %15 = bitcast ptr %o.i to ptr131 store i32 9999, ptr %14, align 4132 call void @"escape__YAXPAH@Z"(ptr nonnull %14) #7 [ "funclet"(token %13) ]133 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %15) #7134 cleanupret from %13 unwind label %catch.dispatch.i135 136 catch.dispatch.i: ; preds = %ehcleanup.i137 %16 = catchswitch within none [label %catch.i] unwind to caller138 139 catch.i: ; preds = %catch.dispatch.i140 %17 = catchpad within %16 [ptr @"_R0H@8", i32 8, ptr %exp.i]141 %18 = load ptr, ptr %exp.i, align 4142 %19 = load i32, ptr %18, align 4143 store atomic volatile i32 %19, ptr @v__3HC release, align 4144 catchret from %17 to label %func__YAXXZ.exit145 146 func__YAXXZ.exit: ; preds = %catch.i147 %20 = bitcast ptr %exp.i to ptr148 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %20)149 %21 = getelementptr inbounds %CXXExceptionRegistration, ptr %0, i32 0, i32 1150 %22 = getelementptr inbounds %EHRegistrationNode, ptr %21, i32 0, i32 0151 %23 = load ptr, ptr %22, align 4152 store ptr %23, ptr addrspace(257) null, align 4153 ret i32 0154 }155 156 ; Function Attrs: argmemonly nofree nosync nounwind willreturn157 declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #2158 159 ; Function Attrs: nofree160 declare dso_local i32 @__CxxFrameHandler3(...) #3161 162 ; Function Attrs: argmemonly nofree nosync nounwind willreturn163 declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #2164 165 ; Function Attrs: nofree166 declare dso_local x86_stdcallcc void @_CxxThrowException(ptr, ptr) local_unnamed_addr #3167 168 declare i32 @_setjmp3(ptr, i32, ...)169 170 ; Function Attrs: nofree nosync nounwind willreturn171 declare ptr @llvm.stacksave() #4172 173 define internal i32 @"__ehhandler$main"(ptr %0, ptr %1, ptr %2, ptr %3) #5 {174 entry:175 %4 = call ptr @llvm.x86.seh.lsda(ptr @main)176 %5 = tail call i32 @__CxxFrameHandler3(ptr inreg %4, ptr %0, ptr %1, ptr %2, ptr %3)177 ret i32 %5178 }179 180 ; Function Attrs: nounwind readnone181 declare ptr @llvm.x86.seh.lsda(ptr) #6182 183 declare x86_stdcallcc void @__CxxLongjmpUnwind(ptr)184 185 ; Function Attrs: nounwind186 declare void @llvm.x86.seh.ehregnode(ptr) #7187 188 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" "use-soft-float"="false" }189 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" "use-soft-float"="false" }190 attributes #2 = { argmemonly nofree nosync nounwind willreturn }191 attributes #3 = { nofree }192 attributes #4 = { nofree nosync nounwind willreturn }193 attributes #5 = { "safeseh" }194 attributes #6 = { nounwind readnone }195 attributes #7 = { nounwind }196 attributes #8 = { noreturn }197 198 !llvm.linker.options = !{!0, !1, !2}199 !llvm.module.flags = !{!3, !4}200 !llvm.ident = !{!5}201 202 !0 = !{!"/DEFAULTLIB:libcmt.lib"}203 !1 = !{!"/DEFAULTLIB:libmmt.lib"}204 !2 = !{!"/DEFAULTLIB:oldnames.lib"}205 !3 = !{i32 1, !"NumRegisterParameters", i32 0}206 !4 = !{i32 1, !"wchar_size", i32 2}207 !5 = !{!"Intel(R) oneAPI DPC++ Compiler Pro 2021.1 (YYYY.x.0.MMDD)"}208 209...210---211name: 'escape__YAXPAH@Z'212alignment: 16213exposesReturnsTwice: false214legalized: false215regBankSelected: false216selected: false217failedISel: false218tracksRegLiveness: true219hasWinCFI: false220registers: []221liveins: []222frameInfo:223 isFrameAddressTaken: false224 isReturnAddressTaken: false225 hasStackMap: false226 hasPatchPoint: false227 stackSize: 0228 offsetAdjustment: 0229 maxAlignment: 4230 adjustsStack: false231 hasCalls: false232 stackProtector: ''233 maxCallFrameSize: 4294967295234 cvBytesOfCalleeSavedRegisters: 0235 hasOpaqueSPAdjustment: false236 hasVAStart: false237 hasMustTailInVarArgFunc: false238 localFrameSize: 0239 savePoint: []240 restorePoint: []241fixedStack:242 - { id: 0, type: default, offset: 0, size: 4, alignment: 4, stack-id: default,243 isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,244 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }245stack: []246callSites: []247debugValueSubstitutions: []248constants: []249machineFunctionInfo: {}250body: |251 bb.0.entry:252 RET 0253 254...255---256name: main257alignment: 16258exposesReturnsTwice: false259legalized: false260regBankSelected: false261selected: false262failedISel: false263tracksRegLiveness: true264hasWinCFI: false265registers:266 - { id: 0, class: gr32, preferred-register: '' }267 - { id: 1, class: gr32, preferred-register: '' }268 - { id: 2, class: gr32, preferred-register: '' }269 - { id: 3, class: gr32, preferred-register: '' }270 - { id: 4, class: gr32, preferred-register: '' }271 - { id: 5, class: gr32, preferred-register: '' }272 - { id: 6, class: gr32, preferred-register: '' }273 - { id: 7, class: gr32, preferred-register: '' }274 - { id: 8, class: gr32, preferred-register: '' }275 - { id: 9, class: gr32, preferred-register: '' }276 - { id: 10, class: gr32, preferred-register: '' }277liveins: []278frameInfo:279 isFrameAddressTaken: false280 isReturnAddressTaken: false281 hasStackMap: false282 hasPatchPoint: false283 stackSize: 0284 offsetAdjustment: 0285 maxAlignment: 4286 adjustsStack: false287 hasCalls: true288 stackProtector: ''289 maxCallFrameSize: 4294967295290 cvBytesOfCalleeSavedRegisters: 0291 hasOpaqueSPAdjustment: true292 hasVAStart: false293 hasMustTailInVarArgFunc: false294 localFrameSize: 0295 savePoint: []296 restorePoint: []297fixedStack: []298stack:299 - { id: 0, name: zx, type: default, offset: 0, size: 16, alignment: 4,300 stack-id: default, callee-saved-register: '', callee-saved-restored: true,301 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }302 - { id: 1, name: tmp.i.i, type: default, offset: 0, size: 4, alignment: 4,303 stack-id: default, callee-saved-register: '', callee-saved-restored: true,304 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }305 - { id: 2, name: o.i, type: default, offset: 0, size: 4, alignment: 4,306 stack-id: default, callee-saved-register: '', callee-saved-restored: true,307 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }308 - { id: 3, name: exp.i, type: default, offset: 0, size: 4, alignment: 4,309 stack-id: default, callee-saved-register: '', callee-saved-restored: true,310 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }311callSites: []312debugValueSubstitutions: []313constants: []314machineFunctionInfo: {}315body: |316 bb.0.entry:317 successors: %bb.1(0x7ffff800), %bb.2(0x00000800)318 319 %0:gr32 = COPY $esp320 MOV32mr %stack.0.zx, 1, $noreg, 0, $noreg, %0 :: (store (s32) into %ir.3)321 MOV32mi %stack.0.zx, 1, $noreg, 12, $noreg, -1 :: (store (s32) into %ir.4)322 %1:gr32 = nuw LEA32r %stack.0.zx, 1, $noreg, 4, $noreg323 MOV32mi %stack.0.zx, 1, $noreg, 8, $noreg, @"__ehhandler$main" :: (store (s32) into %ir.6)324 %2:gr32 = MOV32rm $noreg, 1, $noreg, 0, $fs :: (load (s32) from `ptr addrspace(257) null`, addrspace 257)325 MOV32mr %stack.0.zx, 1, $noreg, 4, $noreg, killed %2 :: (store (s32) into %ir.8)326 MOV32mr $noreg, 1, $noreg, 0, $fs, killed %1 :: (store (s32) into `ptr addrspace(257) null`, addrspace 257)327 MOV32mi %stack.2.o.i, 1, $noreg, 0, $noreg, 1 :: (store (s32) into %ir.i.i.i1)328 MOV32mi %stack.1.tmp.i.i, 1, $noreg, 0, $noreg, 999 :: (store (s32) into %ir.tmp.i.i)329 MOV32mi %stack.0.zx, 1, $noreg, 12, $noreg, 1 :: (store (s32) into %ir.12)330 ADJCALLSTACKDOWN32 8, 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp331 %3:gr32 = COPY $esp332 %4:gr32 = LEA32r %stack.1.tmp.i.i, 1, $noreg, 0, $noreg333 MOV32mr %3, 1, $noreg, 0, $noreg, killed %4 :: (store (s32) into stack)334 MOV32mi %3, 1, $noreg, 4, $noreg, @_TI1H :: (store (s32) into stack + 4)335 CALLpcrel32 @_CxxThrowException, csr_noregs, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp336 ADJCALLSTACKUP32 8, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp337 JMP_1 %bb.1338 339 bb.1..noexc.i:340 successors:341 342 343 bb.2.ehcleanup.i (landing-pad, ehfunclet-entry):344 successors: %bb.3(0x80000000)345 346 MOV32mi %stack.2.o.i, 1, $noreg, 0, $noreg, 9999 :: (store (s32) into %ir.14)347 ADJCALLSTACKDOWN32 4, 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp348 %5:gr32 = COPY $esp349 %6:gr32 = LEA32r %stack.2.o.i, 1, $noreg, 0, $noreg350 MOV32mr %5, 1, $noreg, 0, $noreg, killed %6 :: (store (s32) into stack)351 CALLpcrel32 @"escape__YAXPAH@Z", csr_32, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp352 ADJCALLSTACKUP32 4, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp353 CLEANUPRET354 355 bb.3.catch.i (landing-pad, ehfunclet-entry):356 successors: %bb.4(0x80000000)357 358 %7:gr32 = MOV32rm %stack.3.exp.i, 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from %ir.exp.i)359 %8:gr32 = MOV32rm killed %7, 1, $noreg, 0, $noreg :: (load (s32) from %ir.18)360 MOV32mr $noreg, 1, $noreg, @v__3HC, $noreg, killed %8 :: (volatile store release (s32) into @v__3HC)361 CATCHRET %bb.4, %bb.0362 363 bb.4.catch.i (landing-pad):364 successors: %bb.5(0x80000000)365 366 JMP_4 %bb.5367 368 bb.5.func__YAXXZ.exit:369 %9:gr32 = MOV32rm %stack.0.zx, 1, $noreg, 4, $noreg :: (dereferenceable load (s32) from %ir.22)370 MOV32mr $noreg, 1, $noreg, 0, $fs, killed %9 :: (store (s32) into `ptr addrspace(257) null`, addrspace 257)371 %10:gr32 = MOV32r0 implicit-def dead $eflags372 $eax = COPY %10373 RET 0, $eax374 375...376---377name: '__ehhandler$main'378alignment: 16379exposesReturnsTwice: false380legalized: false381regBankSelected: false382selected: false383failedISel: false384tracksRegLiveness: true385hasWinCFI: false386registers:387 - { id: 0, class: gr32, preferred-register: '' }388liveins: []389frameInfo:390 isFrameAddressTaken: false391 isReturnAddressTaken: false392 hasStackMap: false393 hasPatchPoint: false394 stackSize: 0395 offsetAdjustment: 0396 maxAlignment: 4397 adjustsStack: false398 hasCalls: false399 stackProtector: ''400 maxCallFrameSize: 4294967295401 cvBytesOfCalleeSavedRegisters: 0402 hasOpaqueSPAdjustment: false403 hasVAStart: false404 hasMustTailInVarArgFunc: false405 localFrameSize: 0406 savePoint: []407 restorePoint: []408fixedStack:409 - { id: 0, type: default, offset: 0, size: 4, alignment: 4, stack-id: default,410 isImmutable: false, isAliased: false, callee-saved-register: '',411 callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',412 debug-info-location: '' }413 - { id: 1, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,414 isImmutable: false, isAliased: false, callee-saved-register: '',415 callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',416 debug-info-location: '' }417 - { id: 2, type: default, offset: 8, size: 4, alignment: 4, stack-id: default,418 isImmutable: false, isAliased: false, callee-saved-register: '',419 callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',420 debug-info-location: '' }421 - { id: 3, type: default, offset: 12, size: 4, alignment: 4, stack-id: default,422 isImmutable: false, isAliased: false, callee-saved-register: '',423 callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',424 debug-info-location: '' }425stack: []426callSites: []427debugValueSubstitutions: []428constants: []429machineFunctionInfo: {}430body: |431 bb.0.entry:432 %0:gr32 = MOV32ri <mcsymbol L__ehtable$main>433 $eax = COPY %0434 TCRETURNdi @__CxxFrameHandler3, 0, csr_32, implicit $esp, implicit $ssp, implicit $eax435 436...437