llvm-6502/test/CodeGen/SPARC/setjmp.ll
Venkatraman Govindaraju 1b41835f02 [Sparc] Correctly handle call to functions with ReturnsTwice attribute.
In sparc, setjmp stores only the registers %fp, %sp, %i7 and %o7. longjmp restores
the stack, and the callee-saved registers (all local/in registers: %i0-%i7, %l0-%l7)
using the stored %fp and register windows. However, this does not guarantee that the longjmp
will restore the registers, as they were when the setjmp was called. This is because these
registers may be clobbered after returning from setjmp, but before calling longjmp.

This patch prevents the registers %i0-%i5, %l0-l7 to live across the setjmp call using the register mask.  



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190033 91177308-0d34-0410-b5e6-96231b3b80d8
2013-09-05 05:32:16 +00:00

71 lines
2.5 KiB
LLVM

;RUN: llc -march=sparc < %s | FileCheck %s
;RUN: llc -march=sparcv9 < %s | FileCheck %s --check-prefix=V9
%0 = type { [32 x i32] }
%struct.jmpbuf_env = type { i32, i32, [1 x %struct.__jmp_buf_tag], i32 }
%struct.__jmp_buf_tag = type { [3 x i32], i32, %0 }
@jenv = common unnamed_addr global %struct.jmpbuf_env* null
@.cst = linker_private unnamed_addr constant [30 x i8] c"in bar with jmp_buf's id: %d\0A\00", align 64
; CHECK-LABEL: foo
; CHECK-DAG: st {{.+}}, [%i0]
; CHECK-DAG: st {{.+}}, [%i0+4]
; CHECK: call _setjmp
; CHECK: ld [%fp+{{.+}}], %[[R:[gilo][0-7]]]
; CHECK: st %o0, [%[[R]]+{{.+}}]
; V9-LABEL: foo
; V9-DAG: st {{.+}}, [%i0]
; V9-DAG: st {{.+}}, [%i0+4]
; V9: call _setjmp
; V9: ldx [%fp+{{.+}}], %[[R:[gilo][0-7]]]
; V9: st %o0, [%[[R]]+{{.+}}]
; Function Attrs: nounwind
define i32 @foo(%struct.jmpbuf_env* byval %inbuf) #0 {
entry:
%0 = getelementptr inbounds %struct.jmpbuf_env* %inbuf, i32 0, i32 0
store i32 0, i32* %0, align 4, !tbaa !2
%1 = getelementptr inbounds %struct.jmpbuf_env* %inbuf, i32 0, i32 1
store i32 1, i32* %1, align 4, !tbaa !2
%2 = getelementptr inbounds %struct.jmpbuf_env* %inbuf, i32 0, i32 2, i32 0
%3 = call i32 @_setjmp(%struct.__jmp_buf_tag* %2) #2
%4 = getelementptr inbounds %struct.jmpbuf_env* %inbuf, i32 0, i32 3
store i32 %3, i32* %4, align 4, !tbaa !2
store %struct.jmpbuf_env* %inbuf, %struct.jmpbuf_env** @jenv, align 4, !tbaa !0
%5 = load i32* %1, align 4, !tbaa !2
%6 = icmp eq i32 %5, 1
%7 = icmp eq i32 %3, 0
%or.cond = and i1 %6, %7
br i1 %or.cond, label %"4.i", label %bar.exit
"4.i": ; preds = %entry
call void @longjmp(%struct.__jmp_buf_tag* %2, i32 0) #1
unreachable
bar.exit: ; preds = %entry
%8 = load i32* %0, align 4, !tbaa !2
%9 = call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([30 x i8]* @.cst, i32 0, i32 0), i32 %8) #0
ret i32 0
}
; Function Attrs: nounwind returns_twice
declare i32 @_setjmp(%struct.__jmp_buf_tag*) #2
; Function Attrs: noreturn nounwind
declare void @longjmp(%struct.__jmp_buf_tag*, i32) #1
; Function Attrs: nounwind
declare i32 @printf(i8* nocapture, ...) #0
attributes #0 = { nounwind }
attributes #1 = { noreturn nounwind }
attributes #2 = { nounwind returns_twice }
!0 = metadata !{metadata !"alias set 6: struct.jmpbuf_env*", metadata !1}
!1 = metadata !{metadata !1}
!2 = metadata !{metadata !"alias set 3: int", metadata !1}