Skip to content

Commit 5032050

Browse files
Benson Chujakevossen5evodius96
committed
[ARM][Thumb] Save FPSCR + FPEXC for save-vfp attribute
FPSCR and FPEXC will be stored in FPStatusRegs, after GPRCS2 has been saved. - GPRCS1 - GPRCS2 - FPStatusRegs (new) - DPRCS - GPRCS3 - DPRCS2 FPSCR is present on all targets with a VFP, but the FPEXC register is not present on Cortex-M devices, so different amounts of bytes are being pushed onto the stack depending on our target, which would affect alignment for subsequent saves. DPRCS1 will sum up all previous bytes that were saved, and will emit extra instructions to ensure that its alignment is correct. My assumption is that if DPRCS1 is able to correct its alignment to be correct, then all subsequent saves will also have correct alignment. Avoid annotating the saving of FPSCR and FPEXC for functions marked with the interrupt_save_fp attribute, even though this is done as part of frame setup. Since these are status registers, there really is no viable way of annotating this. Since these aren't GPRs or DPRs, they can't be used with .save or .vsave directives. Instead, just record that the intermediate registers r4 and r5 are saved to the stack again. Co-authored-by: Jake Vossen <jake@vossen.dev> Co-authored-by: Alan Phipps <a-phipps@ti.com>
1 parent d7460da commit 5032050

22 files changed

+999
-26
lines changed

Diff for: clang/include/clang/Basic/Attr.td

+16
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,22 @@ def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
999999
let Documentation = [ARMInterruptDocs];
10001000
}
10011001

1002+
def ARMInterruptSaveFP : InheritableAttr, TargetSpecificAttr<TargetARM> {
1003+
let Spellings = [GNU<"interrupt_save_fp">];
1004+
let Args = [EnumArgument<"Interrupt", "InterruptType", /*is_string=*/true,
1005+
["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""],
1006+
["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", "Generic"],
1007+
1>];
1008+
let HasCustomParsing = 0;
1009+
let Documentation = [ARMInterruptSaveFPDocs];
1010+
}
1011+
1012+
def ARMSaveFP : InheritableAttr, TargetSpecificAttr<TargetARM> {
1013+
let Spellings = [];
1014+
let Subjects = SubjectList<[Function]>;
1015+
let Documentation = [InternalOnly];
1016+
}
1017+
10021018
def AVRInterrupt : InheritableAttr, TargetSpecificAttr<TargetAVR> {
10031019
let Spellings = [GCC<"interrupt">];
10041020
let Subjects = SubjectList<[Function]>;

Diff for: clang/include/clang/Basic/AttrDocs.td

+13
Original file line numberDiff line numberDiff line change
@@ -2686,6 +2686,19 @@ The semantics are as follows:
26862686
}];
26872687
}
26882688

