Skip to content

Commit d8e67c1

Browse files
committed
[ARM] Add SEH opcodes in frame lowering
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
1 parent 5482ae6 commit d8e67c1

13 files changed

+804
-76
lines changed

llvm/lib/Target/ARM/ARMAsmPrinter.cpp

+41
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,47 @@ void ARMAsmPrinter::emitInstruction(const MachineInstr *MI) {
22742274
EmitToStreamer(*OutStreamer, TmpInstSB);
22752275
return;
22762276
}
2277+
2278+
case ARM::SEH_StackAlloc:
2279+
ATS.emitARMWinCFIAllocStack(MI->getOperand(0).getImm(),
2280+
MI->getOperand(1).getImm());
2281+
return;
2282+
2283+
case ARM::SEH_SaveRegs:
2284+
case ARM::SEH_SaveRegs_Ret:
2285+
ATS.emitARMWinCFISaveRegMask(MI->getOperand(0).getImm(),
2286+
MI->getOperand(1).getImm());
2287+
return;
2288+
2289+
case ARM::SEH_SaveSP:
2290+
ATS.emitARMWinCFISaveSP(MI->getOperand(0).getImm());
2291+
return;
2292+
2293+
case ARM::SEH_SaveFRegs:
2294+
ATS.emitARMWinCFISaveFRegs(MI->getOperand(0).getImm(),
2295+
MI->getOperand(1).getImm());
2296+
return;
2297+
2298+
case ARM::SEH_SaveLR:
2299+
ATS.emitARMWinCFISaveLR(MI->getOperand(0).getImm());
2300+
return;
2301+
2302+
case ARM::SEH_Nop:
2303+
case ARM::SEH_Nop_Ret:
2304+
ATS.emitARMWinCFINop(MI->getOperand(0).getImm());
2305+
return;
2306+
2307+
case ARM::SEH_PrologEnd:
2308+
ATS.emitARMWinCFIPrologEnd(/*Fragment=*/false);
2309+
return;
2310+
2311+
case ARM::SEH_EpilogStart:
2312+
ATS.emitARMWinCFIEpilogStart(ARMCC::AL);
2313+
return;
2314+
2315+
case ARM::SEH_EpilogEnd:
2316+
ATS.emitARMWinCFIEpilogEnd();
2317+
return;
22772318
}
22782319

22792320
MCInst TmpInst;

llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -2071,6 +2071,9 @@ bool ARMBaseInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
20712071
if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
20722072
return true;
20732073

2074+
if (isSEHInstruction(MI))
2075+
return true;
2076+
20742077
// Treat the start of the IT block as a scheduling boundary, but schedule
20752078
// t2IT along with all instructions following it.
20762079
// FIXME: This is a big hammer. But the alternative is to add all potential

llvm/lib/Target/ARM/ARMBaseInstrInfo.h

+20
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,26 @@ static inline bool isValidCoprocessorNumber(unsigned Num,
757757
return true;
758758
}
759759

760+
static inline bool isSEHInstruction(const MachineInstr &MI) {
761+
unsigned Opc = MI.getOpcode();
762+
switch (Opc) {
763+
case ARM::SEH_StackAlloc:
764+
case ARM::SEH_SaveRegs:
765+
case ARM::SEH_SaveRegs_Ret:
766+
case ARM::SEH_SaveSP:
767+
case ARM::SEH_SaveFRegs:
768+
case ARM::SEH_SaveLR:
769+
case ARM::SEH_Nop:
770+
case ARM::SEH_Nop_Ret:
771+
case ARM::SEH_PrologEnd:
772+
case ARM::SEH_EpilogStart:
773+
case ARM::SEH_EpilogEnd:
774+
return true;
775+
default:
776+
return false;
777+
}
778+
}
779+
760780
/// getInstrPredicate - If instruction is predicated, returns its predicate
761781
/// condition, otherwise returns AL. It also returns the condition code
762782
/// register by reference.

llvm/lib/Target/ARM/ARMBaseRegisterInfo.h

+2
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo {
214214
unsigned DefSubReg,
215215
const TargetRegisterClass *SrcRC,
216216
unsigned SrcSubReg) const override;
217+
218+
int getSEHRegNum(unsigned i) const { return getEncodingValue(i); }
217219
};
218220

219221
} // end namespace llvm

llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/CodeGen/LivePhysRegs.h"
2424
#include "llvm/CodeGen/MachineFrameInfo.h"
2525
#include "llvm/CodeGen/MachineFunctionPass.h"
26+
#include "llvm/MC/MCAsmInfo.h"
2627
#include "llvm/Support/Debug.h"
2728

2829
using namespace llvm;
@@ -2107,6 +2108,10 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
21072108
case ARM::TCRETURNdi:
21082109
case ARM::TCRETURNri: {
21092110
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
2111+
if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)
2112+
MBBI--;
2113+
if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)
2114+
MBBI--;
21102115
assert(MBBI->isReturn() &&
21112116
"Can only insert epilog into returning blocks");
21122117
unsigned RetOpcode = MBBI->getOpcode();
@@ -2116,13 +2121,21 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
21162121

21172122
// Tail call return: adjust the stack pointer and jump to callee.
21182123
MBBI = MBB.getLastNonDebugInstr();
2124+
if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)
2125+
MBBI--;
2126+
if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)
2127+
MBBI--;
21192128
MachineOperand &JumpTarget = MBBI->getOperand(0);
21202129

21212130
// Jump to label or value in register.
21222131
if (RetOpcode == ARM::TCRETURNdi) {
2132+
MachineFunction *MF = MBB.getParent();
2133+
bool NeedsWinCFI = MF->getTarget().getMCAsmInfo()->usesWindowsCFI() &&
2134+
MF->getFunction().needsUnwindTableEntry();
21232135
unsigned TCOpcode =
21242136
STI->isThumb()
2125-
? (STI->isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND)
2137+
? ((STI->isTargetMachO() || NeedsWinCFI) ? ARM::tTAILJMPd
2138+
: ARM::tTAILJMPdND)
21262139
: ARM::TAILJMPd;
21272140
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
21282141
if (JumpTarget.isGlobal())

0 commit comments

Comments
 (0)