xref: /llvm-project/llvm/lib/CodeGen/CFIFixup.cpp (revision 07137ce3e1d7b9f18f579a9a2a4f47ec4270f156)
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 
68 #include "llvm/CodeGen/CFIFixup.h"
69 
70 #include "llvm/ADT/DenseMap.h"
71 #include "llvm/ADT/PostOrderIterator.h"
72 #include "llvm/ADT/STLExtras.h"
73 #include "llvm/ADT/iterator_range.h"
74 #include "llvm/CodeGen/MachineBasicBlock.h"
75 #include "llvm/CodeGen/MachineFunction.h"
76 #include "llvm/CodeGen/Passes.h"
77 #include "llvm/CodeGen/TargetFrameLowering.h"
78 #include "llvm/CodeGen/TargetInstrInfo.h"
79 #include "llvm/CodeGen/TargetSubtargetInfo.h"
80 #include "llvm/MC/MCAsmInfo.h"
81 #include "llvm/MC/MCDwarf.h"
82 #include "llvm/Target/TargetMachine.h"
83 
84 #include <iterator>
85 
86 using namespace llvm;
87 
88 #define DEBUG_TYPE "cfi-fixup"
89 
90 char CFIFixup::ID = 0;
91 
92 INITIALIZE_PASS(CFIFixup, "cfi-fixup",
93                 "Insert CFI remember/restore state instructions", false, false)
94 FunctionPass *llvm::createCFIFixup() { return new CFIFixup(); }
95 
96 static bool isPrologueCFIInstruction(const MachineInstr &MI) {
97   return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
98          MI.getFlag(MachineInstr::FrameSetup);
99 }
100 
101 static bool containsEpilogue(const MachineBasicBlock &MBB) {
102   return llvm::any_of(llvm::reverse(MBB), [](const auto &MI) {
103     return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
104            MI.getFlag(MachineInstr::FrameDestroy);
105   });
106 }
107 
108 static MachineBasicBlock *
109 findPrologueEnd(MachineFunction &MF, MachineBasicBlock::iterator &PrologueEnd) {
110   // Even though we should theoretically traverse the blocks in post-order, we
111   // can't encode correctly cases where prologue blocks are not laid out in
112   // topological order. Then, assuming topological order, we can just traverse
113   // the function in reverse.
114   for (MachineBasicBlock &MBB : reverse(MF)) {
115     for (MachineInstr &MI : reverse(MBB.instrs())) {
116       if (!isPrologueCFIInstruction(MI))
117         continue;
118       PrologueEnd = std::next(MI.getIterator());
119       return &MBB;
120     }
121   }
122   return nullptr;
123 }
124 
125 // Represents the point within a basic block where we can insert an instruction.
126 // Note that we need the MachineBasicBlock* as well as the iterator since the
127 // iterator can point to the end of the block. Instructions are inserted
128 // *before* the iterator.
129 struct InsertionPoint {
130   MachineBasicBlock *MBB = nullptr;
131   MachineBasicBlock::iterator Iterator;
132 };
133 
134 // Inserts a `.cfi_remember_state` instruction before PrologueEnd and a
135 // `.cfi_restore_state` instruction before DstInsertPt. Returns an iterator
136 // to the first instruction after the inserted `.cfi_restore_state` instruction.
137 static InsertionPoint
138 insertRememberRestorePair(const InsertionPoint &RememberInsertPt,
139                           const InsertionPoint &RestoreInsertPt) {
140   MachineFunction &MF = *RememberInsertPt.MBB->getParent();
141   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
142 
143   // Insert the `.cfi_remember_state` instruction.
144   unsigned CFIIndex =
145       MF.addFrameInst(MCCFIInstruction::createRememberState(nullptr));
146   BuildMI(*RememberInsertPt.MBB, RememberInsertPt.Iterator, DebugLoc(),
147           TII.get(TargetOpcode::CFI_INSTRUCTION))
148       .addCFIIndex(CFIIndex);
149 
150   // Insert the `.cfi_restore_state` instruction.
151   CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestoreState(nullptr));
152 
153   return {RestoreInsertPt.MBB,
154           std::next(BuildMI(*RestoreInsertPt.MBB, RestoreInsertPt.Iterator,
155                             DebugLoc(), TII.get(TargetOpcode::CFI_INSTRUCTION))
156                         .addCFIIndex(CFIIndex)
157                         ->getIterator())};
158 }
159 
160 // Copies all CFI instructions before PrologueEnd and inserts them before
161 // DstInsertPt. Returns the iterator to the first instruction after the
162 // inserted instructions.
163 static InsertionPoint cloneCfiPrologue(const InsertionPoint &PrologueEnd,
164                                        const InsertionPoint &DstInsertPt) {
165   MachineFunction &MF = *DstInsertPt.MBB->getParent();
166 
167   auto cloneCfiInstructions = [&](MachineBasicBlock::iterator Begin,
168                                   MachineBasicBlock::iterator End) {
169     auto ToClone = map_range(
170         make_filter_range(make_range(Begin, End), isPrologueCFIInstruction),
171         [&](const MachineInstr &MI) { return MF.CloneMachineInstr(&MI); });
172     DstInsertPt.MBB->insert(DstInsertPt.Iterator, ToClone.begin(),
173                             ToClone.end());
174   };
175 
176   // Clone all CFI instructions from previous blocks.
177   for (auto &MBB : make_range(MF.begin(), PrologueEnd.MBB->getIterator()))
178     cloneCfiInstructions(MBB.begin(), MBB.end());
179   // Clone all CFI instructions from the final prologue block.
180   cloneCfiInstructions(PrologueEnd.MBB->begin(), PrologueEnd.Iterator);
181   return DstInsertPt;
182 }
183 
184 bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
185   const TargetFrameLowering &TFL = *MF.getSubtarget().getFrameLowering();
186   if (!TFL.enableCFIFixup(MF))
187     return false;
188 
189   const unsigned NumBlocks = MF.getNumBlockIDs();
190   if (NumBlocks < 2)
191     return false;
192 
193   // Find the prologue and the point where we can issue the first
194   // `.cfi_remember_state`.
195   MachineBasicBlock::iterator PrologueEnd;
196   MachineBasicBlock *PrologueBlock = findPrologueEnd(MF, PrologueEnd);
197   if (PrologueBlock == nullptr)
198     return false;
199 
200   struct BlockFlags {
201     bool Reachable : 1;
202     bool StrongNoFrameOnEntry : 1;
203     bool HasFrameOnEntry : 1;
204     bool HasFrameOnExit : 1;
205   };
206   SmallVector<BlockFlags, 32> BlockInfo(NumBlocks,
207                                         {false, false, false, false});
208   BlockInfo[0].Reachable = true;
209   BlockInfo[0].StrongNoFrameOnEntry = true;
210 
211   // Compute the presence/absence of frame at each basic block.
212   ReversePostOrderTraversal<MachineBasicBlock *> RPOT(&*MF.begin());
213   for (MachineBasicBlock *MBB : RPOT) {
214     BlockFlags &Info = BlockInfo[MBB->getNumber()];
215 
216     // Set to true if the current block contains the prologue or the epilogue,
217     // respectively.
218     bool HasPrologue = MBB == PrologueBlock;
219     bool HasEpilogue = false;
220 
221     if (Info.HasFrameOnEntry || HasPrologue)
222       HasEpilogue = containsEpilogue(*MBB);
223 
224     // If the function has a call frame at the entry of the current block or the
225     // current block contains the prologue, then the function has a call frame
226     // at the exit of the block, unless the block contains the epilogue.
227     Info.HasFrameOnExit = (Info.HasFrameOnEntry || HasPrologue) && !HasEpilogue;
228 
229     // Set the successors' state on entry.
230     for (MachineBasicBlock *Succ : MBB->successors()) {
231       BlockFlags &SuccInfo = BlockInfo[Succ->getNumber()];
232       SuccInfo.Reachable = true;
233       SuccInfo.StrongNoFrameOnEntry |=
234           Info.StrongNoFrameOnEntry && !HasPrologue;
235       SuccInfo.HasFrameOnEntry = Info.HasFrameOnExit;
236     }
237   }
238 
239   // Walk the blocks of the function in "physical" order.
240   // Every block inherits the frame state (as recorded in the unwind tables)
241   // of the previous block. If the intended frame state is different, insert
242   // compensating CFI instructions.
243   bool Change = false;
244   // `InsertPt[sectionID]` always points to the point in a preceding block where
245   // we have to insert a `.cfi_remember_state`, in the case that the current
246   // block needs a `.cfi_restore_state`.
247   SmallDenseMap<MBBSectionID, InsertionPoint> InsertionPts;
248   InsertionPts[PrologueBlock->getSectionID()] = {PrologueBlock, PrologueEnd};
249 
250   assert(PrologueEnd != PrologueBlock->begin() &&
251          "Inconsistent notion of \"prologue block\"");
252 
253   // No point starting before the prologue block.
254   // TODO: the unwind tables will still be incorrect if an epilogue physically
255   // preceeds the prologue.
256   MachineFunction::iterator CurrBB = std::next(PrologueBlock->getIterator());
257   bool HasFrame = BlockInfo[PrologueBlock->getNumber()].HasFrameOnExit;
258   while (CurrBB != MF.end()) {
259     const BlockFlags &Info = BlockInfo[CurrBB->getNumber()];
260     if (!Info.Reachable) {
261       ++CurrBB;
262       continue;
263     }
264 
265 #ifndef NDEBUG
266     if (!Info.StrongNoFrameOnEntry) {
267       for (auto *Pred : CurrBB->predecessors()) {
268         BlockFlags &PredInfo = BlockInfo[Pred->getNumber()];
269         assert((!PredInfo.Reachable ||
270                 Info.HasFrameOnEntry == PredInfo.HasFrameOnExit) &&
271                "Inconsistent call frame state");
272       }
273     }
274 #endif
275 
276     // If the block is the first block in its section, then it doesn't have a
277     // frame on entry.
278     HasFrame &= !CurrBB->isBeginSection();
279     if (!Info.StrongNoFrameOnEntry && Info.HasFrameOnEntry && !HasFrame) {
280       // Reset to the "after prologue" state.
281 
282       InsertionPoint &InsertPt = InsertionPts[CurrBB->getSectionID()];
283       if (InsertPt.MBB == nullptr) {
284         // CurBB is the first block in its section, so there is no "after
285         // prologue" state. Clone the CFI instructions from the prologue block
286         // to create it.
287         InsertPt = cloneCfiPrologue({PrologueBlock, PrologueEnd},
288                                     {&*CurrBB, CurrBB->begin()});
289       } else {
290         // There's an earlier block known to have a stack frame. Insert a
291         // `.cfi_remember_state` instruction into that block and a
292         // `.cfi_restore_state` instruction at the beginning of the current
293         // block.
294         InsertPt =
295             insertRememberRestorePair(InsertPt, {&*CurrBB, CurrBB->begin()});
296       }
297       Change = true;
298     } else if ((Info.StrongNoFrameOnEntry || !Info.HasFrameOnEntry) &&
299                HasFrame) {
300       // Reset to the state upon function entry.
301       TFL.resetCFIToInitialState(*CurrBB);
302       Change = true;
303     }
304 
305     HasFrame = Info.HasFrameOnExit;
306     ++CurrBB;
307   }
308 
309   return Change;
310 }
311