2689+
def ARMInterruptSaveFPDocs : Documentation {
2690+
let Category = DocCatFunction;
2691+
let Heading = "interrupt_save_fp (ARM)";
2692+
let Content = [{
2693+
Clang supports the GNU style ``__attribute__((interrupt_save_fp("TYPE")))``
2694+
on ARM targets. This attribute behaves the same way as the ARM interrupt
2695+
attribute, except the general purpose floating point registers are also saved,
2696+
along with FPEXC and FPSCR. Note, even on M-class CPUs, where the floating
2697+
point context can be automatically saved depending on the FPCCR, the general
2698+
purpose floating point registers will be saved.
2699+
}];
2700+
}
2701+
26892702
def BPFPreserveAccessIndexDocs : Documentation {
26902703
let Category = DocCatFunction;
26912704
let Content = [{

Diff for: clang/include/clang/Basic/DiagnosticSemaKinds.td

+7-1
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,14 @@ def warn_anyx86_excessive_regsave : Warning<
402402
InGroup<DiagGroup<"excessive-regsave">>;
403403
def warn_arm_interrupt_vfp_clobber : Warning<
404404
"interrupt service routine with vfp enabled may clobber the "
405-
"interruptee's vfp state">,
405+
"interruptee's vfp state; "
406+
"consider using the `interrupt_save_fp` attribute to prevent this behavior">,
406407
InGroup<DiagGroup<"arm-interrupt-vfp-clobber">>;
408+
def warn_arm_interrupt_save_fp_without_vfp_unit : Warning<
409+
"`interrupt_save_fp` only applies to targets that have a VFP unit enabled "
410+
"for this compilation; this will be treated as a regular `interrupt` "
411+
"attribute">,
412+
InGroup<DiagGroup<"arm-interrupt-save-fp-no-vfp-unit">>;
407413
def err_arm_interrupt_called : Error<
408414
"interrupt service routine cannot be called directly">;
409415
def warn_interrupt_signal_attribute_invalid : Warning<

Diff for: clang/include/clang/Sema/SemaARM.h

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class SemaARM : public SemaBase {
7979
void handleNewAttr(Decl *D, const ParsedAttr &AL);
8080
void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL);
8181
void handleInterruptAttr(Decl *D, const ParsedAttr &AL);
82+
void handleInterruptSaveFPAttr(Decl *D, const ParsedAttr &AL);
8283

8384
void CheckSMEFunctionDefAttributes(const FunctionDecl *FD);
8485
};

Diff for: clang/lib/CodeGen/Targets/ARM.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,12 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
190190

191191
Fn->addFnAttr("interrupt", Kind);
192192

193+
// Note: the ARMSaveFPAttr can only exist if we also have an interrupt
194+
// attribute
195+
const ARMSaveFPAttr *SaveFPAttr = FD->getAttr<ARMSaveFPAttr>();
196+
if (SaveFPAttr)
197+
Fn->addFnAttr("save-fp");
198+
193199
ARMABIKind ABI = getABIInfo<ARMABIInfo>().getABIKind();
194200
if (ABI == ARMABIKind::APCS)
195201
return;

Diff for: clang/lib/Sema/SemaARM.cpp

+27-3
Original file line numberDiff line numberDiff line change
@@ -1316,14 +1316,38 @@ void SemaARM::handleInterruptAttr(Decl *D, const ParsedAttr &AL) {
13161316
return;
13171317
}
13181318

1319-
const TargetInfo &TI = getASTContext().getTargetInfo();
1320-
if (TI.hasFeature("vfp"))
1321-
Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
1319+
if (!D->hasAttr<ARMSaveFPAttr>()) {
1320+
const TargetInfo &TI = getASTContext().getTargetInfo();
1321+
if (TI.hasFeature("vfp"))
1322+
Diag(D->getLocation(), diag::warn_arm_interrupt_vfp_clobber);
1323+
}
13221324

13231325
D->addAttr(::new (getASTContext())
13241326
ARMInterruptAttr(getASTContext(), AL, Kind));
13251327
}
13261328

1329+
void SemaARM::handleInterruptSaveFPAttr(Decl *D, const ParsedAttr &AL) {
1330+
// Go ahead and add ARMSaveFPAttr because handleInterruptAttr() checks for
1331+
// it when deciding to issue a diagnostic about clobbering floating point
1332+
// registers, which ARMSaveFPAttr prevents.
1333+
D->addAttr(::new (SemaRef.Context) ARMSaveFPAttr(SemaRef.Context, AL));
1334+
SemaRef.ARM().handleInterruptAttr(D, AL);
1335+
1336+
// If ARM().handleInterruptAttr() failed, remove ARMSaveFPAttr.
1337+
if (!D->hasAttr<ARMInterruptAttr>()) {
1338+
D->dropAttr<ARMSaveFPAttr>();
1339+
return;
1340+
}
1341+
1342+
// If VFP not enabled, remove ARMSaveFPAttr but leave ARMInterruptAttr.
1343+
bool VFP = SemaRef.Context.getTargetInfo().hasFeature("vfp");
1344+
1345+
if (!VFP) {
1346+
SemaRef.Diag(D->getLocation(), diag::warn_arm_interrupt_save_fp_without_vfp_unit);
1347+
D->dropAttr<ARMSaveFPAttr>();
1348+
}
1349+
}
1350+
13271351
// Check if the function definition uses any AArch64 SME features without
13281352
// having the '+sme' feature enabled and warn user if sme locally streaming
13291353
// function returns or uses arguments with VL-based types.

Diff for: clang/lib/Sema/SemaDeclAttr.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -6950,6 +6950,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
69506950
case ParsedAttr::AT_Interrupt:
69516951
handleInterruptAttr(S, D, AL);
69526952
break;
6953+
case ParsedAttr::AT_ARMInterruptSaveFP:
6954+
S.ARM().handleInterruptSaveFPAttr(D, AL);
6955+
break;
69536956
case ParsedAttr::AT_X86ForceAlignArgPointer:
69546957
S.X86().handleForceAlignArgPointerAttr(D, AL);
69556958
break;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// REQUIRES: arm-registered-target
2+
// RUN: %clang -target arm-none-none-eabihf -mcpu=cortex-r5 -mfpu=vfpv3-d16 -marm -S -o - %s \
3+
// RUN: | FileCheck %s --check-prefix=CHECK-R
4+
// RUN: %clang -target arm-none-none-eabihf -mcpu=cortex-r5 -mfpu=vfpv3-d16 -mthumb -S -o - %s \
5+
// RUN: | FileCheck %s --check-prefix=CHECK-R
6+
// RUN: %clang -target arm-none-none-eabihf -mcpu=cortex-r4 -mfpu=vfpv3-d16 -marm -S -o - %s \
7+
// RUN: | FileCheck %s --check-prefix=CHECK-R
8+
// RUN: %clang -target arm-none-none-eabihf -mcpu=cortex-r4 -mfpu=vfpv3-d16 -mthumb -S -o - %s \
9+
// RUN: | FileCheck %s --check-prefix=CHECK-R
10+
// RUN: %clang -target arm-none-none-eabihf -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -S -o - %s \
11+
// RUN: | FileCheck %s --check-prefix=CHECK-M
12+
// RUN: %clang -target arm-none-none-eabihf -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -S -o - %s \
13+
// RUN: | FileCheck %s --check-prefix=CHECK-M
14+
15+
void bar();
16+
17+
__attribute__((interrupt_save_fp)) void test_generic_interrupt() {
18+
// CHECK-R: vmrs r4, fpscr
19+
// CHECK-R-NEXT: vmrs r5, fpexc
20+
// CHECK-R-NEXT: .save {r4, r5}
21+
// CHECK-R-NEXT: push {r4, r5}
22+
// .....
23+
// CHECK-R: pop {r4, r5}
24+
// CHECK-R-NEXT: vmsr fpscr, r4
25+
// CHECK-R-NEXT: vmsr fpexc, r5
26+
27+
// CHECK-M: vmrs r4, fpscr
28+
// CHECK-M-NEXT: .save {r4}
29+
// CHECK-M-NEXT: push {r4}
30+
// .....
31+
// CHECK-M: pop {r4}
32+
// CHECK-M-NEXT: vmsr fpscr, r4
33+
bar();
34+
}

Diff for: clang/test/CodeGen/arm-interrupt-save-fp-attr.c

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 -triple thumb-apple-darwin -target-abi aapcs -target-feature +vfp4 -target-cpu cortex-m3 -emit-llvm -o - %s | FileCheck %s
2+
// RUN: %clang_cc1 -triple arm-apple-darwin -target-abi apcs-gnu -target-feature +vfp4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-APCS
3+
4+
__attribute__((interrupt_save_fp)) void test_generic_interrupt() {
5+
// CHECK: define{{.*}} arm_aapcscc void @test_generic_interrupt() [[GENERIC_ATTR:#[0-9]+]]
6+
7+
// CHECK-APCS: define{{.*}} void @test_generic_interrupt() [[GENERIC_ATTR:#[0-9]+]]
8+
}
9+
10+
__attribute__((interrupt_save_fp("IRQ"))) void test_irq_interrupt() {
11+
// CHECK: define{{.*}} arm_aapcscc void @test_irq_interrupt() [[IRQ_ATTR:#[0-9]+]]
12+
}
13+
14+
__attribute__((interrupt_save_fp("FIQ"))) void test_fiq_interrupt() {
15+
// CHECK: define{{.*}} arm_aapcscc void @test_fiq_interrupt() [[FIQ_ATTR:#[0-9]+]]
16+
}
17+
18+
__attribute__((interrupt_save_fp("SWI"))) void test_swi_interrupt() {
19+
// CHECK: define{{.*}} arm_aapcscc void @test_swi_interrupt() [[SWI_ATTR:#[0-9]+]]
20+
}
21+
22+
__attribute__((interrupt_save_fp("ABORT"))) void test_abort_interrupt() {
23+
// CHECK: define{{.*}} arm_aapcscc void @test_abort_interrupt() [[ABORT_ATTR:#[0-9]+]]
24+
}
25+
26+
27+
__attribute__((interrupt_save_fp("UNDEF"))) void test_undef_interrupt() {
28+
// CHECK: define{{.*}} arm_aapcscc void @test_undef_interrupt() [[UNDEF_ATTR:#[0-9]+]]
29+
}
30+
31+
32+
// CHECK: attributes [[GENERIC_ATTR]] = { {{.*}} {{"interrupt"[^=]}}{{.*}} "save-fp"
33+
// CHECK: attributes [[IRQ_ATTR]] = { {{.*}} "interrupt"="IRQ" {{.*}} "save-fp"
34+
// CHECK: attributes [[FIQ_ATTR]] = { {{.*}} "interrupt"="FIQ" {{.*}} "save-fp"
35+
// CHECK: attributes [[SWI_ATTR]] = { {{.*}} "interrupt"="SWI" {{.*}} "save-fp"
36+
// CHECK: attributes [[ABORT_ATTR]] = { {{.*}} "interrupt"="ABORT" {{.*}} "save-fp"
37+
// CHECK: attributes [[UNDEF_ATTR]] = { {{.*}} "interrupt"="UNDEF" {{.*}} "save-fp"
38+
39+
// CHECK-APCS: attributes [[GENERIC_ATTR]] = { {{.*}} "interrupt" {{.*}} "save-fp"

Diff for: clang/test/Sema/arm-interrupt-attr.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44

55
#ifdef __ARM_FP
6-
__attribute__((interrupt("IRQ"))) void float_irq(void); // expected-warning {{interrupt service routine with vfp enabled may clobber the interruptee's vfp state}}
6+
__attribute__((interrupt("IRQ"))) void float_irq(void); // expected-warning {{interrupt service routine with vfp enabled may clobber the interruptee's vfp state; consider using the `interrupt_save_fp` attribute to prevent this behavior}}
77
#else // !defined(__ARM_FP)
88
__attribute__((interrupt("irq"))) void foo1(void) {} // expected-warning {{'interrupt' attribute argument not supported: irq}}
99
__attribute__((interrupt(IRQ))) void foo(void) {} // expected-error {{'interrupt' attribute requires a string}}

Diff for: clang/test/Sema/arm-interrupt-save-fp-attr.c

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 %s -triple arm-none-eabi -verify -fsyntax-only
2+
// RUN: %clang_cc1 %s -triple arm-none-eabi -target-feature +vfp2 -verify -fsyntax-only
3+
4+
5+
#if !defined(__ARM_FP)
6+
__attribute__((interrupt_save_fp("IRQ"))) void float_irq(void); // expected-warning {{`interrupt_save_fp` only applies to targets that have a VFP unit enabled for this compilation; this will be treated as a regular `interrupt` attribute}}
7+
#else // defined(__ARM_FP)
8+
__attribute__((interrupt_save_fp("irq"))) void foo1(void) {} // expected-warning {{'interrupt_save_fp' attribute argument not supported: irq}}
9+
__attribute__((interrupt_save_fp(IRQ))) void foo(void) {} // expected-error {{'interrupt_save_fp' attribute requires a string}}
10+
__attribute__((interrupt_save_fp("IRQ", 1))) void foo2(void) {} // expected-error {{'interrupt_save_fp' attribute takes no more than 1 argument}}
11+
__attribute__((interrupt_save_fp("IRQ"))) void foo3(void) {}
12+
__attribute__((interrupt_save_fp("FIQ"))) void foo4(void) {}
13+
__attribute__((interrupt_save_fp("SWI"))) void foo5(void) {}
14+
__attribute__((interrupt_save_fp("ABORT"))) void foo6(void) {}
15+
__attribute__((interrupt_save_fp("UNDEF"))) void foo7(void) {}
16+
__attribute__((interrupt_save_fp)) void foo8(void) {}
17+
__attribute__((interrupt_save_fp())) void foo9(void) {}
18+
__attribute__((interrupt_save_fp(""))) void foo10(void) {}
19+
20+
__attribute__((interrupt_save_fp("IRQ"))) void callee(void) {}
21+
22+
void caller(void)
23+
{
24+
callee(); // expected-error {{interrupt service routine cannot be called directly}}
25+
}
26+
#endif // __ARM_FP

Diff for: llvm/include/llvm/IR/IntrinsicsARM.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ def int_arm_isb : ClangBuiltin<"__builtin_arm_isb">, MSBuiltin<"__isb">,
311311
// VFP
312312

313313
def int_arm_get_fpscr : ClangBuiltin<"__builtin_arm_get_fpscr">,
314-
DefaultAttrsIntrinsic<[llvm_i32_ty], [], []>;
314+
DefaultAttrsIntrinsic<[llvm_i32_ty], [], [IntrReadMem]>;
315315
def int_arm_set_fpscr : ClangBuiltin<"__builtin_arm_set_fpscr">,
316316
DefaultAttrsIntrinsic<[], [llvm_i32_ty], []>;
317317
def int_arm_vcvtr : DefaultAttrsIntrinsic<[llvm_float_ty],

Diff for: llvm/lib/Target/ARM/ARMAsmPrinter.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,14 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
12021202
SrcReg = ~0U;
12031203
DstReg = MI->getOperand(0).getReg();
12041204
break;
1205+
case ARM::VMRS:
1206+
SrcReg = ARM::FPSCR;
1207+
DstReg = MI->getOperand(0).getReg();
1208+
break;
1209+
case ARM::VMRS_FPEXC:
1210+
SrcReg = ARM::FPEXC;
1211+
DstReg = MI->getOperand(0).getReg();
1212+
break;
12051213
default:
12061214
SrcReg = MI->getOperand(1).getReg();
12071215
DstReg = MI->getOperand(0).getReg();
@@ -1368,6 +1376,14 @@ void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
13681376
// correct ".save" later.
13691377
AFI->EHPrologueRemappedRegs[DstReg] = SrcReg;
13701378
break;
1379+
case ARM::VMRS:
1380+
case ARM::VMRS_FPEXC:
1381+
// If a function spills FPSCR or FPEXC, we copy the values to low
1382+
// registers before pushing them. However, we can't issue annotations
1383+
// for FP status registers because ".save" requires GPR registers, and
1384+
// ".vsave" requires DPR registers, so don't record the copy and simply
1385+
// emit annotations for the source registers used for the store.
1386+
break;
13711387
case ARM::tLDRpci: {
13721388
// Grab the constpool index and check, whether it corresponds to
13731389
// original or cloned constpool entry.

Diff for: llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,25 @@ ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
8080
? CSR_ATPCS_SplitPush_SwiftTail_SaveList
8181
: CSR_AAPCS_SwiftTail_SaveList);
8282
} else if (F.hasFnAttribute("interrupt")) {
83+
84+
// Don't save the floating point registers if target does not have floating
85+
// point registers.
86+
if (STI.hasFPRegs() && F.hasFnAttribute("save-fp")) {
87+
bool HasNEON = STI.hasNEON();
88+
89+
if (STI.isMClass()) {
90+
assert(!HasNEON && "NEON is only for Cortex-R/A");
91+
return PushPopSplit == ARMSubtarget::SplitR7
92+
? CSR_ATPCS_SplitPush_FP_SaveList
93+
: CSR_AAPCS_FP_SaveList;
94+
}
95+
if (F.getFnAttribute("interrupt").getValueAsString() == "FIQ") {
96+
return HasNEON ? CSR_FIQ_FP_NEON_SaveList : CSR_FIQ_FP_SaveList;
97+
}
98+
return HasNEON ? CSR_GenericInt_FP_NEON_SaveList
99+
: CSR_GenericInt_FP_SaveList;
100+
}
101+
83102
if (STI.isMClass()) {
84103
// M-class CPUs have hardware which saves the registers needed to allow a
85104
// function conforming to the AAPCS to function as a handler.

Diff for: llvm/lib/Target/ARM/ARMCallingConv.td

+32-10
Original file line numberDiff line numberDiff line change
@@ -268,19 +268,14 @@ def CC_ARM_Win32_CFGuard_Check : CallingConv<[
268268
def CSR_NoRegs : CalleeSavedRegs<(add)>;
269269
def CSR_FPRegs : CalleeSavedRegs<(add (sequence "D%u", 0, 31))>;
270270

271+
def CSR_FP_Interrupt_Regs : CalleeSavedRegs<(add FPSCR, FPEXC, (sequence "D%u", 15, 0))>;
272+
def CSR_FP_NEON_Interrupt_Regs : CalleeSavedRegs<(add CSR_FP_Interrupt_Regs,
273+
(sequence "D%u", 31, 16))>;
274+
271275
def CSR_AAPCS : CalleeSavedRegs<(add LR, R11, R10, R9, R8, R7, R6, R5, R4,
272276
(sequence "D%u", 15, 8))>;
273277

274-
// The Windows Control Flow Guard Check function preserves the same registers as
275-
// AAPCS, and also preserves all floating point registers.
276-
def CSR_Win_AAPCS_CFGuard_Check : CalleeSavedRegs<(add LR, R11, R10, R9, R8, R7,
277-
R6, R5, R4, (sequence "D%u", 15, 0))>;
278-
279-
// R8 is used to pass swifterror, remove it from CSR.
280-
def CSR_AAPCS_SwiftError : CalleeSavedRegs<(sub CSR_AAPCS, R8)>;
281-
282-
// R10 is used to pass swiftself, remove it from CSR.
283-
def CSR_AAPCS_SwiftTail : CalleeSavedRegs<(sub CSR_AAPCS, R10)>;
278+
def CSR_AAPCS_FP : CalleeSavedRegs<(add CSR_AAPCS, CSR_FP_Interrupt_Regs)>;
284279

285280
// The order of callee-saved registers needs to match the order we actually push
286281
// them in FrameLowering, because this order is what's used by
@@ -294,6 +289,21 @@ def CSR_Win_SplitFP : CalleeSavedRegs<(add R10, R9, R8, R7, R6, R5, R4,
294289
(sequence "D%u", 15, 8),
295290
LR, R11)>;
296291

292+
def CSR_ATPCS_SplitPush_FP : CalleeSavedRegs<(add CSR_ATPCS_SplitPush,
293+
CSR_FP_Interrupt_Regs)>;
294+
295+
// The Windows Control Flow Guard Check function preserves the same registers as
296+
// AAPCS, and also preserves all floating point registers.
297+
def CSR_Win_AAPCS_CFGuard_Check : CalleeSavedRegs<(add LR, R11, R10, R9, R8, R7,
298+
R6, R5, R4, (sequence "D%u", 15, 0))>;
299+
300+
// R8 is used to pass swifterror, remove it from CSR.
301+
def CSR_AAPCS_SwiftError : CalleeSavedRegs<(sub CSR_AAPCS, R8)>;
302+
303+
// R10 is used to pass swiftself, remove it from CSR.
304+
def CSR_AAPCS_SwiftTail : CalleeSavedRegs<(sub CSR_AAPCS, R10)>;
305+
306+
297307
// R8 is used to pass swifterror, remove it from CSR.
298308
def CSR_ATPCS_SplitPush_SwiftError : CalleeSavedRegs<(sub CSR_ATPCS_SplitPush,
299309
R8)>;
@@ -361,6 +371,13 @@ def CSR_iOS_CXX_TLS_ViaCopy : CalleeSavedRegs<(sub CSR_iOS_CXX_TLS,
361371
// generally does rather than tracking its liveness as a normal register.
362372
def CSR_GenericInt : CalleeSavedRegs<(add LR, (sequence "R%u", 12, 0))>;
363373

374+
def CSR_GenericInt_FP : CalleeSavedRegs<(add CSR_GenericInt,
375+
CSR_FP_Interrupt_Regs)>;
376+
377+
def CSR_GenericInt_FP_NEON : CalleeSavedRegs<(add CSR_GenericInt_FP,
378+
CSR_FP_NEON_Interrupt_Regs)>;
379+
380+
364381
// The fast interrupt handlers have more private state and get their own copies
365382
// of R8-R12, in addition to SP and LR. As before, mark LR for saving too.
366383

@@ -369,4 +386,9 @@ def CSR_GenericInt : CalleeSavedRegs<(add LR, (sequence "R%u", 12, 0))>;
369386
// registers.
370387
def CSR_FIQ : CalleeSavedRegs<(add LR, R11, (sequence "R%u", 7, 0))>;
371388

389+
def CSR_FIQ_FP : CalleeSavedRegs<(add CSR_FIQ, CSR_FP_Interrupt_Regs)>;
390+
391+
def CSR_FIQ_FP_NEON : CalleeSavedRegs<(add CSR_FIQ_FP,
392+
CSR_FP_NEON_Interrupt_Regs)>;
393+
372394

0 commit comments

Comments
 (0)