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