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/PostOrderIterator.h" 71 #include "llvm/ADT/SmallBitVector.h" 72 #include "llvm/CodeGen/Passes.h" 73 #include "llvm/CodeGen/TargetFrameLowering.h" 74 #include "llvm/CodeGen/TargetInstrInfo.h" 75 #include "llvm/CodeGen/TargetSubtargetInfo.h" 76 #include "llvm/MC/MCAsmInfo.h" 77 #include "llvm/MC/MCDwarf.h" 78 #include "llvm/Target/TargetMachine.h" 79 80 using namespace llvm; 81 82 #define DEBUG_TYPE "cfi-fixup" 83 84 char CFIFixup::ID = 0; 85 86 INITIALIZE_PASS(CFIFixup, "cfi-fixup", 87 "Insert CFI remember/restore state instructions", false, false) 88 FunctionPass *llvm::createCFIFixup() { return new CFIFixup(); } 89 90 static bool isPrologueCFIInstruction(const MachineInstr &MI) { 91 return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION && 92 MI.getFlag(MachineInstr::FrameSetup); 93 } 94 95 static bool containsEpilogue(const MachineBasicBlock &MBB) { 96 return llvm::any_of(llvm::reverse(MBB), [](const auto &MI) { 97 return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION && 98 MI.getFlag(MachineInstr::FrameDestroy); 99 }); 100 } 101 102 static MachineBasicBlock * 103 findPrologueEnd(MachineFunction &MF, MachineBasicBlock::iterator &PrologueEnd) { 104 // Even though we should theoretically traverse the blocks in post-order, we 105 // can't encode correctly cases where prologue blocks are not laid out in 106 // topological order. Then, assuming topological order, we can just traverse 107 // the function in reverse. 108 for (MachineBasicBlock &MBB : reverse(MF)) { 109 for (MachineInstr &MI : reverse(MBB.instrs())) { 110 if (!isPrologueCFIInstruction(MI)) 111 continue; 112 PrologueEnd = std::next(MI.getIterator()); 113 return &MBB; 114 } 115 } 116 return nullptr; 117 } 118 119 bool CFIFixup::runOnMachineFunction(MachineFunction &MF) { 120 const TargetFrameLowering &TFL = *MF.getSubtarget().getFrameLowering(); 121 if (!TFL.enableCFIFixup(MF)) 122 return false; 123 124 const unsigned NumBlocks = MF.getNumBlockIDs(); 125 if (NumBlocks < 2) 126 return false; 127 128 // Find the prologue and the point where we can issue the first 129 // `.cfi_remember_state`. 130 MachineBasicBlock::iterator PrologueEnd; 131 MachineBasicBlock *PrologueBlock = findPrologueEnd(MF, PrologueEnd); 132 if (PrologueBlock == nullptr) 133 return false; 134 135 struct BlockFlags { 136 bool Reachable : 1; 137 bool StrongNoFrameOnEntry : 1; 138 bool HasFrameOnEntry : 1; 139 bool HasFrameOnExit : 1; 140 }; 141 SmallVector<BlockFlags, 32> BlockInfo(NumBlocks, {false, false, false, false}); 142 BlockInfo[0].Reachable = true; 143 BlockInfo[0].StrongNoFrameOnEntry = true; 144 145 // Compute the presence/absence of frame at each basic block. 146 ReversePostOrderTraversal<MachineBasicBlock *> RPOT(&*MF.begin()); 147 for (MachineBasicBlock *MBB : RPOT) { 148 BlockFlags &Info = BlockInfo[MBB->getNumber()]; 149 150 // Set to true if the current block contains the prologue or the epilogue, 151 // respectively. 152 bool HasPrologue = MBB == PrologueBlock; 153 bool HasEpilogue = false; 154 155 if (Info.HasFrameOnEntry || HasPrologue) 156 HasEpilogue = containsEpilogue(*MBB); 157 158 // If the function has a call frame at the entry of the current block or the 159 // current block contains the prologue, then the function has a call frame 160 // at the exit of the block, unless the block contains the epilogue. 161 Info.HasFrameOnExit = (Info.HasFrameOnEntry || HasPrologue) && !HasEpilogue; 162 163 // Set the successors' state on entry. 164 for (MachineBasicBlock *Succ : MBB->successors()) { 165 BlockFlags &SuccInfo = BlockInfo[Succ->getNumber()]; 166 SuccInfo.Reachable = true; 167 SuccInfo.StrongNoFrameOnEntry |= 168 Info.StrongNoFrameOnEntry && !HasPrologue; 169 SuccInfo.HasFrameOnEntry = Info.HasFrameOnExit; 170 } 171 } 172 173 // Walk the blocks of the function in "physical" order. 174 // Every block inherits the frame state (as recorded in the unwind tables) 175 // of the previous block. If the intended frame state is different, insert 176 // compensating CFI instructions. 177 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 178 bool Change = false; 179 // `InsertPt` always points to the point in a preceding block where we have to 180 // insert a `.cfi_remember_state`, in the case that the current block needs a 181 // `.cfi_restore_state`. 182 MachineBasicBlock *InsertMBB = PrologueBlock; 183 MachineBasicBlock::iterator InsertPt = PrologueEnd; 184 185 assert(InsertPt != PrologueBlock->begin() && 186 "Inconsistent notion of \"prologue block\""); 187 188 // No point starting before the prologue block. 189 // TODO: the unwind tables will still be incorrect if an epilogue physically 190 // preceeds the prologue. 191 MachineFunction::iterator CurrBB = std::next(PrologueBlock->getIterator()); 192 bool HasFrame = BlockInfo[PrologueBlock->getNumber()].HasFrameOnExit; 193 while (CurrBB != MF.end()) { 194 const BlockFlags &Info = BlockInfo[CurrBB->getNumber()]; 195 if (!Info.Reachable) { 196 ++CurrBB; 197 continue; 198 } 199 200 #ifndef NDEBUG 201 if (!Info.StrongNoFrameOnEntry) { 202 for (auto *Pred : CurrBB->predecessors()) { 203 BlockFlags &PredInfo = BlockInfo[Pred->getNumber()]; 204 assert((!PredInfo.Reachable || 205 Info.HasFrameOnEntry == PredInfo.HasFrameOnExit) && 206 "Inconsistent call frame state"); 207 } 208 } 209 #endif 210 if (!Info.StrongNoFrameOnEntry && Info.HasFrameOnEntry && !HasFrame) { 211 // Reset to the "after prologue" state. 212 213 // Insert a `.cfi_remember_state` into the last block known to have a 214 // stack frame. 215 unsigned CFIIndex = 216 MF.addFrameInst(MCCFIInstruction::createRememberState(nullptr)); 217 BuildMI(*InsertMBB, InsertPt, DebugLoc(), 218 TII.get(TargetOpcode::CFI_INSTRUCTION)) 219 .addCFIIndex(CFIIndex); 220 // Insert a `.cfi_restore_state` at the beginning of the current block. 221 CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestoreState(nullptr)); 222 InsertPt = BuildMI(*CurrBB, CurrBB->begin(), DebugLoc(), 223 TII.get(TargetOpcode::CFI_INSTRUCTION)) 224 .addCFIIndex(CFIIndex); 225 ++InsertPt; 226 InsertMBB = &*CurrBB; 227 Change = true; 228 } else if ((Info.StrongNoFrameOnEntry || !Info.HasFrameOnEntry) && 229 HasFrame) { 230 // Reset to the state upon function entry. 231 TFL.resetCFIToInitialState(*CurrBB); 232 Change = true; 233 } 234 235 HasFrame = Info.HasFrameOnExit; 236 ++CurrBB; 237 } 238 239 return Change; 240 } 241