|
27 | 27 |
|
28 | 28 | using namespace llvm;
|
29 | 29 |
|
| 30 | +// Returns the register used to hold the frame pointer. |
| 31 | +static Register getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; } |
| 32 | + |
| 33 | +// Returns the register used to hold the stack pointer. |
| 34 | +static Register getSPReg(const RISCVSubtarget &STI) { return RISCV::X2; } |
| 35 | + |
30 | 36 | // For now we use x18, a.k.a s2, as pointer to shadow call stack.
|
31 | 37 | // User should explicitly set -ffixed-x18 and not use x18 in their asm.
|
32 | 38 | static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
|
33 | 39 | MachineBasicBlock::iterator MI,
|
34 | 40 | const DebugLoc &DL) {
|
35 |
| - if (!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)) |
| 41 | + if (!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack) || |
| 42 | + MF.getFunction().hasFnAttribute("interrupt")) |
36 | 43 | return;
|
37 | 44 |
|
38 | 45 | const auto &STI = MF.getSubtarget<RISCVSubtarget>();
|
@@ -65,25 +72,32 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
|
65 | 72 | const RISCVInstrInfo *TII = STI.getInstrInfo();
|
66 | 73 | bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
|
67 | 74 | int64_t SlotSize = STI.getXLen() / 8;
|
68 |
| - // Store return address to shadow call stack |
| 75 | + // Store return address and the stack pointer to shadow call stack. |
69 | 76 | // s[w|d] ra, 0(s2)
|
70 |
| - // addi s2, s2, [4|8] |
| 77 | + // s[w|d] sp, [4|8](s2) |
| 78 | + // addi s2, s2, [4|8]*2 |
71 | 79 | BuildMI(MBB, MI, DL, TII->get(IsRV64 ? RISCV::SD : RISCV::SW))
|
72 | 80 | .addReg(RAReg)
|
73 | 81 | .addReg(SCSPReg)
|
74 | 82 | .addImm(0)
|
75 | 83 | .setMIFlag(MachineInstr::FrameSetup);
|
| 84 | + BuildMI(MBB, MI, DL, TII->get(IsRV64 ? RISCV::SD : RISCV::SW)) |
| 85 | + .addReg(getSPReg(STI)) |
| 86 | + .addReg(SCSPReg) |
| 87 | + .addImm(SlotSize) |
| 88 | + .setMIFlag(MachineInstr::FrameSetup); |
76 | 89 | BuildMI(MBB, MI, DL, TII->get(RISCV::ADDI))
|
77 | 90 | .addReg(SCSPReg, RegState::Define)
|
78 | 91 | .addReg(SCSPReg)
|
79 |
| - .addImm(SlotSize) |
| 92 | + .addImm(SlotSize * 2) |
80 | 93 | .setMIFlag(MachineInstr::FrameSetup);
|
81 | 94 | }
|
82 | 95 |
|
83 | 96 | static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
|
84 | 97 | MachineBasicBlock::iterator MI,
|
85 | 98 | const DebugLoc &DL) {
|
86 |
| - if (!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)) |
| 99 | + if (!MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack) || |
| 100 | + MF.getFunction().hasFnAttribute("interrupt")) |
87 | 101 | return;
|
88 | 102 |
|
89 | 103 | const auto &STI = MF.getSubtarget<RISCVSubtarget>();
|
@@ -115,18 +129,92 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
|
115 | 129 | const RISCVInstrInfo *TII = STI.getInstrInfo();
|
116 | 130 | bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
|
117 | 131 | int64_t SlotSize = STI.getXLen() / 8;
|
118 |
| - // Load return address from shadow call stack |
119 |
| - // l[w|d] ra, -[4|8](s2) |
| 132 | + // The assembly code below loads the return address and stack pointer from |
| 133 | + // the shadow call stack and executes the following pseudo-code without using |
| 134 | + // branches: |
| 135 | + // |
| 136 | + // if (sp == shadow_sp && ra == shadow_ra) { |
| 137 | + // return; |
| 138 | + // } else { |
| 139 | + // __abi_shutdown$(); |
| 140 | + // } |
| 141 | + // |
| 142 | + // l[w|d] t0, -[4|8](s2) |
| 143 | + // l[w|d] t1, -[4|8]*2(s2) |
120 | 144 | // addi s2, s2, -[4|8]
|
| 145 | + // xor t0, t0, sp |
| 146 | + // xor t1, t1, ra |
| 147 | + // or t0, t0, t1 |
| 148 | + // snez t1, t0 |
| 149 | + // addi t1, t1, -1 |
| 150 | + // not t0, t1 |
| 151 | + // la t2, __abi_shutdown$ |
| 152 | + // and t0, t0, t2 |
| 153 | + // and t1, t1, ra |
| 154 | + // or ra, t0, t1 |
121 | 155 | BuildMI(MBB, MI, DL, TII->get(IsRV64 ? RISCV::LD : RISCV::LW))
|
122 |
| - .addReg(RAReg, RegState::Define) |
| 156 | + .addReg(RISCV::X5, RegState::Define) |
123 | 157 | .addReg(SCSPReg)
|
124 | 158 | .addImm(-SlotSize)
|
125 | 159 | .setMIFlag(MachineInstr::FrameDestroy);
|
| 160 | + BuildMI(MBB, MI, DL, TII->get(IsRV64 ? RISCV::LD : RISCV::LW)) |
| 161 | + .addReg(RISCV::X6, RegState::Define) |
| 162 | + .addReg(SCSPReg) |
| 163 | + .addImm(-SlotSize * 2) |
| 164 | + .setMIFlag(MachineInstr::FrameDestroy); |
126 | 165 | BuildMI(MBB, MI, DL, TII->get(RISCV::ADDI))
|
127 | 166 | .addReg(SCSPReg, RegState::Define)
|
128 | 167 | .addReg(SCSPReg)
|
129 |
| - .addImm(-SlotSize) |
| 168 | + .addImm(-SlotSize * 2) |
| 169 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 170 | + BuildMI(MBB, MI, DL, TII->get(RISCV::XOR)) |
| 171 | + .addReg(RISCV::X5, RegState::Define) |
| 172 | + .addReg(RISCV::X5) |
| 173 | + .addReg(getSPReg(STI)) |
| 174 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 175 | + BuildMI(MBB, MI, DL, TII->get(RISCV::XOR)) |
| 176 | + .addReg(RISCV::X6, RegState::Define) |
| 177 | + .addReg(RISCV::X6) |
| 178 | + .addReg(RAReg) |
| 179 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 180 | + BuildMI(MBB, MI, DL, TII->get(RISCV::OR)) |
| 181 | + .addReg(RISCV::X5, RegState::Define) |
| 182 | + .addReg(RISCV::X5) |
| 183 | + .addReg(RISCV::X6) |
| 184 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 185 | + BuildMI(MBB, MI, DL, TII->get(RISCV::SLTU)) |
| 186 | + .addReg(RISCV::X6, RegState::Define) |
| 187 | + .addReg(RISCV::X0) |
| 188 | + .addReg(RISCV::X5) |
| 189 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 190 | + BuildMI(MBB, MI, DL, TII->get(RISCV::ADDI)) |
| 191 | + .addReg(RISCV::X6, RegState::Define) |
| 192 | + .addReg(RISCV::X6) |
| 193 | + .addImm(-1) |
| 194 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 195 | + BuildMI(MBB, MI, DL, TII->get(RISCV::XORI)) |
| 196 | + .addReg(RISCV::X5, RegState::Define) |
| 197 | + .addReg(RISCV::X6) |
| 198 | + .addImm(-1) |
| 199 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 200 | + BuildMI(MBB, MI, DL, TII->get(RISCV::PseudoLLA)) |
| 201 | + .addReg(RISCV::X7, RegState::Define) |
| 202 | + .addExternalSymbol("__abi_shutdown$", RISCVII::MO_CALL) |
| 203 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 204 | + BuildMI(MBB, MI, DL, TII->get(RISCV::AND)) |
| 205 | + .addReg(RISCV::X5, RegState::Define) |
| 206 | + .addReg(RISCV::X5) |
| 207 | + .addReg(RISCV::X7, RegState::Kill) |
| 208 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 209 | + BuildMI(MBB, MI, DL, TII->get(RISCV::AND)) |
| 210 | + .addReg(RISCV::X6, RegState::Define) |
| 211 | + .addReg(RISCV::X6) |
| 212 | + .addReg(RAReg) |
| 213 | + .setMIFlag(MachineInstr::FrameDestroy); |
| 214 | + BuildMI(MBB, MI, DL, TII->get(RISCV::OR)) |
| 215 | + .addReg(RAReg, RegState::Define) |
| 216 | + .addReg(RISCV::X5, RegState::Kill) |
| 217 | + .addReg(RISCV::X6, RegState::Kill) |
130 | 218 | .setMIFlag(MachineInstr::FrameDestroy);
|
131 | 219 | }
|
132 | 220 |
|
@@ -291,12 +379,6 @@ uint64_t RISCVFrameLowering::getStackSizeWithRVVPadding(
|
291 | 379 | return alignTo(MFI.getStackSize() + RVFI->getRVVPadding(), getStackAlign());
|
292 | 380 | }
|
293 | 381 |
|
294 |
| -// Returns the register used to hold the frame pointer. |
295 |
| -static Register getFPReg(const RISCVSubtarget &STI) { return RISCV::X8; } |
296 |
| - |
297 |
| -// Returns the register used to hold the stack pointer. |
298 |
| -static Register getSPReg(const RISCVSubtarget &STI) { return RISCV::X2; } |
299 |
| - |
300 | 382 | static SmallVector<CalleeSavedInfo, 8>
|
301 | 383 | getNonLibcallCSI(const MachineFunction &MF,
|
302 | 384 | const std::vector<CalleeSavedInfo> &CSI) {
|
|
0 commit comments