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 63 #include "llvm/ADT/PostOrderIterator.h" 64 #include "llvm/ADT/SmallBitVector.h" 65 #include "llvm/CodeGen/Passes.h" 66 #include "llvm/CodeGen/TargetFrameLowering.h" 67 #include "llvm/CodeGen/TargetInstrInfo.h" 68 #include "llvm/CodeGen/TargetSubtargetInfo.h" 69 #include "llvm/MC/MCAsmInfo.h" 70 #include "llvm/MC/MCDwarf.h" 71 #include "llvm/Target/TargetMachine.h" 72 73 using namespace llvm; 74 75 #define DEBUG_TYPE "cfi-fixup" 76 77 char CFIFixup::ID = 0; 78 79 INITIALIZE_PASS(CFIFixup, "cfi-fixup", 80 "Insert CFI remember/restore state instructions", false, false) 81 FunctionPass *llvm::createCFIFixup() { return new CFIFixup(); } 82 83 static bool isPrologueCFIInstruction(const MachineInstr &MI) { 84 return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION && 85 MI.getFlag(MachineInstr::FrameSetup); 86 } 87 88 static bool containsPrologue(const MachineBasicBlock &MBB) { 89 return llvm::any_of(MBB.instrs(), isPrologueCFIInstruction); 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 && 95 MI.getFlag(MachineInstr::FrameDestroy); 96 }); 97 } 98 99 bool CFIFixup::runOnMachineFunction(MachineFunction &MF) { 100 const TargetFrameLowering &TFL = *MF.getSubtarget().getFrameLowering(); 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; 120 ReversePostOrderTraversal<MachineBasicBlock *> RPOT(&*MF.begin()); 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) 167 if (isPrologueCFIInstruction(MI)) 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 = 201 MF.addFrameInst(MCCFIInstruction::createRememberState(nullptr)); 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 } 226