@@ -486,6 +486,18 @@ getPushOrLibCallsSavedInfo(const MachineFunction &MF,
486
486
return PushOrLibCallsCSI;
487
487
488
488
for (const auto &CS : CSI) {
489
+ if (RVFI->useQCIInterrupt (MF)) {
490
+ // Some registers are saved by both `QC.C.MIENTER(.NEST)` and
491
+ // `QC.CM.PUSH(FP)`. In these cases, prioritise the CFI info that points
492
+ // to the versions saved by `QC.C.MIENTER(.NEST)` which is what FP
493
+ // unwinding would use.
494
+ const auto *FII = llvm::find_if (FixedCSRFIQCIInterruptMap, [&](auto P) {
495
+ return P.first == CS.getReg ();
496
+ });
497
+ if (FII != std::end (FixedCSRFIQCIInterruptMap))
498
+ continue ;
499
+ }
500
+
489
501
const auto *FII = llvm::find_if (
490
502
FixedCSRFIMap, [&](MCPhysReg P) { return P == CS.getReg (); });
491
503
if (FII != std::end (FixedCSRFIMap))
@@ -826,12 +838,12 @@ static bool isPop(unsigned Opcode) {
826
838
}
827
839
828
840
static unsigned getPushOpcode (RISCVMachineFunctionInfo::PushPopKind Kind,
829
- bool HasFP ) {
841
+ bool UpdateFP ) {
830
842
switch (Kind) {
831
843
case RISCVMachineFunctionInfo::PushPopKind::StdExtZcmp:
832
844
return RISCV::CM_PUSH;
833
845
case RISCVMachineFunctionInfo::PushPopKind::VendorXqccmp:
834
- return HasFP ? RISCV::QC_CM_PUSHFP : RISCV::QC_CM_PUSH;
846
+ return UpdateFP ? RISCV::QC_CM_PUSHFP : RISCV::QC_CM_PUSH;
835
847
default :
836
848
llvm_unreachable (" Unhandled PushPopKind" );
837
849
}
@@ -872,7 +884,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
872
884
// Emit prologue for shadow call stack.
873
885
emitSCSPrologue (MF, MBB, MBBI, DL);
874
886
875
- auto FirstFrameSetup = MBBI;
887
+ // We keep track of the first instruction because it might be a
888
+ // `(QC.)CM.PUSH(FP)`, and we may need to adjust the immediate rather than
889
+ // inserting an `addi sp, sp, -N*16`
890
+ auto PossiblePush = MBBI;
876
891
877
892
// Skip past all callee-saved register spill instructions.
878
893
while (MBBI != MBB.end () && MBBI->getFlag (MachineInstr::FrameSetup))
@@ -949,22 +964,32 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
949
964
}
950
965
951
966
if (RVFI->useQCIInterrupt (MF)) {
967
+ // The function starts with `QC.C.MIENTER(.NEST)`, so the `(QC.)CM.PUSH(FP)`
968
+ // could only be the next instruction.
969
+ PossiblePush = std::next (PossiblePush);
970
+
971
+ // Insert the CFI metadata before where we think the `(QC.)CM.PUSH(FP)`
972
+ // could be. The PUSH will also get its own CFI metadata for its own
973
+ // modifications, which should come after the PUSH.
952
974
unsigned CFIIndex = MF.addFrameInst (
953
975
MCCFIInstruction::cfiDefCfaOffset (nullptr , QCIInterruptPushAmount));
954
- BuildMI (MBB, MBBI , DL, TII->get (TargetOpcode::CFI_INSTRUCTION))
976
+ BuildMI (MBB, PossiblePush , DL, TII->get (TargetOpcode::CFI_INSTRUCTION))
955
977
.addCFIIndex (CFIIndex)
956
978
.setMIFlag (MachineInstr::FrameSetup);
957
979
958
- emitCFIForCSI<CFISaveRegisterEmitter>(MBB, MBBI, getQCISavedInfo (MF, CSI));
959
- } else if (RVFI->isPushable (MF) && FirstFrameSetup != MBB.end () &&
960
- isPush (FirstFrameSetup->getOpcode ())) {
980
+ emitCFIForCSI<CFISaveRegisterEmitter>(MBB, PossiblePush,
981
+ getQCISavedInfo (MF, CSI));
982
+ }
983
+
984
+ if (RVFI->isPushable (MF) && PossiblePush != MBB.end () &&
985
+ isPush (PossiblePush->getOpcode ())) {
961
986
// Use available stack adjustment in push instruction to allocate additional
962
987
// stack space. Align the stack size down to a multiple of 16. This is
963
988
// needed for RVE.
964
989
// FIXME: Can we increase the stack size to a multiple of 16 instead?
965
990
uint64_t Spimm =
966
991
std::min (alignDown (StackSize, 16 ), static_cast <uint64_t >(48 ));
967
- FirstFrameSetup ->getOperand (1 ).setImm (Spimm);
992
+ PossiblePush ->getOperand (1 ).setImm (Spimm);
968
993
StackSize -= Spimm;
969
994
970
995
unsigned CFIIndex = MF.addFrameInst (
@@ -1868,10 +1893,13 @@ bool RISCVFrameLowering::assignCalleeSavedSpillSlots(
1868
1893
auto *RVFI = MF.getInfo <RISCVMachineFunctionInfo>();
1869
1894
if (RVFI->useQCIInterrupt (MF)) {
1870
1895
RVFI->setQCIInterruptStackSize (QCIInterruptPushAmount);
1871
- } else if (RVFI->isPushable (MF)) {
1896
+ }
1897
+
1898
+ if (RVFI->isPushable (MF)) {
1872
1899
// Determine how many GPRs we need to push and save it to RVFI.
1873
1900
unsigned PushedRegNum = getNumPushPopRegs (CSI);
1874
- if (PushedRegNum) {
1901
+ unsigned PushMoreThan = RVFI->useQCIInterrupt (MF) ? 2 : 0 ;
1902
+ if (PushedRegNum > PushMoreThan) {
1875
1903
RVFI->setRVPushRegs (PushedRegNum);
1876
1904
RVFI->setRVPushStackSize (alignTo ((STI.getXLen () / 8 ) * PushedRegNum, 16 ));
1877
1905
}
@@ -1897,8 +1925,9 @@ bool RISCVFrameLowering::assignCalleeSavedSpillSlots(
1897
1925
CS.setFrameIdx (FrameIdx);
1898
1926
continue ;
1899
1927
}
1900
- // TODO: QCI Interrupt + Push/Pop
1901
- } else if (RVFI->useSaveRestoreLibCalls (MF) || RVFI->isPushable (MF)) {
1928
+ }
1929
+
1930
+ if (RVFI->useSaveRestoreLibCalls (MF) || RVFI->isPushable (MF)) {
1902
1931
const auto *FII = llvm::find_if (
1903
1932
FixedCSRFIMap, [&](MCPhysReg P) { return P == CS.getReg (); });
1904
1933
unsigned RegNum = std::distance (std::begin (FixedCSRFIMap), FII);
@@ -1911,6 +1940,9 @@ bool RISCVFrameLowering::assignCalleeSavedSpillSlots(
1911
1940
else
1912
1941
Offset = -int64_t (RegNum + 1 ) * Size;
1913
1942
1943
+ if (RVFI->useQCIInterrupt (MF))
1944
+ Offset -= QCIInterruptPushAmount;
1945
+
1914
1946
int FrameIdx = MFI.CreateFixedSpillStackObject (Size, Offset);
1915
1947
assert (FrameIdx < 0 );
1916
1948
CS.setFrameIdx (FrameIdx);
@@ -1939,12 +1971,17 @@ bool RISCVFrameLowering::assignCalleeSavedSpillSlots(
1939
1971
// because there are gaps which are reserved for future use.
1940
1972
MFI.CreateFixedSpillStackObject (
1941
1973
QCIInterruptPushAmount, -static_cast <int64_t >(QCIInterruptPushAmount));
1942
- } else if (RVFI->isPushable (MF)) {
1974
+ }
1975
+
1976
+ if (RVFI->isPushable (MF)) {
1943
1977
// Allocate a fixed object that covers all the registers that are pushed.
1944
1978
if (unsigned PushedRegs = RVFI->getRVPushRegs ()) {
1945
1979
int64_t PushedRegsBytes =
1946
1980
static_cast <int64_t >(PushedRegs) * (STI.getXLen () / 8 );
1947
- MFI.CreateFixedSpillStackObject (PushedRegsBytes, -PushedRegsBytes);
1981
+ int64_t QCIOffset =
1982
+ RVFI->useQCIInterrupt (MF) ? QCIInterruptPushAmount : 0 ;
1983
+ MFI.CreateFixedSpillStackObject (PushedRegsBytes,
1984
+ -PushedRegsBytes - QCIOffset);
1948
1985
}
1949
1986
} else if (int LibCallRegs = getLibCallID (MF, CSI) + 1 ) {
1950
1987
// Allocate a fixed object that covers all of the stack allocated by the
@@ -1982,13 +2019,15 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters(
1982
2019
1983
2020
for (auto [Reg, _Offset] : FixedCSRFIQCIInterruptMap)
1984
2021
MBB.addLiveIn (Reg);
1985
- // TODO: Handle QCI Interrupt + Push/Pop
1986
- } else if (RVFI->isPushable (*MF)) {
2022
+ }
2023
+
2024
+ if (RVFI->isPushable (*MF)) {
1987
2025
// Emit CM.PUSH with base SPimm & evaluate Push stack
1988
2026
unsigned PushedRegNum = RVFI->getRVPushRegs ();
1989
2027
if (PushedRegNum > 0 ) {
1990
2028
// Use encoded number to represent registers to spill.
1991
- unsigned Opcode = getPushOpcode (RVFI->getPushPopKind (*MF), hasFP (*MF));
2029
+ unsigned Opcode = getPushOpcode (
2030
+ RVFI->getPushPopKind (*MF), hasFP (*MF) && !RVFI->useQCIInterrupt (*MF));
1992
2031
unsigned RegEnc = RISCVZC::encodeRlistNumRegs (PushedRegNum);
1993
2032
MachineInstrBuilder PushBuilder =
1994
2033
BuildMI (MBB, MI, DL, TII.get (Opcode))
@@ -2146,8 +2185,9 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters(
2146
2185
// QC.C.MILEAVERET which we already inserted to return.
2147
2186
assert (MI->getOpcode () == RISCV::QC_C_MILEAVERET &&
2148
2187
" Unexpected QCI Interrupt Return Instruction" );
2149
- // TODO: Handle QCI + Push/Pop
2150
- } else if (RVFI->isPushable (*MF)) {
2188
+ }
2189
+
2190
+ if (RVFI->isPushable (*MF)) {
2151
2191
unsigned PushedRegNum = RVFI->getRVPushRegs ();
2152
2192
if (PushedRegNum > 0 ) {
2153
2193
unsigned Opcode = getPopOpcode (RVFI->getPushPopKind (*MF));
0 commit comments