
`f16` is passed and returned in vector registers on both x86 on AArch64, the same calling convention as `f32`, so it is a straightforward type to support. The calling convention support already exists, added as part of a6065f0fa55a ("Arm64EC entry/exit thunks, consolidated. (#79067)"). Thus, add mangling and remove the error in order to make `half` work. MSVC does not yet support `_Float16`, so for now this will remain an LLVM-only extension. Fixes the `f16` portion of https://github.com/llvm/llvm-project/issues/94434
654 lines
29 KiB
LLVM
654 lines
29 KiB
LLVM
; RUN: llc -mtriple=arm64ec-pc-windows-msvc < %s | FileCheck %s
|
|
|
|
declare void @no_op() nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$v$v;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$v$v
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: stp x29, x30, [sp, #32] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add x29, sp, #32
|
|
; CHECK-NEXT: .seh_add_fp 32
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #32] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#no_op$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#no_op$exit_thunk"
|
|
; CHECK: .weak_anti_dep no_op
|
|
; CHECK: .weak_anti_dep "#no_op"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, no_op
|
|
; CHECK-NEXT: add x11, x11, :lo12:no_op
|
|
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$v$v
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$v$v
|
|
; CHECK-NEXT: blr x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
declare i64 @simple_integers(i8, i16, i32, i64) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$i8$i8i8i8i8;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$i8$i8i8i8i8
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: stp x29, x30, [sp, #32] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add x29, sp, #32
|
|
; CHECK-NEXT: .seh_add_fp 32
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: mov x0, x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #32] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#simple_integers$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#simple_integers$exit_thunk"
|
|
; CHECK: .weak_anti_dep simple_integers
|
|
; CHECK: .weak_anti_dep "#simple_integers"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, simple_integers
|
|
; CHECK-NEXT: add x11, x11, :lo12:simple_integers
|
|
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$i8$i8i8i8i8
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$i8$i8i8i8i8
|
|
; CHECK-NEXT: blr x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
; NOTE: Only half, float, and double are supported.
|
|
declare double @simple_floats(half, float, double) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$d$__llvm_h__fd;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$d$__llvm_h__fd
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: stp x29, x30, [sp, #32] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add x29, sp, #32
|
|
; CHECK-NEXT: .seh_add_fp 32
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #32] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#simple_floats$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#simple_floats$exit_thunk"
|
|
; CHECK: .weak_anti_dep simple_floats
|
|
; CHECK: .weak_anti_dep "#simple_floats"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, simple_floats
|
|
; CHECK-NEXT: add x11, x11, :lo12:simple_floats
|
|
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$d$__llvm_h__fd
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$d$__llvm_h__fd
|
|
; CHECK-NEXT: blr x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
declare void @has_varargs(...) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$v$varargs;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$v$varargs
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #64
|
|
; CHECK-NEXT: .seh_stackalloc 64
|
|
; CHECK-NEXT: stp x29, x30, [sp, #48] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 48
|
|
; CHECK-NEXT: add x29, sp, #48
|
|
; CHECK-NEXT: .seh_add_fp 48
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: stp x4, x5, [sp, #32]
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #48] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 48
|
|
; CHECK-NEXT: add sp, sp, #64
|
|
; CHECK-NEXT: .seh_stackalloc 64
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#has_varargs$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#has_varargs$exit_thunk"
|
|
; CHECK: .weak_anti_dep has_varargs
|
|
; CHECK: .weak_anti_dep "#has_varargs"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, has_varargs
|
|
; CHECK-NEXT: add x11, x11, :lo12:has_varargs
|
|
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$v$varargs
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$v$varargs
|
|
; CHECK-NEXT: blr x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
declare void @has_sret(ptr sret([100 x i8])) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$m100$v;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m100$v
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: stp x29, x30, [sp, #32] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add x29, sp, #32
|
|
; CHECK-NEXT: .seh_add_fp 32
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: mov x0, x8
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #32] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#has_sret$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#has_sret$exit_thunk"
|
|
; CHECK: .weak_anti_dep has_sret
|
|
; CHECK: .weak_anti_dep "#has_sret"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x9, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, has_sret
|
|
; CHECK-NEXT: add x11, x11, :lo12:has_sret
|
|
; CHECK-NEXT: ldr x9, [x9, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$m100$v
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$m100$v
|
|
; CHECK-NEXT: blr x9
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
%TSRet = type { i64, i64 }
|
|
declare void @has_aligned_sret(ptr align 32 sret(%TSRet)) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$m16$v;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m16$v
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: stp x29, x30, [sp, #32] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add x29, sp, #32
|
|
; CHECK-NEXT: .seh_add_fp 32
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: mov x0, x8
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #32] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 32
|
|
; CHECK-NEXT: add sp, sp, #48
|
|
; CHECK-NEXT: .seh_stackalloc 48
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#has_aligned_sret$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#has_aligned_sret$exit_thunk"
|
|
; CHECK: .weak_anti_dep has_aligned_sret
|
|
; CHECK: .weak_anti_dep "#has_aligned_sret"
|
|
; CHECK: // %bb.0:
|
|
; CHECK: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK: .seh_save_reg_x x30, 16
|
|
; CHECK: .seh_endprologue
|
|
; CHECK: adrp x9, __os_arm64x_check_icall
|
|
; CHECK: adrp x11, has_aligned_sret
|
|
; CHECK: add x11, x11, :lo12:has_aligned_sret
|
|
; CHECK: ldr x9, [x9, :lo12:__os_arm64x_check_icall]
|
|
; CHECK: adrp x10, $iexit_thunk$cdecl$m16$v
|
|
; CHECK: add x10, x10, :lo12:$iexit_thunk$cdecl$m16$v
|
|
; CHECK: blr x9
|
|
; CHECK: .seh_startepilogue
|
|
; CHECK: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK: .seh_save_reg_x x30, 16
|
|
; CHECK: .seh_endepilogue
|
|
; CHECK: br x11
|
|
; CHECK: .seh_endfunclet
|
|
; CHECK: .seh_endproc
|
|
|
|
declare [2 x i8] @small_array([2 x i8], [2 x half], [2 x float]) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$m2$m2__llvm_H__4F8;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m2$m2__llvm_H__4F8
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #80
|
|
; CHECK-NEXT: .seh_stackalloc 80
|
|
; CHECK-NEXT: stp x29, x30, [sp, #64] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 64
|
|
; CHECK-NEXT: add x29, sp, #64
|
|
; CHECK-NEXT: .seh_add_fp 64
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: sturb w0, [x29, #-2]
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: sturb w1, [x29, #-1]
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: stur h0, [x29, #-6]
|
|
; CHECK-NEXT: ldurh w0, [x29, #-2]
|
|
; CHECK-NEXT: stur h1, [x29, #-4]
|
|
; CHECK-NEXT: stp s2, s3, [x29, #-16]
|
|
; CHECK-NEXT: ldur w1, [x29, #-6]
|
|
; CHECK-NEXT: ldur x2, [x29, #-16]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: mov w0, w8
|
|
; CHECK-NEXT: sturh w8, [x29, #-18]
|
|
; CHECK-NEXT: ubfx w1, w8, #8, #8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #64] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 64
|
|
; CHECK-NEXT: add sp, sp, #80
|
|
; CHECK-NEXT: .seh_stackalloc 80
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#small_array$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#small_array$exit_thunk"
|
|
; CHECK: .weak_anti_dep small_array
|
|
; CHECK: .weak_anti_dep "#small_array"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, small_array
|
|
; CHECK-NEXT: add x11, x11, :lo12:small_array
|
|
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$m2$m2__llvm_H__4F8
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$m2$m2__llvm_H__4F8
|
|
; CHECK-NEXT: blr x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
declare [3 x i64] @large_array([3 x i64], [2 x double], [2 x [2 x i64]]) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$m24$m24D16m32;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m24$m24D16m32
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #144
|
|
; CHECK-NEXT: .seh_stackalloc 144
|
|
; CHECK-NEXT: stp x29, x30, [sp, #128] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 128
|
|
; CHECK-NEXT: add x29, sp, #128
|
|
; CHECK-NEXT: .seh_add_fp 128
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: stp x0, x1, [x29, #-48]
|
|
; CHECK-NEXT: sub x0, x29, #24
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: stur x2, [x29, #-32]
|
|
; CHECK-NEXT: sub x1, x29, #48
|
|
; CHECK-NEXT: stp x3, x4, [sp, #32]
|
|
; CHECK-NEXT: add x2, sp, #64
|
|
; CHECK-NEXT: add x3, sp, #32
|
|
; CHECK-NEXT: stp d0, d1, [sp, #64]
|
|
; CHECK-NEXT: stp x5, x6, [sp, #48]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: ldp x0, x1, [x29, #-24]
|
|
; CHECK-NEXT: ldur x2, [x29, #-8]
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #128] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 128
|
|
; CHECK-NEXT: add sp, sp, #144
|
|
; CHECK-NEXT: .seh_stackalloc 144
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#large_array$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#large_array$exit_thunk"
|
|
; CHECK: .weak_anti_dep large_array
|
|
; CHECK: .weak_anti_dep "#large_array"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, large_array
|
|
; CHECK-NEXT: add x11, x11, :lo12:large_array
|
|
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$m24$m24D16m32
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$m24$m24D16m32
|
|
; CHECK-NEXT: blr x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
%T1 = type { i16 }
|
|
%T2 = type { i32, float }
|
|
%T3 = type { i64, double }
|
|
%T4 = type { i64, double, i8 }
|
|
declare %T2 @simple_struct(%T1, %T2, %T3, %T4) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$m8$i8m8m16m24;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m8$i8m8m16m24
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #112
|
|
; CHECK-NEXT: .seh_stackalloc 112
|
|
; CHECK-NEXT: stp x29, x30, [sp, #96] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 96
|
|
; CHECK-NEXT: add x29, sp, #96
|
|
; CHECK-NEXT: .seh_add_fp 96
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: stur w1, [x29, #-8]
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: stur s0, [x29, #-4]
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: ldur x1, [x29, #-8]
|
|
; CHECK-NEXT: stur x2, [x29, #-24]
|
|
; CHECK-NEXT: sub x2, x29, #24
|
|
; CHECK-NEXT: str x3, [sp, #48]
|
|
; CHECK-NEXT: add x3, sp, #48
|
|
; CHECK-NEXT: stur d1, [x29, #-16]
|
|
; CHECK-NEXT: str d2, [sp, #56]
|
|
; CHECK-NEXT: strb w4, [sp, #64]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: str x8, [sp, #40]
|
|
; CHECK-NEXT: mov x0, x8
|
|
; CHECK-NEXT: ldr s0, [sp, #44]
|
|
; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #96] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 96
|
|
; CHECK-NEXT: add sp, sp, #112
|
|
; CHECK-NEXT: .seh_stackalloc 112
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#simple_struct$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#simple_struct$exit_thunk"
|
|
; CHECK: .weak_anti_dep simple_struct
|
|
; CHECK: .weak_anti_dep "#simple_struct"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, simple_struct
|
|
; CHECK-NEXT: add x11, x11, :lo12:simple_struct
|
|
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$m8$i8m8m16m24
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$m8$i8m8m16m24
|
|
; CHECK-NEXT: blr x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
declare <4 x i8> @small_vector(<4 x i8> %0) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$m$m;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m$m
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #64
|
|
; CHECK-NEXT: .seh_stackalloc 64
|
|
; CHECK-NEXT: stp x29, x30, [sp, #48] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 48
|
|
; CHECK-NEXT: add x29, sp, #48
|
|
; CHECK-NEXT: .seh_add_fp 48
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: fmov w0, s0
|
|
; CHECK-NEXT: stur s0, [x29, #-4]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: stur w8, [x29, #-8]
|
|
; CHECK-NEXT: ldur s0, [x29, #-8]
|
|
; CHECK-NEXT: ushll v0.8h, v0.8b, #0
|
|
; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #48] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 48
|
|
; CHECK-NEXT: add sp, sp, #64
|
|
; CHECK-NEXT: .seh_stackalloc 64
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#small_vector$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#small_vector$exit_thunk"
|
|
; CHECK: .weak_anti_dep small_vector
|
|
; CHECK: .weak_anti_dep "#small_vector"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, small_vector
|
|
; CHECK-NEXT: add x11, x11, :lo12:small_vector
|
|
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$m$m
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$m$m
|
|
; CHECK-NEXT: blr x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
declare <8 x i16> @large_vector(<8 x i16> %0) nounwind;
|
|
; CHECK-LABEL: .def $iexit_thunk$cdecl$m16$m16;
|
|
; CHECK: .section .wowthk$aa,"xr",discard,$iexit_thunk$cdecl$m16$m16
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #80
|
|
; CHECK-NEXT: .seh_stackalloc 80
|
|
; CHECK-NEXT: stp x29, x30, [sp, #64] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_fplr 64
|
|
; CHECK-NEXT: add x29, sp, #64
|
|
; CHECK-NEXT: .seh_add_fp 64
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_dispatch_call_no_redirect
|
|
; CHECK-NEXT: sub x0, x29, #16
|
|
; CHECK-NEXT: add x1, sp, #32
|
|
; CHECK-NEXT: ldr x16, [x8, :lo12:__os_arm64x_dispatch_call_no_redirect]
|
|
; CHECK-NEXT: str q0, [sp, #32]
|
|
; CHECK-NEXT: blr x16
|
|
; CHECK-NEXT: ldur q0, [x29, #-16]
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldp x29, x30, [sp, #64] // 16-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_fplr 64
|
|
; CHECK-NEXT: add sp, sp, #80
|
|
; CHECK-NEXT: .seh_stackalloc 80
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
; CHECK-LABEL: .def "#large_vector$exit_thunk";
|
|
; CHECK: .section .wowthk$aa,"xr",discard,"#large_vector$exit_thunk"
|
|
; CHECK: .weak_anti_dep large_vector
|
|
; CHECK: .weak_anti_dep "#large_vector"
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endprologue
|
|
; CHECK-NEXT: adrp x8, __os_arm64x_check_icall
|
|
; CHECK-NEXT: adrp x11, large_vector
|
|
; CHECK-NEXT: add x11, x11, :lo12:large_vector
|
|
; CHECK-NEXT: ldr x8, [x8, :lo12:__os_arm64x_check_icall]
|
|
; CHECK-NEXT: adrp x10, $iexit_thunk$cdecl$m16$m16
|
|
; CHECK-NEXT: add x10, x10, :lo12:$iexit_thunk$cdecl$m16$m16
|
|
; CHECK-NEXT: blr x8
|
|
; CHECK-NEXT: .seh_startepilogue
|
|
; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
|
|
; CHECK-NEXT: .seh_save_reg_x x30, 16
|
|
; CHECK-NEXT: .seh_endepilogue
|
|
; CHECK-NEXT: br x11
|
|
; CHECK-NEXT: .seh_endfunclet
|
|
; CHECK-NEXT: .seh_endproc
|
|
|
|
; CHECK-LABEL: .section .hybmp$x,"yi"
|
|
; CHECK-NEXT: .symidx "#func_caller"
|
|
; CHECK-NEXT: .symidx $ientry_thunk$cdecl$v$v
|
|
; CHECK-NEXT: .word 1
|
|
; CHECK-NEXT: .symidx no_op
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$v$v
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#no_op$exit_thunk"
|
|
; CHECK-NEXT: .symidx no_op
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx simple_integers
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$i8$i8i8i8i8
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#simple_integers$exit_thunk"
|
|
; CHECK-NEXT: .symidx simple_integers
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx simple_floats
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$d$__llvm_h__fd
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#simple_floats$exit_thunk"
|
|
; CHECK-NEXT: .symidx simple_floats
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx has_varargs
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$v$varargs
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#has_varargs$exit_thunk"
|
|
; CHECK-NEXT: .symidx has_varargs
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx has_sret
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$m100$v
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#has_sret$exit_thunk"
|
|
; CHECK-NEXT: .symidx has_sret
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx has_aligned_sret
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$m16$v
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#has_aligned_sret$exit_thunk"
|
|
; CHECK-NEXT: .symidx has_aligned_sret
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx small_array
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$m2$m2__llvm_H__4F8
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#small_array$exit_thunk"
|
|
; CHECK-NEXT: .symidx small_array
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx large_array
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$m24$m24D16m32
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#large_array$exit_thunk"
|
|
; CHECK-NEXT: .symidx large_array
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx simple_struct
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$m8$i8m8m16m24
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#simple_struct$exit_thunk"
|
|
; CHECK-NEXT: .symidx simple_struct
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx small_vector
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$m$m
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#small_vector$exit_thunk"
|
|
; CHECK-NEXT: .symidx small_vector
|
|
; CHECK-NEXT: .word 0
|
|
; CHECK-NEXT: .symidx large_vector
|
|
; CHECK-NEXT: .symidx $iexit_thunk$cdecl$m16$m16
|
|
; CHECK-NEXT: .word 4
|
|
; CHECK-NEXT: .symidx "#large_vector$exit_thunk"
|
|
; CHECK-NEXT: .symidx large_vector
|
|
; CHECK-NEXT: .word 0
|
|
|
|
define void @func_caller() nounwind {
|
|
call void @no_op()
|
|
call i64 @simple_integers(i8 0, i16 0, i32 0, i64 0)
|
|
call double @simple_floats(half 0.0, float 0.0, double 0.0)
|
|
call void (...) @has_varargs()
|
|
%c = alloca i8
|
|
call void @has_sret(ptr sret([100 x i8]) %c)
|
|
%aligned = alloca %TSRet, align 32
|
|
store %TSRet { i64 0, i64 0 }, ptr %aligned, align 32
|
|
call void @has_aligned_sret(ptr align 32 sret(%TSRet) %aligned)
|
|
call [2 x i8] @small_array([2 x i8] [i8 0, i8 0], [2 x half] [half 0.0, half 0.0], [2 x float] [float 0.0, float 0.0])
|
|
call [3 x i64] @large_array([3 x i64] [i64 0, i64 0, i64 0], [2 x double] [double 0.0, double 0.0], [2 x [2 x i64]] [[2 x i64] [i64 0, i64 0], [2 x i64] [i64 0, i64 0]])
|
|
call %T2 @simple_struct(%T1 { i16 0 }, %T2 { i32 0, float 0.0 }, %T3 { i64 0, double 0.0 }, %T4 { i64 0, double 0.0, i8 0 })
|
|
call <4 x i8> @small_vector(<4 x i8> <i8 0, i8 0, i8 0, i8 0>)
|
|
call <8 x i16> @large_vector(<8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>)
|
|
ret void
|
|
}
|