llvm-project/llvm/test/CodeGen/X86/push-cfi.ll

144 lines
3.9 KiB
LLVM
Raw Normal View History

; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s
declare i32 @__gxx_personality_v0(...)
declare void @good(i32 %a, i32 %b, i32 %c, i32 %d)
declare void @large(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f)
declare void @empty()
; We use an invoke, and expect a .cfi_escape GNU_ARGS_SIZE with size 16
; before the invocation
; CHECK-LABEL: test1:
; CHECK: .cfi_escape 0x2e, 0x10
; CHECK-NEXT: pushl $4
; CHECK-NEXT: pushl $3
; CHECK-NEXT: pushl $2
; CHECK-NEXT: pushl $1
; CHECK-NEXT: call
; CHECK-NEXT: addl $16, %esp
define void @test1() optsize personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @good(i32 1, i32 2, i32 3, i32 4)
to label %continue unwind label %cleanup
continue:
ret void
cleanup:
landingpad { i8*, i32 }
cleanup
ret void
}
; If the function has no handlers, we don't need to generate GNU_ARGS_SIZE,
; even if it has an unwind table.
; CHECK-LABEL: test2:
; CHECK-NOT: .cfi_escape
; CHECK: pushl $4
; CHECK-NEXT: pushl $3
; CHECK-NEXT: pushl $2
; CHECK-NEXT: pushl $1
; CHECK-NEXT: call
; CHECK-NEXT: addl $16, %esp
define void @test2() optsize personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
call void @good(i32 1, i32 2, i32 3, i32 4)
ret void
}
; If we did not end up using any pushes, no need for GNU_ARGS_SIZE anywhere
; CHECK-LABEL: test3:
; CHECK-NOT: .cfi_escape
; CHECK-NOT: pushl
; CHECK: retl
define void @test3() optsize personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @empty()
to label %continue unwind label %cleanup
continue:
ret void
cleanup:
landingpad { i8*, i32 }
cleanup
ret void
}
; Different sized stacks need different GNU_ARGS_SIZEs
; CHECK-LABEL: test4:
; CHECK: .cfi_escape 0x2e, 0x10
; CHECK-NEXT: pushl $4
; CHECK-NEXT: pushl $3
; CHECK-NEXT: pushl $2
; CHECK-NEXT: pushl $1
; CHECK-NEXT: call
; CHECK-NEXT: addl $16, %esp
; CHECK: .cfi_escape 0x2e, 0x20
; CHECK-NEXT: subl $8, %esp
; CHECK-NEXT: pushl $11
; CHECK-NEXT: pushl $10
; CHECK-NEXT: pushl $9
; CHECK-NEXT: pushl $8
; CHECK-NEXT: pushl $7
; CHECK-NEXT: pushl $6
; CHECK-NEXT: calll large
; CHECK-NEXT: addl $32, %esp
define void @test4() optsize personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @good(i32 1, i32 2, i32 3, i32 4)
to label %continue1 unwind label %cleanup
continue1:
invoke void @large(i32 6, i32 7, i32 8, i32 9, i32 10, i32 11)
to label %continue2 unwind label %cleanup
continue2:
ret void
cleanup:
landingpad { i8*, i32 }
cleanup
ret void
}
; If we did use pushes, we need to reset GNU_ARGS_SIZE before a call
; without parameters
; CHECK-LABEL: test5:
; CHECK: .cfi_escape 0x2e, 0x10
; CHECK-NEXT: pushl $4
; CHECK-NEXT: pushl $3
; CHECK-NEXT: pushl $2
; CHECK-NEXT: pushl $1
; CHECK-NEXT: call
; CHECK-NEXT: addl $16, %esp
; CHECK: .cfi_escape 0x2e, 0x00
; CHECK-NEXT: call
define void @test5() optsize personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @good(i32 1, i32 2, i32 3, i32 4)
to label %continue1 unwind label %cleanup
continue1:
invoke void @empty()
to label %continue2 unwind label %cleanup
continue2:
ret void
cleanup:
landingpad { i8*, i32 }
cleanup
ret void
}
; This is actually inefficient - we don't need to repeat the .cfi_escape twice.
; CHECK-LABEL: test6:
; CHECK: .cfi_escape 0x2e, 0x10
; CHECK: call
; CHECK: .cfi_escape 0x2e, 0x10
; CHECK: call
define void @test6() optsize personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @good(i32 1, i32 2, i32 3, i32 4)
to label %continue1 unwind label %cleanup
continue1:
invoke void @good(i32 5, i32 6, i32 7, i32 8)
to label %continue2 unwind label %cleanup
continue2:
ret void
cleanup:
landingpad { i8*, i32 }
cleanup
ret void
}