Skip to content

Commit

Permalink
[ARM] Add SEH opcodes in frame lowering
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mstorsjo committed Jun 2, 2022
1 parent 5482ae6 commit d8e67c1
Show file tree
Hide file tree
Showing 13 changed files with 804 additions and 76 deletions.
41 changes: 41 additions & 0 deletions llvm/lib/Target/ARM/ARMAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,47 @@ void ARMAsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, TmpInstSB);
return;
}

case ARM::SEH_StackAlloc:
ATS.emitARMWinCFIAllocStack(MI->getOperand(0).getImm(),
MI->getOperand(1).getImm());
return;

case ARM::SEH_SaveRegs:
case ARM::SEH_SaveRegs_Ret:
ATS.emitARMWinCFISaveRegMask(MI->getOperand(0).getImm(),
MI->getOperand(1).getImm());
return;

case ARM::SEH_SaveSP:
ATS.emitARMWinCFISaveSP(MI->getOperand(0).getImm());
return;

case ARM::SEH_SaveFRegs:
ATS.emitARMWinCFISaveFRegs(MI->getOperand(0).getImm(),
MI->getOperand(1).getImm());
return;

case ARM::SEH_SaveLR:
ATS.emitARMWinCFISaveLR(MI->getOperand(0).getImm());
return;

case ARM::SEH_Nop:
case ARM::SEH_Nop_Ret:
ATS.emitARMWinCFINop(MI->getOperand(0).getImm());
return;

case ARM::SEH_PrologEnd:
ATS.emitARMWinCFIPrologEnd(/*Fragment=*/false);
return;

case ARM::SEH_EpilogStart:
ATS.emitARMWinCFIEpilogStart(ARMCC::AL);
return;

case ARM::SEH_EpilogEnd:
ATS.emitARMWinCFIEpilogEnd();
return;
}

MCInst TmpInst;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2071,6 +2071,9 @@ bool ARMBaseInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
return true;

if (isSEHInstruction(MI))
return true;

// Treat the start of the IT block as a scheduling boundary, but schedule
// t2IT along with all instructions following it.
// FIXME: This is a big hammer. But the alternative is to add all potential
Expand Down
20 changes: 20 additions & 0 deletions llvm/lib/Target/ARM/ARMBaseInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,26 @@ static inline bool isValidCoprocessorNumber(unsigned Num,
return true;
}

static inline bool isSEHInstruction(const MachineInstr &MI) {
unsigned Opc = MI.getOpcode();
switch (Opc) {
case ARM::SEH_StackAlloc:
case ARM::SEH_SaveRegs:
case ARM::SEH_SaveRegs_Ret:
case ARM::SEH_SaveSP:
case ARM::SEH_SaveFRegs:
case ARM::SEH_SaveLR:
case ARM::SEH_Nop:
case ARM::SEH_Nop_Ret:
case ARM::SEH_PrologEnd:
case ARM::SEH_EpilogStart:
case ARM::SEH_EpilogEnd:
return true;
default:
return false;
}
}

/// getInstrPredicate - If instruction is predicated, returns its predicate
/// condition, otherwise returns AL. It also returns the condition code
/// register by reference.
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/ARM/ARMBaseRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ class ARMBaseRegisterInfo : public ARMGenRegisterInfo {
unsigned DefSubReg,
const TargetRegisterClass *SrcRC,
unsigned SrcSubReg) const override;

int getSEHRegNum(unsigned i) const { return getEncodingValue(i); }
};

} // end namespace llvm
Expand Down
15 changes: 14 additions & 1 deletion llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/Debug.h"

using namespace llvm;
Expand Down Expand Up @@ -2107,6 +2108,10 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
case ARM::TCRETURNdi:
case ARM::TCRETURNri: {
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)
MBBI--;
if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)
MBBI--;
assert(MBBI->isReturn() &&
"Can only insert epilog into returning blocks");
unsigned RetOpcode = MBBI->getOpcode();
Expand All @@ -2116,13 +2121,21 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,

// Tail call return: adjust the stack pointer and jump to callee.
MBBI = MBB.getLastNonDebugInstr();
if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)
MBBI--;
if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)
MBBI--;
MachineOperand &JumpTarget = MBBI->getOperand(0);

// Jump to label or value in register.
if (RetOpcode == ARM::TCRETURNdi) {
MachineFunction *MF = MBB.getParent();
bool NeedsWinCFI = MF->getTarget().getMCAsmInfo()->usesWindowsCFI() &&
MF->getFunction().needsUnwindTableEntry();
unsigned TCOpcode =
STI->isThumb()
? (STI->isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND)
? ((STI->isTargetMachO() || NeedsWinCFI) ? ARM::tTAILJMPd
: ARM::tTAILJMPdND)
: ARM::TAILJMPd;
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode));
if (JumpTarget.isGlobal())
Expand Down
Loading

0 comments on commit d8e67c1

Please sign in to comment.