LLVM 23.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) and has certain preconditions about
14// placement of CFI instructions:
15// * For any two CFI instructions of the function prologue one dominates
16// and is post-dominated by the other.
17// * The function possibly contains multiple epilogue blocks, where each
18// epilogue block is complete and self-contained, i.e. CSR restore
19// instructions (and the corresponding CFI instructions)
20// are not split across two or more blocks.
21// * CFI instructions are not contained in any loops.
22
23// Thus, during execution, at the beginning and at the end of each basic block,
24// following the prologue, the function can be in one of two states:
25// - "has a call frame", if the function has executed the prologue, and
26// has not executed any epilogue
27// - "does not have a call frame", if the function has not executed the
28// prologue, or has executed an epilogue
29// which can be computed by a single RPO traversal.
30
31// The location of the prologue is determined by finding the first block in the
32// reverse traversal which contains CFI instructions.
33
34// In order to accommodate backends which do not generate unwind info in
35// epilogues we compute an additional property "strong no call frame on entry",
36// which is set for the entry point of the function and for every block
37// reachable from the entry along a path that does not execute the prologue. If
38// this property holds, it takes precedence over the "has a call frame"
39// property.
40
41// From the point of view of the unwind tables, the "has/does not have call
42// frame" state at beginning of each block is determined by the state at the end
43// of the previous block, in layout order. Where these states differ, we insert
44// compensating CFI instructions, which come in two flavours:
45
46// - CFI instructions, which reset the unwind table state to the initial one.
47// This is done by a target specific hook and is expected to be trivial
48// to implement, for example it could be:
49// .cfi_def_cfa <sp>, 0
50// .cfi_same_value <rN>
51// .cfi_same_value <rN-1>
52// ...
53// where <rN> are the callee-saved registers.
54// - CFI instructions, which reset the unwind table state to the one
55// created by the function prologue. These are
56// .cfi_restore_state
57// .cfi_remember_state
58// In this case we also insert a `.cfi_remember_state` after the last CFI
59// instruction in the function prologue.
60//
61// Known limitations:
62// * the pass cannot handle an epilogue preceding the prologue in the basic
63// block layout
64// * the pass does not handle functions where SP is used as a frame pointer and
65// SP adjustments up and down are done in different basic blocks (TODO)
66//===----------------------------------------------------------------------===//
67
69
70#include "llvm/ADT/DenseMap.h"
72#include "llvm/ADT/STLExtras.h"
77#include "llvm/CodeGen/Passes.h"
81#include "llvm/MC/MCAsmInfo.h"
82#include "llvm/MC/MCDwarf.h"
84
85#include <iterator>
86
87using namespace llvm;
88
89#define DEBUG_TYPE "cfi-fixup"
90
91char CFIFixupLegacy::ID = 0;
92
94 "Insert CFI remember/restore state instructions", false, false)
96
98 return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
100}
101
103 return llvm::any_of(llvm::reverse(MBB), [](const auto &MI) {
104 return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
106 });
107}
108
109static MachineBasicBlock *
111 // Even though we should theoretically traverse the blocks in post-order, we
112 // can't encode correctly cases where prologue blocks are not laid out in
113 // topological order. Then, assuming topological order, we can just traverse
114 // the function in reverse.
115 for (MachineBasicBlock &MBB : reverse(MF)) {
116 for (MachineInstr &MI : reverse(MBB.instrs())) {
118 continue;
119 PrologueEnd = std::next(MI.getIterator());
120 return &MBB;
121 }
122 }
123 return nullptr;
124}
125
126// Represents a basic block's relationship to the call frame. This metadata
127// reflects what the state *should* be, which may differ from the actual state
128// after final machine basic block layout.
138
139// Most functions will have <= 32 basic blocks.
141
142// Computes the frame information for each block in the function. Frame info
143// for a block is inferred from its predecessors.
144static BlockFlagsVector
146 const MachineBasicBlock *PrologueBlock) {
147 BlockFlagsVector BlockInfo(MF.getNumBlockIDs());
148 BlockInfo[0].Reachable = true;
149 BlockInfo[0].StrongNoFrameOnEntry = true;
150
151 // Compute the presence/absence of frame at each basic block.
153 for (const MachineBasicBlock *MBB : RPOT) {
154 BlockFlags &Info = BlockInfo[MBB->getNumber()];
155
156 // Set to true if the current block contains the prologue or the epilogue,
157 // respectively.
158 bool HasPrologue = MBB == PrologueBlock;
159 bool HasEpilogue = false;
160
161 if (Info.HasFrameOnEntry || HasPrologue)
162 HasEpilogue = containsEpilogue(*MBB);
163
164 // If the function has a call frame at the entry of the current block or the
165 // current block contains the prologue, then the function has a call frame
166 // at the exit of the block, unless the block contains the epilogue.
167 Info.HasFrameOnExit = (Info.HasFrameOnEntry || HasPrologue) && !HasEpilogue;
168
169 // Set the successors' state on entry.
170 for (MachineBasicBlock *Succ : MBB->successors()) {
171 BlockFlags &SuccInfo = BlockInfo[Succ->getNumber()];
172 SuccInfo.Reachable = true;
173 SuccInfo.StrongNoFrameOnEntry |=
174 Info.StrongNoFrameOnEntry && !HasPrologue;
175 SuccInfo.HasFrameOnEntry = Info.HasFrameOnExit;
176 }
177 }
178
179 return BlockInfo;
180}
181
182// Represents the point within a basic block where we can insert an instruction.
183// Note that we need the MachineBasicBlock* as well as the iterator since the
184// iterator can point to the end of the block. Instructions are inserted
185// *before* the iterator.
190
191// Inserts a `.cfi_remember_state` instruction before PrologueEnd and a
192// `.cfi_restore_state` instruction before DstInsertPt. Returns an iterator
193// to the first instruction after the inserted `.cfi_restore_state` instruction.
194static InsertionPoint
196 const InsertionPoint &RestoreInsertPt) {
197 MachineFunction &MF = *RememberInsertPt.MBB->getParent();
199
200 // Insert the `.cfi_remember_state` instruction.
201 unsigned CFIIndex =
203 BuildMI(*RememberInsertPt.MBB, RememberInsertPt.Iterator, DebugLoc(),
204 TII.get(TargetOpcode::CFI_INSTRUCTION))
205 .addCFIIndex(CFIIndex);
206
207 // Insert the `.cfi_restore_state` instruction.
209
210 return {RestoreInsertPt.MBB,
211 std::next(BuildMI(*RestoreInsertPt.MBB, RestoreInsertPt.Iterator,
212 DebugLoc(), TII.get(TargetOpcode::CFI_INSTRUCTION))
213 .addCFIIndex(CFIIndex)
214 ->getIterator())};
215}
216
217// Copies all CFI instructions before PrologueEnd and inserts them before
218// DstInsertPt. Returns the iterator to the first instruction after the
219// inserted instructions.
221 const InsertionPoint &DstInsertPt) {
222 MachineFunction &MF = *DstInsertPt.MBB->getParent();
223
224 auto cloneCfiInstructions = [&](MachineBasicBlock::iterator Begin,
226 auto ToClone = map_range(
228 [&](const MachineInstr &MI) { return MF.CloneMachineInstr(&MI); });
229 DstInsertPt.MBB->insert(DstInsertPt.Iterator, ToClone.begin(),
230 ToClone.end());
231 };
232
233 // Clone all CFI instructions from previous blocks.
234 for (auto &MBB : make_range(MF.begin(), PrologueEnd.MBB->getIterator()))
235 cloneCfiInstructions(MBB.begin(), MBB.end());
236 // Clone all CFI instructions from the final prologue block.
237 cloneCfiInstructions(PrologueEnd.MBB->begin(), PrologueEnd.Iterator);
238 return DstInsertPt;
239}
240
241// Fixes up the CFI instructions in a basic block to be consistent with the
242// intended frame state, adding or removing CFI instructions as necessary.
243// Returns true if a change was made and false otherwise.
244static bool
247 const InsertionPoint &Prologue) {
248 const MachineFunction &MF = *CurrBB.getParent();
250 const BlockFlags &Info = BlockInfo[CurrBB.getNumber()];
251
252 if (!Info.Reachable)
253 return false;
254
255 // If we don't need to perform full CFI fix up, we only need to fix up the
256 // first basic block in the section.
257 if (!TFL.enableFullCFIFixup(MF) && !CurrBB.isBeginSection())
258 return false;
259
260 // If the previous block and the current block are in the same section,
261 // the frame info will propagate from the previous block to the current one.
262 const BlockFlags &PrevInfo =
263 BlockInfo[std::prev(CurrBB.getIterator())->getNumber()];
264 bool HasFrame = PrevInfo.HasFrameOnExit && !CurrBB.isBeginSection();
265 bool NeedsFrame = Info.HasFrameOnEntry && !Info.StrongNoFrameOnEntry;
266
267#ifndef NDEBUG
268 if (!Info.StrongNoFrameOnEntry) {
269 for (auto *Pred : CurrBB.predecessors()) {
270 const BlockFlags &PredInfo = BlockInfo[Pred->getNumber()];
271 assert((!PredInfo.Reachable ||
272 Info.HasFrameOnEntry == PredInfo.HasFrameOnExit) &&
273 "Inconsistent call frame state");
274 }
275 }
276#endif
277
278 if (HasFrame == NeedsFrame)
279 return false;
280
281 if (!NeedsFrame) {
282 // Reset to the state upon function entry.
283 TFL.resetCFIToInitialState(CurrBB);
284 return true;
285 }
286
287 // Reset to the "after prologue" state.
288 InsertionPoint &InsertPt = InsertionPts[CurrBB.getSectionID()];
289 if (InsertPt.MBB == nullptr) {
290 // CurBB is the first block in its section, so there is no "after
291 // prologue" state. Clone the CFI instructions from the prologue block
292 // to create it.
293 InsertPt = cloneCfiPrologue(Prologue, {&CurrBB, CurrBB.begin()});
294 } else {
295 // There's an earlier block known to have a stack frame. Insert a
296 // `.cfi_remember_state` instruction into that block and a
297 // `.cfi_restore_state` instruction at the beginning of the current
298 // block.
299 InsertPt = insertRememberRestorePair(InsertPt, {&CurrBB, CurrBB.begin()});
300 }
301 return true;
302}
303
304static bool runImpl(MachineFunction &MF) {
306 return false;
307
308 if (MF.getNumBlockIDs() < 2)
309 return false;
310
311 // Find the prologue and the point where we can issue the first
312 // `.cfi_remember_state`.
313 MachineBasicBlock::iterator PrologueEnd;
314 MachineBasicBlock *PrologueBlock = findPrologueEnd(MF, PrologueEnd);
315 if (PrologueBlock == nullptr)
316 return false;
317
318 BlockFlagsVector BlockInfo = computeBlockInfo(MF, PrologueBlock);
319
320 // Walk the blocks of the function in "physical" order.
321 // Every block inherits the frame state (as recorded in the unwind tables)
322 // of the previous block. If the intended frame state is different, insert
323 // compensating CFI instructions.
324 bool Change = false;
325 // `InsertPt[sectionID]` always points to the point in a preceding block where
326 // we have to insert a `.cfi_remember_state`, in the case that the current
327 // block needs a `.cfi_restore_state`.
329 InsertionPts[PrologueBlock->getSectionID()] = {PrologueBlock, PrologueEnd};
330
331 assert(PrologueEnd != PrologueBlock->begin() &&
332 "Inconsistent notion of \"prologue block\"");
333
334 // No point starting before the prologue block.
335 // TODO: the unwind tables will still be incorrect if an epilogue physically
336 // preceeds the prologue.
337 for (MachineBasicBlock &MBB :
338 make_range(std::next(PrologueBlock->getIterator()), MF.end())) {
339 Change |=
340 fixupBlock(MBB, BlockInfo, InsertionPts, {PrologueBlock, PrologueEnd});
341 }
342
343 return Change;
344}
345
351
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static InsertionPoint insertRememberRestorePair(const InsertionPoint &RememberInsertPt, const InsertionPoint &RestoreInsertPt)
Definition CFIFixup.cpp:195
static bool fixupBlock(MachineBasicBlock &CurrBB, const BlockFlagsVector &BlockInfo, SmallDenseMap< MBBSectionID, InsertionPoint > &InsertionPts, const InsertionPoint &Prologue)
Definition CFIFixup.cpp:245
static InsertionPoint cloneCfiPrologue(const InsertionPoint &PrologueEnd, const InsertionPoint &DstInsertPt)
Definition CFIFixup.cpp:220
static bool isPrologueCFIInstruction(const MachineInstr &MI)
Definition CFIFixup.cpp:97
static BlockFlagsVector computeBlockInfo(const MachineFunction &MF, const MachineBasicBlock *PrologueBlock)
Definition CFIFixup.cpp:145
static MachineBasicBlock * findPrologueEnd(MachineFunction &MF, MachineBasicBlock::iterator &PrologueEnd)
Definition CFIFixup.cpp:110
static bool containsEpilogue(const MachineBasicBlock &MBB)
Definition CFIFixup.cpp:102
SmallVector< BlockFlags, 32 > BlockFlagsVector
Definition CFIFixup.cpp:140
static bool runImpl(MachineFunction &MF)
Definition CFIFixup.cpp:304
Contains definition of the base CFIFixup pass.
This file defines the DenseMap class.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
static char ID
Definition CFIFixup.h:24
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
Definition CFIFixup.cpp:352
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Definition CFIFixup.cpp:346
A debug info location.
Definition DebugLoc.h:124
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
static MCCFIInstruction createRememberState(MCSymbol *L, SMLoc Loc={})
.cfi_remember_state Save all current rules for all registers.
Definition MCDwarf.h:716
static MCCFIInstruction createRestoreState(MCSymbol *L, SMLoc Loc={})
.cfi_restore_state Restore the previously saved state.
Definition MCDwarf.h:721
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
MBBSectionID getSectionID() const
Returns the section ID of this basic block.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
bool isBeginSection() const
Returns true if this block begins any section.
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
Representation of each machine instruction.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Information about stack frame layout on the target.
virtual bool enableFullCFIFixup(const MachineFunction &MF) const
enableFullCFIFixup - Returns true if we may need to fix the unwind information such that it is accura...
virtual void resetCFIToInitialState(MachineBasicBlock &MBB) const
Emit CFI instructions that recreate the state of the unwind information upon function entry.
virtual bool enableCFIFixup(const MachineFunction &MF) const
Returns true if we may need to fix the unwind information for the function.
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
self_iterator getIterator()
Definition ilist_node.h:123
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
Definition STLExtras.h:365
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:1745
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:551
LLVM_ABI FunctionPass * createCFIFixupLegacy()
Creates CFI Fixup pass.
bool HasFrameOnEntry
Definition CFIFixup.cpp:132
bool HasFrameOnExit
Definition CFIFixup.cpp:133
bool StrongNoFrameOnEntry
Definition CFIFixup.cpp:131
bool Reachable
Definition CFIFixup.cpp:130
MachineBasicBlock::iterator Iterator
Definition CFIFixup.cpp:188
MachineBasicBlock * MBB
Definition CFIFixup.cpp:187