llvm/test/CodeGen/ARM/interrupt-attr.ll
Tim Northover 0aba46f4cd ARM MachO: sort out isTargetDarwin/isTargetIOS/... checks.
The ARM backend has been using most of the MachO related subtarget
checks almost interchangeably, and since the only target it's had to
run on has been IOS (which is all three of MachO, Darwin and IOS) it's
worked out OK so far.

But we'd like to support embedded targets under the "*-*-none-macho"
triple, which means everything starts falling apart and inconsistent
behaviours emerge.

This patch should pick a reasonably sensible set of behaviours for the
new triple (and any others that come along, with luck). Some choices
were debatable (notably FP == r7 or r11), but we can revisit those
later when deficiencies become apparent.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198617 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-06 14:28:05 +00:00

134 lines
3.9 KiB
LLVM

; RUN: llc -mtriple=arm-none-none-eabi -mcpu=cortex-a15 -o - %s | FileCheck --check-prefix=CHECK-A %s
; RUN: llc -mtriple=thumb-none-none-eabi -mcpu=cortex-a15 -o - %s | FileCheck --check-prefix=CHECK-A-THUMB %s
; RUN: llc -mtriple=thumb-apple-none-macho -mcpu=cortex-m3 -o - %s | FileCheck --check-prefix=CHECK-M %s
declare arm_aapcscc void @bar()
@bigvar = global [16 x i32] zeroinitializer
define arm_aapcscc void @irq_fn() alignstack(8) "interrupt"="IRQ" {
; Must save all registers except banked sp and lr (we save lr anyway because
; we actually need it at the end to execute the return ourselves).
; Also need special function return setting pc and CPSR simultaneously.
; CHECK-A-LABEL: irq_fn:
; CHECK-A: push {r0, r1, r2, r3, r11, lr}
; CHECK-A: add r11, sp, #16
; CHECK-A: sub sp, sp, #{{[0-9]+}}
; CHECK-A: bic sp, sp, #7
; CHECK-A: bl bar
; CHECK-A: sub sp, r11, #16
; CHECK-A: pop {r0, r1, r2, r3, r11, lr}
; CHECK-A: subs pc, lr, #4
; CHECK-A-THUMB-LABEL: irq_fn:
; CHECK-A-THUMB: push {r0, r1, r2, r3, r4, r7, lr}
; CHECK-A-THUMB: mov r4, sp
; CHECK-A-THUMB: add r7, sp, #20
; CHECK-A-THUMB: bic r4, r4, #7
; CHECK-A-THUMB: bl bar
; CHECK-A-THUMB: sub.w r4, r7, #20
; CHECK-A-THUMB: mov sp, r4
; CHECK-A-THUMB: pop.w {r0, r1, r2, r3, r4, r7, lr}
; CHECK-A-THUMB: subs pc, lr, #4
; Normal AAPCS function (r0-r3 pushed onto stack by hardware, lr set to
; appropriate sentinel so no special return needed).
; CHECK-M-LABEL: irq_fn:
; CHECK-M: push {r4, r7, lr}
; CHECK-M: add r7, sp, #4
; CHECK-M: mov r4, sp
; CHECK-M: bic r4, r4, #7
; CHECK-M: mov sp, r4
; CHECK-M: blx _bar
; CHECK-M: subs r4, r7, #4
; CHECK-M: mov sp, r4
; CHECK-M: pop {r4, r7, pc}
call arm_aapcscc void @bar()
ret void
}
define arm_aapcscc void @fiq_fn() alignstack(8) "interrupt"="FIQ" {
; CHECK-A-LABEL: fiq_fn:
; CHECK-A: push {r0, r1, r2, r3, r4, r5, r6, r7, r11, lr}
; 32 to get past r0, r1, ..., r7
; CHECK-A: add r11, sp, #32
; CHECK-A: sub sp, sp, #{{[0-9]+}}
; CHECK-A: bic sp, sp, #7
; [...]
; 32 must match above
; CHECK-A: sub sp, r11, #32
; CHECK-A: pop {r0, r1, r2, r3, r4, r5, r6, r7, r11, lr}
; CHECK-A: subs pc, lr, #4
; CHECK-A-THUMB-LABEL: fiq_fn:
; CHECK-M-LABEL: fiq_fn:
%val = load volatile [16 x i32]* @bigvar
store volatile [16 x i32] %val, [16 x i32]* @bigvar
ret void
}
define arm_aapcscc void @swi_fn() alignstack(8) "interrupt"="SWI" {
; CHECK-A-LABEL: swi_fn:
; CHECK-A: push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}
; CHECK-A: add r11, sp, #44
; CHECK-A: sub sp, sp, #{{[0-9]+}}
; CHECK-A: bic sp, sp, #7
; [...]
; CHECK-A: sub sp, r11, #44
; CHECK-A: pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}
; CHECK-A: subs pc, lr, #0
%val = load volatile [16 x i32]* @bigvar
store volatile [16 x i32] %val, [16 x i32]* @bigvar
ret void
}
define arm_aapcscc void @undef_fn() alignstack(8) "interrupt"="UNDEF" {
; CHECK-A-LABEL: undef_fn:
; CHECK-A: push {r0, r1, r2, r3, r11, lr}
; CHECK-A: add r11, sp, #16
; CHECK-A: sub sp, sp, #{{[0-9]+}}
; CHECK-A: bic sp, sp, #7
; [...]
; CHECK-A: sub sp, r11, #16
; CHECK-A: pop {r0, r1, r2, r3, r11, lr}
; CHECK-A: subs pc, lr, #0
call void @bar()
ret void
}
define arm_aapcscc void @abort_fn() alignstack(8) "interrupt"="ABORT" {
; CHECK-A-LABEL: abort_fn:
; CHECK-A: push {r0, r1, r2, r3, r11, lr}
; CHECK-A: add r11, sp, #16
; CHECK-A: sub sp, sp, #{{[0-9]+}}
; CHECK-A: bic sp, sp, #7
; [...]
; CHECK-A: sub sp, r11, #16
; CHECK-A: pop {r0, r1, r2, r3, r11, lr}
; CHECK-A: subs pc, lr, #4
call void @bar()
ret void
}
@var = global double 0.0
; We don't save VFP regs, since it would be a massive overhead in the general
; case.
define arm_aapcscc void @floating_fn() alignstack(8) "interrupt"="IRQ" {
; CHECK-A-LABEL: floating_fn:
; CHECK-A-NOT: vpush
; CHECK-A-NOT: vstr
; CHECK-A-NOT: vstm
; CHECK-A: vadd.f64 {{d[0-9]+}}, {{d[0-9]+}}, {{d[0-9]+}}
%lhs = load volatile double* @var
%rhs = load volatile double* @var
%sum = fadd double %lhs, %rhs
store double %sum, double* @var
ret void
}