Skip inserting regular CFI instructions if using WinCFI. This is based a fair amount on the corresponding ARM64 implementation, but instead of trying to insert the SEH opcodes one by one where we generate other prolog/epilog instructions, we try to walk over the whole prolog/epilog range and insert them. This is done because in many cases, the exact number of instructions inserted is abstracted away deeper. For some cases, we manually insert specific SEH opcodes directly where instructions are generated, where the automatic mapping of instructions to SEH opcodes doesn't hold up (e.g. for __chkstk stack probes). Skip Thumb2SizeReduction for SEH prologs/epilogs, and force tail calls to wide instructions (just like on MachO), to make sure that the unwind info actually matches the width of the final instructions, without heuristics about what later passes will do. Mark SEH instructions as scheduling boundaries, to make sure that they aren't reordered away from the instruction they describe by PostRAScheduler. Mark the SEH instructions with the NoMerge flag, to avoid doing tail merging of functions that have multiple epilogs that all end with the same sequence of "b <other>; .seh_nop_w, .seh_endepilogue". Differential Revision: https://reviews.llvm.org/D125648
62 lines
1.3 KiB
LLVM
62 lines
1.3 KiB
LLVM
; RUN: llc -mtriple thumbv7-windows -filetype asm -o - %s | FileCheck %s
|
|
|
|
; ModuleID = 'dllimport.c'
|
|
|
|
@var = external dllimport global i32
|
|
@ext = external global i32
|
|
declare dllimport arm_aapcs_vfpcc i32 @external()
|
|
declare arm_aapcs_vfpcc i32 @internal()
|
|
|
|
define arm_aapcs_vfpcc i32 @get_var() {
|
|
%1 = load i32, i32* @var, align 4
|
|
ret i32 %1
|
|
}
|
|
|
|
; CHECK-LABEL: get_var
|
|
; CHECK: movw r0, :lower16:__imp_var
|
|
; CHECK: movt r0, :upper16:__imp_var
|
|
; CHECK: ldr r0, [r0]
|
|
; CHECK: ldr r0, [r0]
|
|
; CHECK: bx lr
|
|
|
|
define arm_aapcs_vfpcc i32 @get_ext() {
|
|
%1 = load i32, i32* @ext, align 4
|
|
ret i32 %1
|
|
}
|
|
|
|
; CHECK-LABEL: get_ext
|
|
; CHECK: movw r0, :lower16:ext
|
|
; CHECK: movt r0, :upper16:ext
|
|
; CHECK: ldr r0, [r0]
|
|
; CHECK: bx lr
|
|
|
|
define arm_aapcs_vfpcc i32* @get_var_pointer() {
|
|
ret i32* @var
|
|
}
|
|
|
|
; CHECK-LABEL: get_var_pointer
|
|
; CHECK: movw r0, :lower16:__imp_var
|
|
; CHECK: movt r0, :upper16:__imp_var
|
|
; CHECK: ldr r0, [r0]
|
|
; CHECK: bx lr
|
|
|
|
define arm_aapcs_vfpcc i32 @call_external() {
|
|
%call = tail call arm_aapcs_vfpcc i32 @external()
|
|
ret i32 %call
|
|
}
|
|
|
|
; CHECK-LABEL: call_external
|
|
; CHECK: movw r0, :lower16:__imp_external
|
|
; CHECK: movt r0, :upper16:__imp_external
|
|
; CHECK: ldr r0, [r0]
|
|
; CHECK: bx r0
|
|
|
|
define arm_aapcs_vfpcc i32 @call_internal() {
|
|
%call = tail call arm_aapcs_vfpcc i32 @internal()
|
|
ret i32 %call
|
|
}
|
|
|
|
; CHECK-LABEL: call_internal
|
|
; CHECK: b.w internal
|
|
|