LLVM  16.0.0git
CFIFixup.cpp
Go to the documentation of this file.
1 //===------ CFIFixup.cpp - Insert CFI remember/restore instructions -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 
10 // This pass inserts the necessary instructions to adjust for the inconsistency
11 // of the call-frame information caused by final machine basic block layout.
12 // The pass relies in constraints LLVM imposes on the placement of
13 // save/restore points (cf. ShrinkWrap):
14 // * there is a single basic block, containing the function prologue
15 // * possibly multiple epilogue blocks, where each epilogue block is
16 // complete and self-contained, i.e. CSR restore instructions (and the
17 // corresponding CFI instructions are not split across two or more blocks.
18 // * prologue and epilogue blocks are outside of any loops
19 // Thus, during execution, at the beginning and at the end of each basic block
20 // the function can be in one of two states:
21 // - "has a call frame", if the function has executed the prologue, and
22 // has not executed any epilogue
23 // - "does not have a call frame", if the function has not executed the
24 // prologue, or has executed an epilogue
25 // which can be computed by a single RPO traversal.
26 
27 // In order to accommodate backends which do not generate unwind info in
28 // epilogues we compute an additional property "strong no call frame on entry",
29 // which is set for the entry point of the function and for every block
30 // reachable from the entry along a path that does not execute the prologue. If
31 // this property holds, it takes precedence over the "has a call frame"
32 // property.
33 
34 // From the point of view of the unwind tables, the "has/does not have call
35 // frame" state at beginning of each block is determined by the state at the end
36 // of the previous block, in layout order. Where these states differ, we insert
37 // compensating CFI instructions, which come in two flavours:
38 
39 // - CFI instructions, which reset the unwind table state to the initial one.
40 // This is done by a target specific hook and is expected to be trivial
41 // to implement, for example it could be:
42 // .cfi_def_cfa <sp>, 0
43 // .cfi_same_value <rN>
44 // .cfi_same_value <rN-1>
45 // ...
46 // where <rN> are the callee-saved registers.
47 // - CFI instructions, which reset the unwind table state to the one
48 // created by the function prologue. These are
49 // .cfi_restore_state
50 // .cfi_remember_state
51 // In this case we also insert a `.cfi_remember_state` after the last CFI
52 // instruction in the function prologue.
53 //
54 // Known limitations:
55 // * the pass cannot handle an epilogue preceding the prologue in the basic
56 // block layout
57 // * the pass does not handle functions where SP is used as a frame pointer and
58 // SP adjustments up and down are done in different basic blocks (TODO)
59 //===----------------------------------------------------------------------===//
60 
61 #include "llvm/CodeGen/CFIFixup.h"
62 
65 #include "llvm/CodeGen/Passes.h"
69 #include "llvm/MC/MCAsmInfo.h"
70 #include "llvm/MC/MCDwarf.h"
72 
73 using namespace llvm;
74 
75 #define DEBUG_TYPE "cfi-fixup"
76 
77 char CFIFixup::ID = 0;
78 
80  "Insert CFI remember/restore state instructions", false, false)
81 FunctionPass *llvm::createCFIFixup() { return new CFIFixup(); }
82 
84  return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
86 }
87 
88 static bool containsPrologue(const MachineBasicBlock &MBB) {
90 }
91 
92 static bool containsEpilogue(const MachineBasicBlock &MBB) {
93  return llvm::any_of(llvm::reverse(MBB), [](const auto &MI) {
94  return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
96  });
97 }
98 
101  if (!TFL.enableCFIFixup(MF))
102  return false;
103 
104  const unsigned NumBlocks = MF.getNumBlockIDs();
105  if (NumBlocks < 2)
106  return false;
107 
108  struct BlockFlags {
109  bool Reachable : 1;
110  bool StrongNoFrameOnEntry : 1;
111  bool HasFrameOnEntry : 1;
112  bool HasFrameOnExit : 1;
113  };
114  SmallVector<BlockFlags, 32> BlockInfo(NumBlocks, {false, false, false, false});
115  BlockInfo[0].Reachable = true;
116  BlockInfo[0].StrongNoFrameOnEntry = true;
117 
118  // Compute the presence/absence of frame at each basic block.
119  MachineBasicBlock *PrologueBlock = nullptr;
121  for (MachineBasicBlock *MBB : RPOT) {
122  BlockFlags &Info = BlockInfo[MBB->getNumber()];
123 
124  // Set to true if the current block contains the prologue or the epilogue,
125  // respectively.
126  bool HasPrologue = false;
127  bool HasEpilogue = false;
128 
129  if (!PrologueBlock && !Info.HasFrameOnEntry && containsPrologue(*MBB)) {
130  PrologueBlock = MBB;
131  HasPrologue = true;
132  }
133 
134  if (Info.HasFrameOnEntry || HasPrologue)
135  HasEpilogue = containsEpilogue(*MBB);
136 
137  // If the function has a call frame at the entry of the current block or the
138  // current block contains the prologue, then the function has a call frame
139  // at the exit of the block, unless the block contains the epilogue.
140  Info.HasFrameOnExit = (Info.HasFrameOnEntry || HasPrologue) && !HasEpilogue;
141 
142  // Set the successors' state on entry.
143  for (MachineBasicBlock *Succ : MBB->successors()) {
144  BlockFlags &SuccInfo = BlockInfo[Succ->getNumber()];
145  SuccInfo.Reachable = true;
146  SuccInfo.StrongNoFrameOnEntry |=
147  Info.StrongNoFrameOnEntry && !HasPrologue;
148  SuccInfo.HasFrameOnEntry = Info.HasFrameOnExit;
149  }
150  }
151 
152  if (!PrologueBlock)
153  return false;
154 
155  // Walk the blocks of the function in "physical" order.
156  // Every block inherits the frame state (as recorded in the unwind tables)
157  // of the previous block. If the intended frame state is different, insert
158  // compensating CFI instructions.
159  const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
160  bool Change = false;
161  // `InsertPt` always points to the point in a preceding block where we have to
162  // insert a `.cfi_remember_state`, in the case that the current block needs a
163  // `.cfi_restore_state`.
164  MachineBasicBlock *InsertMBB = PrologueBlock;
165  MachineBasicBlock::iterator InsertPt = PrologueBlock->begin();
166  for (MachineInstr &MI : *PrologueBlock)
168  InsertPt = std::next(MI.getIterator());
169 
170  assert(InsertPt != PrologueBlock->begin() &&
171  "Inconsistent notion of \"prologue block\"");
172 
173  // No point starting before the prologue block.
174  // TODO: the unwind tables will still be incorrect if an epilogue physically
175  // preceeds the prologue.
176  MachineFunction::iterator CurrBB = std::next(PrologueBlock->getIterator());
177  bool HasFrame = BlockInfo[PrologueBlock->getNumber()].HasFrameOnExit;
178  while (CurrBB != MF.end()) {
179  const BlockFlags &Info = BlockInfo[CurrBB->getNumber()];
180  if (!Info.Reachable) {
181  ++CurrBB;
182  continue;
183  }
184 
185 #ifndef NDEBUG
186  if (!Info.StrongNoFrameOnEntry) {
187  for (auto *Pred : CurrBB->predecessors()) {
188  BlockFlags &PredInfo = BlockInfo[Pred->getNumber()];
189  assert((!PredInfo.Reachable ||
190  Info.HasFrameOnEntry == PredInfo.HasFrameOnExit) &&
191  "Inconsistent call frame state");
192  }
193  }
194 #endif
195  if (!Info.StrongNoFrameOnEntry && Info.HasFrameOnEntry && !HasFrame) {
196  // Reset to the "after prologue" state.
197 
198  // Insert a `.cfi_remember_state` into the last block known to have a
199  // stack frame.
200  unsigned CFIIndex =
202  BuildMI(*InsertMBB, InsertPt, DebugLoc(),
203  TII.get(TargetOpcode::CFI_INSTRUCTION))
204  .addCFIIndex(CFIIndex);
205  // Insert a `.cfi_restore_state` at the beginning of the current block.
206  CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestoreState(nullptr));
207  InsertPt = BuildMI(*CurrBB, CurrBB->begin(), DebugLoc(),
208  TII.get(TargetOpcode::CFI_INSTRUCTION))
209  .addCFIIndex(CFIIndex);
210  ++InsertPt;
211  InsertMBB = &*CurrBB;
212  Change = true;
213  } else if ((Info.StrongNoFrameOnEntry || !Info.HasFrameOnEntry) &&
214  HasFrame) {
215  // Reset to the state upon function entry.
216  TFL.resetCFIToInitialState(*CurrBB);
217  Change = true;
218  }
219 
220  HasFrame = Info.HasFrameOnExit;
221  ++CurrBB;
222  }
223 
224  return Change;
225 }
MCDwarf.h
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:108
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
TargetFrameLowering.h
llvm::TargetFrameLowering
Information about stack frame layout on the target.
Definition: TargetFrameLowering.h:43
llvm::TargetSubtargetInfo::getInstrInfo
virtual const TargetInstrInfo * getInstrInfo() const
Definition: TargetSubtargetInfo.h:95
llvm::MachineBasicBlock::instrs
instr_range instrs()
Definition: MachineBasicBlock.h:300
llvm::MachineInstrBuilder::addCFIIndex
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
Definition: MachineInstrBuilder.h:247
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::MachineFunction::end
iterator end()
Definition: MachineFunction.h:856
llvm::MachineFunction::getNumBlockIDs
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
Definition: MachineFunction.h:799
TargetInstrInfo.h
llvm::TargetFrameLowering::resetCFIToInitialState
virtual void resetCFIToInitialState(MachineBasicBlock &MBB) const
Emit CFI instructions that recreate the state of the unwind information upon fucntion entry.
Definition: TargetFrameLowering.h:232
llvm::MachineInstr::FrameDestroy
@ FrameDestroy
Definition: MachineInstr.h:86
llvm::CFIFixup
Definition: CFIFixup.h:21
containsEpilogue
static bool containsEpilogue(const MachineBasicBlock &MBB)
Definition: CFIFixup.cpp:92
llvm::TargetInstrInfo
TargetInstrInfo - Interface to description of machine instruction set.
Definition: TargetInstrInfo.h:98
TargetMachine.h
llvm::TargetFrameLowering::enableCFIFixup
virtual bool enableCFIFixup(MachineFunction &MF) const
Returns true if we may need to fix the unwind information for the function.
Definition: TargetFrameLoweringImpl.cpp:40
llvm::CFIFixup::runOnMachineFunction
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition: CFIFixup.cpp:99
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:125
llvm::MachineInstr::FrameSetup
@ FrameSetup
Definition: MachineInstr.h:84
llvm::MCCFIInstruction::createRestoreState
static MCCFIInstruction createRestoreState(MCSymbol *L)
.cfi_restore_state Restore the previously saved state.
Definition: MCDwarf.h:625
llvm::MachineFunction::begin
iterator begin()
Definition: MachineFunction.h:854
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:94
llvm::createCFIFixup
FunctionPass * createCFIFixup()
Creates CFI Fixup pass.
Passes.h
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:657
containsPrologue
static bool containsPrologue(const MachineBasicBlock &MBB)
Definition: CFIFixup.cpp:88
INITIALIZE_PASS
INITIALIZE_PASS(CFIFixup, "cfi-fixup", "Insert CFI remember/restore state instructions", false, false) FunctionPass *llvm
Definition: CFIFixup.cpp:79
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:66
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachineFunction
Definition: MachineFunction.h:257
llvm::MachineBasicBlock::getNumber
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Definition: MachineBasicBlock.h:1115
MCAsmInfo.h
llvm::any_of
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1716
llvm::MachineBasicBlock::successors
iterator_range< succ_iterator > successors()
Definition: MachineBasicBlock.h:392
TargetSubtargetInfo.h
llvm::MachineFunction::addFrameInst
unsigned addFrameInst(const MCCFIInstruction &Inst)
Definition: MachineFunction.cpp:310
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::TargetSubtargetInfo::getFrameLowering
virtual const TargetFrameLowering * getFrameLowering() const
Definition: TargetSubtargetInfo.h:96
llvm::ilist_iterator
Iterator for intrusive lists based on ilist_node.
Definition: ilist_iterator.h:57
CFIFixup.h
llvm::ReversePostOrderTraversal
Definition: PostOrderIterator.h:291
PostOrderIterator.h
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:357
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:305
SmallBitVector.h
llvm::reverse
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:485
llvm::MCCFIInstruction::createRememberState
static MCCFIInstruction createRememberState(MCSymbol *L)
.cfi_remember_state Save all current rules for all registers.
Definition: MCDwarf.h:620
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:308
llvm::CFIFixup::ID
static char ID
Definition: CFIFixup.h:23
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::MachineInstrBundleIterator< MachineInstr >
isPrologueCFIInstruction
static bool isPrologueCFIInstruction(const MachineInstr &MI)
Definition: CFIFixup.cpp:83