1 //===------ CFIFixup.cpp - Insert CFI remember/restore instructions -------===//
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
7 //===----------------------------------------------------------------------===//
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.
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.
31 // The location of the prologue is determined by finding the first block in the
32 // reverse traversal which contains CFI instructions.
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"
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:
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>
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
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.
62 // * the pass cannot handle an epilogue preceding the prologue in the basic
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 //===----------------------------------------------------------------------===//
68 #include "llvm/CodeGen/CFIFixup.h"
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"
82 #define DEBUG_TYPE "cfi-fixup"
84 char CFIFixup::ID
= 0;
86 INITIALIZE_PASS(CFIFixup
, "cfi-fixup",
87 "Insert CFI remember/restore state instructions", false, false)
88 FunctionPass
*llvm::createCFIFixup() { return new CFIFixup(); }
90 static bool isPrologueCFIInstruction(const MachineInstr
&MI
) {
91 return MI
.getOpcode() == TargetOpcode::CFI_INSTRUCTION
&&
92 MI
.getFlag(MachineInstr::FrameSetup
);
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
);
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
))
112 PrologueEnd
= std::next(MI
.getIterator());
119 bool CFIFixup::runOnMachineFunction(MachineFunction
&MF
) {
120 const TargetFrameLowering
&TFL
= *MF
.getSubtarget().getFrameLowering();
121 if (!TFL
.enableCFIFixup(MF
))
124 const unsigned NumBlocks
= MF
.getNumBlockIDs();
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)
137 bool StrongNoFrameOnEntry
: 1;
138 bool HasFrameOnEntry
: 1;
139 bool HasFrameOnExit
: 1;
141 SmallVector
<BlockFlags
, 32> BlockInfo(NumBlocks
, {false, false, false, false});
142 BlockInfo
[0].Reachable
= true;
143 BlockInfo
[0].StrongNoFrameOnEntry
= true;
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()];
150 // Set to true if the current block contains the prologue or the epilogue,
152 bool HasPrologue
= MBB
== PrologueBlock
;
153 bool HasEpilogue
= false;
155 if (Info
.HasFrameOnEntry
|| HasPrologue
)
156 HasEpilogue
= containsEpilogue(*MBB
);
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
;
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
;
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();
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
;
185 assert(InsertPt
!= PrologueBlock
->begin() &&
186 "Inconsistent notion of \"prologue block\"");
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
) {
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");
210 if (!Info
.StrongNoFrameOnEntry
&& Info
.HasFrameOnEntry
&& !HasFrame
) {
211 // Reset to the "after prologue" state.
213 // Insert a `.cfi_remember_state` into the last block known to have a
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
);
226 InsertMBB
= &*CurrBB
;
228 } else if ((Info
.StrongNoFrameOnEntry
|| !Info
.HasFrameOnEntry
) &&
230 // Reset to the state upon function entry.
231 TFL
.resetCFIToInitialState(*CurrBB
);
235 HasFrame
= Info
.HasFrameOnExit
;