mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-11 05:35:11 +00:00
dfa550a176
We need to ensure that StackSlotColoring.cpp does not reuse stack spill slots in functions that call "returns_twice" functions such as setjmp(), otherwise this can lead to miscompiled code, because a stack slot would be clobbered when it's still live. This was already handled correctly for functions that call setjmp() (though this wasn't covered by a test), but not for functions that invoke setjmp(). We fix this by changing callsFunctionThatReturnsTwice() to check for invoke instructions. This fixes PR18244. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199180 91177308-0d34-0410-b5e6-96231b3b80d8
142 lines
3.9 KiB
LLVM
142 lines
3.9 KiB
LLVM
; RUN: llc < %s -mtriple=i386-linux | FileCheck %s -check-prefix=X86-32
|
|
; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s -check-prefix=X86-64
|
|
|
|
declare i32 @get_val()
|
|
declare void @use_val(i32)
|
|
declare i1 @setjmp()
|
|
declare void @longjmp()
|
|
declare void @personality()
|
|
|
|
|
|
; Test that llc avoids reusing spill slots in functions that call
|
|
; setjmp(), whether they use "call" or "invoke" for calling setjmp()
|
|
; (PR18244).
|
|
|
|
define void @setjmp_caller() {
|
|
; X86-32-LABEL: setjmp_caller:
|
|
; X86-64-LABEL: setjmp_caller:
|
|
; This code keeps enough variables live across the setjmp() call that
|
|
; they don't all fit in registers and the compiler will allocate a
|
|
; spill slot.
|
|
%a1 = call i32 @get_val()
|
|
%a2 = call i32 @get_val()
|
|
%a3 = call i32 @get_val()
|
|
%a4 = call i32 @get_val()
|
|
%a5 = call i32 @get_val()
|
|
%a6 = call i32 @get_val()
|
|
%a7 = call i32 @get_val()
|
|
%a8 = call i32 @get_val()
|
|
; X86-32: movl %eax, [[SPILL_SLOT:[0-9]+]](%esp)
|
|
; X86-32: calll get_val
|
|
; X86-64: movl %eax, [[SPILL_SLOT:[0-9]+]](%rsp)
|
|
; X86-64: callq get_val
|
|
|
|
%setjmp_result = call i1 @setjmp() returns_twice
|
|
br i1 %setjmp_result, label %second, label %first
|
|
; X86-32: calll setjmp
|
|
; X86-64: callq setjmp
|
|
|
|
; Again, keep enough variables live that they need spill slots. Since
|
|
; this function calls a returns_twice function (setjmp()), the
|
|
; compiler should not reuse the spill slots. longjmp() can return to
|
|
; where the first spill slots were still live.
|
|
first:
|
|
%b1 = call i32 @get_val()
|
|
%b2 = call i32 @get_val()
|
|
%b3 = call i32 @get_val()
|
|
%b4 = call i32 @get_val()
|
|
%b5 = call i32 @get_val()
|
|
%b6 = call i32 @get_val()
|
|
%b7 = call i32 @get_val()
|
|
%b8 = call i32 @get_val()
|
|
call void @use_val(i32 %b1)
|
|
call void @use_val(i32 %b2)
|
|
call void @use_val(i32 %b3)
|
|
call void @use_val(i32 %b4)
|
|
call void @use_val(i32 %b5)
|
|
call void @use_val(i32 %b6)
|
|
call void @use_val(i32 %b7)
|
|
call void @use_val(i32 %b8)
|
|
call void @longjmp()
|
|
unreachable
|
|
; X86-32-NOT: movl {{.*}}, [[SPILL_SLOT]](%esp)
|
|
; X86-64-NOT: movl {{.*}}, [[SPILL_SLOT]](%rsp)
|
|
|
|
second:
|
|
call void @use_val(i32 %a1)
|
|
call void @use_val(i32 %a2)
|
|
call void @use_val(i32 %a3)
|
|
call void @use_val(i32 %a4)
|
|
call void @use_val(i32 %a5)
|
|
call void @use_val(i32 %a6)
|
|
call void @use_val(i32 %a7)
|
|
call void @use_val(i32 %a8)
|
|
ret void
|
|
}
|
|
|
|
|
|
; This is the same as above, but using "invoke" rather than "call" to
|
|
; call setjmp().
|
|
|
|
define void @setjmp_invoker() {
|
|
; X86-32-LABEL: setjmp_invoker:
|
|
; X86-64-LABEL: setjmp_invoker:
|
|
%a1 = call i32 @get_val()
|
|
%a2 = call i32 @get_val()
|
|
%a3 = call i32 @get_val()
|
|
%a4 = call i32 @get_val()
|
|
%a5 = call i32 @get_val()
|
|
%a6 = call i32 @get_val()
|
|
%a7 = call i32 @get_val()
|
|
%a8 = call i32 @get_val()
|
|
; X86-32: movl %eax, [[SPILL_SLOT:[0-9]+]](%esp)
|
|
; X86-32: calll get_val
|
|
; X86-64: movl %eax, [[SPILL_SLOT:[0-9]+]](%rsp)
|
|
; X86-64: callq get_val
|
|
|
|
%setjmp_result = invoke i1 @setjmp() returns_twice
|
|
to label %cont unwind label %lpad
|
|
; X86-32: calll setjmp
|
|
; X86-64: callq setjmp
|
|
|
|
cont:
|
|
br i1 %setjmp_result, label %second, label %first
|
|
|
|
lpad:
|
|
%lp = landingpad { i8*, i32 } personality void ()* @personality cleanup
|
|
unreachable
|
|
|
|
first:
|
|
%b1 = call i32 @get_val()
|
|
%b2 = call i32 @get_val()
|
|
%b3 = call i32 @get_val()
|
|
%b4 = call i32 @get_val()
|
|
%b5 = call i32 @get_val()
|
|
%b6 = call i32 @get_val()
|
|
%b7 = call i32 @get_val()
|
|
%b8 = call i32 @get_val()
|
|
call void @use_val(i32 %b1)
|
|
call void @use_val(i32 %b2)
|
|
call void @use_val(i32 %b3)
|
|
call void @use_val(i32 %b4)
|
|
call void @use_val(i32 %b5)
|
|
call void @use_val(i32 %b6)
|
|
call void @use_val(i32 %b7)
|
|
call void @use_val(i32 %b8)
|
|
call void @longjmp()
|
|
unreachable
|
|
; X86-32-NOT: movl {{.*}}, [[SPILL_SLOT]](%esp)
|
|
; X86-64-NOT: movl {{.*}}, [[SPILL_SLOT]](%rsp)
|
|
|
|
second:
|
|
call void @use_val(i32 %a1)
|
|
call void @use_val(i32 %a2)
|
|
call void @use_val(i32 %a3)
|
|
call void @use_val(i32 %a4)
|
|
call void @use_val(i32 %a5)
|
|
call void @use_val(i32 %a6)
|
|
call void @use_val(i32 %a7)
|
|
call void @use_val(i32 %a8)
|
|
ret void
|
|
}
|