xref: /llvm-project/llvm/lib/CodeGen/CFIFixup.cpp (revision 07137ce3e1d7b9f18f579a9a2a4f47ec4270f156)
1b4ad28daSMomchil Velikov //===------ CFIFixup.cpp - Insert CFI remember/restore instructions -------===//
2b4ad28daSMomchil Velikov //
3b4ad28daSMomchil Velikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b4ad28daSMomchil Velikov // See https://llvm.org/LICENSE.txt for license information.
5b4ad28daSMomchil Velikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b4ad28daSMomchil Velikov //
7b4ad28daSMomchil Velikov //===----------------------------------------------------------------------===//
8b4ad28daSMomchil Velikov //
9b4ad28daSMomchil Velikov 
10b4ad28daSMomchil Velikov // This pass inserts the necessary  instructions to adjust for the inconsistency
11b4ad28daSMomchil Velikov // of the call-frame information caused by final machine basic block layout.
12b4ad28daSMomchil Velikov // The pass relies in constraints LLVM imposes on the placement of
1333374c44SMomchil Velikov // save/restore points (cf. ShrinkWrap) and has certain preconditions about
1433374c44SMomchil Velikov // placement of CFI instructions:
1533374c44SMomchil Velikov // * For any two CFI instructions of the function prologue one dominates
1633374c44SMomchil Velikov //   and is post-dominated by the other.
1733374c44SMomchil Velikov // * The function possibly contains multiple epilogue blocks, where each
1833374c44SMomchil Velikov //   epilogue block is complete and self-contained, i.e. CSR restore
1933374c44SMomchil Velikov //   instructions (and the corresponding CFI instructions)
2033374c44SMomchil Velikov //   are not split across two or more blocks.
2133374c44SMomchil Velikov // * CFI instructions are not contained in any loops.
2233374c44SMomchil Velikov 
2333374c44SMomchil Velikov // Thus, during execution, at the beginning and at the end of each basic block,
2433374c44SMomchil Velikov // following the prologue, the function can be in one of two states:
25b4ad28daSMomchil Velikov //  - "has a call frame", if the function has executed the prologue, and
26b4ad28daSMomchil Velikov //    has not executed any epilogue
27b4ad28daSMomchil Velikov //  - "does not have a call frame", if the function has not executed the
28b4ad28daSMomchil Velikov //    prologue, or has executed an epilogue
29b4ad28daSMomchil Velikov // which can be computed by a single RPO traversal.
30b4ad28daSMomchil Velikov 
3133374c44SMomchil Velikov // The location of the prologue is determined by finding the first block in the
3233374c44SMomchil Velikov // reverse traversal which contains CFI instructions.
3333374c44SMomchil Velikov 
34b4ad28daSMomchil Velikov // In order to accommodate backends which do not generate unwind info in
35b4ad28daSMomchil Velikov // epilogues we compute an additional property "strong no call frame on entry",
36b4ad28daSMomchil Velikov // which is set for the entry point of the function and for every block
37b4ad28daSMomchil Velikov // reachable from the entry along a path that does not execute the prologue. If
38b4ad28daSMomchil Velikov // this property holds, it takes precedence over the "has a call frame"
39b4ad28daSMomchil Velikov // property.
40b4ad28daSMomchil Velikov 
41b4ad28daSMomchil Velikov // From the point of view of the unwind tables, the "has/does not have call
42b4ad28daSMomchil Velikov // frame" state at beginning of each block is determined by the state at the end
43b4ad28daSMomchil Velikov // of the previous block, in layout order. Where these states differ, we insert
44b4ad28daSMomchil Velikov // compensating CFI instructions, which come in two flavours:
45b4ad28daSMomchil Velikov 
46b4ad28daSMomchil Velikov //   - CFI instructions, which reset the unwind table state to the initial one.
47b4ad28daSMomchil Velikov //     This is done by a target specific hook and is expected to be trivial
48b4ad28daSMomchil Velikov //     to implement, for example it could be:
49b4ad28daSMomchil Velikov //       .cfi_def_cfa <sp>, 0
50b4ad28daSMomchil Velikov //       .cfi_same_value <rN>
51b4ad28daSMomchil Velikov //       .cfi_same_value <rN-1>
52b4ad28daSMomchil Velikov //       ...
53b4ad28daSMomchil Velikov //     where <rN> are the callee-saved registers.
54b4ad28daSMomchil Velikov //   - CFI instructions, which reset the unwind table state to the one
55b4ad28daSMomchil Velikov //     created by the function prologue. These are
56b4ad28daSMomchil Velikov //       .cfi_restore_state
57b4ad28daSMomchil Velikov //       .cfi_remember_state
58b4ad28daSMomchil Velikov //     In this case we also insert a `.cfi_remember_state` after the last CFI
59b4ad28daSMomchil Velikov //     instruction in the function prologue.
60b4ad28daSMomchil Velikov //
61b4ad28daSMomchil Velikov // Known limitations:
62b4ad28daSMomchil Velikov //  * the pass cannot handle an epilogue preceding the prologue in the basic
63b4ad28daSMomchil Velikov //    block layout
64b4ad28daSMomchil Velikov //  * the pass does not handle functions where SP is used as a frame pointer and
65b4ad28daSMomchil Velikov //    SP adjustments up and down are done in different basic blocks (TODO)
66b4ad28daSMomchil Velikov //===----------------------------------------------------------------------===//
67b4ad28daSMomchil Velikov 
68b4ad28daSMomchil Velikov #include "llvm/CodeGen/CFIFixup.h"
69b4ad28daSMomchil Velikov 
70*07137ce3SDaniel Hoekwater #include "llvm/ADT/DenseMap.h"
71b4ad28daSMomchil Velikov #include "llvm/ADT/PostOrderIterator.h"
72*07137ce3SDaniel Hoekwater #include "llvm/ADT/STLExtras.h"
73*07137ce3SDaniel Hoekwater #include "llvm/ADT/iterator_range.h"
74*07137ce3SDaniel Hoekwater #include "llvm/CodeGen/MachineBasicBlock.h"
75*07137ce3SDaniel Hoekwater #include "llvm/CodeGen/MachineFunction.h"
76b4ad28daSMomchil Velikov #include "llvm/CodeGen/Passes.h"
77b4ad28daSMomchil Velikov #include "llvm/CodeGen/TargetFrameLowering.h"
78b4ad28daSMomchil Velikov #include "llvm/CodeGen/TargetInstrInfo.h"
79b4ad28daSMomchil Velikov #include "llvm/CodeGen/TargetSubtargetInfo.h"
80b4ad28daSMomchil Velikov #include "llvm/MC/MCAsmInfo.h"
81b4ad28daSMomchil Velikov #include "llvm/MC/MCDwarf.h"
82b4ad28daSMomchil Velikov #include "llvm/Target/TargetMachine.h"
83b4ad28daSMomchil Velikov 
84*07137ce3SDaniel Hoekwater #include <iterator>
85*07137ce3SDaniel Hoekwater 
86b4ad28daSMomchil Velikov using namespace llvm;
87b4ad28daSMomchil Velikov 
88b4ad28daSMomchil Velikov #define DEBUG_TYPE "cfi-fixup"
89b4ad28daSMomchil Velikov 
90b4ad28daSMomchil Velikov char CFIFixup::ID = 0;
91b4ad28daSMomchil Velikov 
92b4ad28daSMomchil Velikov INITIALIZE_PASS(CFIFixup, "cfi-fixup",
93b4ad28daSMomchil Velikov                 "Insert CFI remember/restore state instructions", false, false)
94b4ad28daSMomchil Velikov FunctionPass *llvm::createCFIFixup() { return new CFIFixup(); }
95b4ad28daSMomchil Velikov 
96b4ad28daSMomchil Velikov static bool isPrologueCFIInstruction(const MachineInstr &MI) {
97b4ad28daSMomchil Velikov   return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
98b4ad28daSMomchil Velikov          MI.getFlag(MachineInstr::FrameSetup);
99b4ad28daSMomchil Velikov }
100b4ad28daSMomchil Velikov 
101b4ad28daSMomchil Velikov static bool containsEpilogue(const MachineBasicBlock &MBB) {
102b4ad28daSMomchil Velikov   return llvm::any_of(llvm::reverse(MBB), [](const auto &MI) {
103b4ad28daSMomchil Velikov     return MI.getOpcode() == TargetOpcode::CFI_INSTRUCTION &&
104b4ad28daSMomchil Velikov            MI.getFlag(MachineInstr::FrameDestroy);
105b4ad28daSMomchil Velikov   });
106b4ad28daSMomchil Velikov }
107b4ad28daSMomchil Velikov 
10833374c44SMomchil Velikov static MachineBasicBlock *
10933374c44SMomchil Velikov findPrologueEnd(MachineFunction &MF, MachineBasicBlock::iterator &PrologueEnd) {
11033374c44SMomchil Velikov   // Even though we should theoretically traverse the blocks in post-order, we
11133374c44SMomchil Velikov   // can't encode correctly cases where prologue blocks are not laid out in
11233374c44SMomchil Velikov   // topological order. Then, assuming topological order, we can just traverse
11333374c44SMomchil Velikov   // the function in reverse.
11433374c44SMomchil Velikov   for (MachineBasicBlock &MBB : reverse(MF)) {
11533374c44SMomchil Velikov     for (MachineInstr &MI : reverse(MBB.instrs())) {
11633374c44SMomchil Velikov       if (!isPrologueCFIInstruction(MI))
11733374c44SMomchil Velikov         continue;
11833374c44SMomchil Velikov       PrologueEnd = std::next(MI.getIterator());
11933374c44SMomchil Velikov       return &MBB;
12033374c44SMomchil Velikov     }
12133374c44SMomchil Velikov   }
12233374c44SMomchil Velikov   return nullptr;
12333374c44SMomchil Velikov }
12433374c44SMomchil Velikov 
1251b8cff9aSDaniel Hoekwater // Represents the point within a basic block where we can insert an instruction.
1261b8cff9aSDaniel Hoekwater // Note that we need the MachineBasicBlock* as well as the iterator since the
1271b8cff9aSDaniel Hoekwater // iterator can point to the end of the block. Instructions are inserted
1281b8cff9aSDaniel Hoekwater // *before* the iterator.
1291b8cff9aSDaniel Hoekwater struct InsertionPoint {
130*07137ce3SDaniel Hoekwater   MachineBasicBlock *MBB = nullptr;
1311b8cff9aSDaniel Hoekwater   MachineBasicBlock::iterator Iterator;
1321b8cff9aSDaniel Hoekwater };
1331b8cff9aSDaniel Hoekwater 
1341b8cff9aSDaniel Hoekwater // Inserts a `.cfi_remember_state` instruction before PrologueEnd and a
1351b8cff9aSDaniel Hoekwater // `.cfi_restore_state` instruction before DstInsertPt. Returns an iterator
1361b8cff9aSDaniel Hoekwater // to the first instruction after the inserted `.cfi_restore_state` instruction.
1371b8cff9aSDaniel Hoekwater static InsertionPoint
1381b8cff9aSDaniel Hoekwater insertRememberRestorePair(const InsertionPoint &RememberInsertPt,
1391b8cff9aSDaniel Hoekwater                           const InsertionPoint &RestoreInsertPt) {
1401b8cff9aSDaniel Hoekwater   MachineFunction &MF = *RememberInsertPt.MBB->getParent();
1411b8cff9aSDaniel Hoekwater   const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
1421b8cff9aSDaniel Hoekwater 
1431b8cff9aSDaniel Hoekwater   // Insert the `.cfi_remember_state` instruction.
1441b8cff9aSDaniel Hoekwater   unsigned CFIIndex =
1451b8cff9aSDaniel Hoekwater       MF.addFrameInst(MCCFIInstruction::createRememberState(nullptr));
1461b8cff9aSDaniel Hoekwater   BuildMI(*RememberInsertPt.MBB, RememberInsertPt.Iterator, DebugLoc(),
1471b8cff9aSDaniel Hoekwater           TII.get(TargetOpcode::CFI_INSTRUCTION))
1481b8cff9aSDaniel Hoekwater       .addCFIIndex(CFIIndex);
1491b8cff9aSDaniel Hoekwater 
1501b8cff9aSDaniel Hoekwater   // Insert the `.cfi_restore_state` instruction.
1511b8cff9aSDaniel Hoekwater   CFIIndex = MF.addFrameInst(MCCFIInstruction::createRestoreState(nullptr));
1521b8cff9aSDaniel Hoekwater 
1531b8cff9aSDaniel Hoekwater   return {RestoreInsertPt.MBB,
1541b8cff9aSDaniel Hoekwater           std::next(BuildMI(*RestoreInsertPt.MBB, RestoreInsertPt.Iterator,
1551b8cff9aSDaniel Hoekwater                             DebugLoc(), TII.get(TargetOpcode::CFI_INSTRUCTION))
1561b8cff9aSDaniel Hoekwater                         .addCFIIndex(CFIIndex)
1571b8cff9aSDaniel Hoekwater                         ->getIterator())};
1581b8cff9aSDaniel Hoekwater }
1591b8cff9aSDaniel Hoekwater 
160*07137ce3SDaniel Hoekwater // Copies all CFI instructions before PrologueEnd and inserts them before
161*07137ce3SDaniel Hoekwater // DstInsertPt. Returns the iterator to the first instruction after the
162*07137ce3SDaniel Hoekwater // inserted instructions.
163*07137ce3SDaniel Hoekwater static InsertionPoint cloneCfiPrologue(const InsertionPoint &PrologueEnd,
164*07137ce3SDaniel Hoekwater                                        const InsertionPoint &DstInsertPt) {
165*07137ce3SDaniel Hoekwater   MachineFunction &MF = *DstInsertPt.MBB->getParent();
166*07137ce3SDaniel Hoekwater 
167*07137ce3SDaniel Hoekwater   auto cloneCfiInstructions = [&](MachineBasicBlock::iterator Begin,
168*07137ce3SDaniel Hoekwater                                   MachineBasicBlock::iterator End) {
169*07137ce3SDaniel Hoekwater     auto ToClone = map_range(
170*07137ce3SDaniel Hoekwater         make_filter_range(make_range(Begin, End), isPrologueCFIInstruction),
171*07137ce3SDaniel Hoekwater         [&](const MachineInstr &MI) { return MF.CloneMachineInstr(&MI); });
172*07137ce3SDaniel Hoekwater     DstInsertPt.MBB->insert(DstInsertPt.Iterator, ToClone.begin(),
173*07137ce3SDaniel Hoekwater                             ToClone.end());
174*07137ce3SDaniel Hoekwater   };
175*07137ce3SDaniel Hoekwater 
176*07137ce3SDaniel Hoekwater   // Clone all CFI instructions from previous blocks.
177*07137ce3SDaniel Hoekwater   for (auto &MBB : make_range(MF.begin(), PrologueEnd.MBB->getIterator()))
178*07137ce3SDaniel Hoekwater     cloneCfiInstructions(MBB.begin(), MBB.end());
179*07137ce3SDaniel Hoekwater   // Clone all CFI instructions from the final prologue block.
180*07137ce3SDaniel Hoekwater   cloneCfiInstructions(PrologueEnd.MBB->begin(), PrologueEnd.Iterator);
181*07137ce3SDaniel Hoekwater   return DstInsertPt;
182*07137ce3SDaniel Hoekwater }
183*07137ce3SDaniel Hoekwater 
184b4ad28daSMomchil Velikov bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
185b4ad28daSMomchil Velikov   const TargetFrameLowering &TFL = *MF.getSubtarget().getFrameLowering();
186b4ad28daSMomchil Velikov   if (!TFL.enableCFIFixup(MF))
187b4ad28daSMomchil Velikov     return false;
188b4ad28daSMomchil Velikov 
189b4ad28daSMomchil Velikov   const unsigned NumBlocks = MF.getNumBlockIDs();
190b4ad28daSMomchil Velikov   if (NumBlocks < 2)
191b4ad28daSMomchil Velikov     return false;
192b4ad28daSMomchil Velikov 
19333374c44SMomchil Velikov   // Find the prologue and the point where we can issue the first
19433374c44SMomchil Velikov   // `.cfi_remember_state`.
19533374c44SMomchil Velikov   MachineBasicBlock::iterator PrologueEnd;
19633374c44SMomchil Velikov   MachineBasicBlock *PrologueBlock = findPrologueEnd(MF, PrologueEnd);
19733374c44SMomchil Velikov   if (PrologueBlock == nullptr)
19833374c44SMomchil Velikov     return false;
19933374c44SMomchil Velikov 
200b4ad28daSMomchil Velikov   struct BlockFlags {
201b4ad28daSMomchil Velikov     bool Reachable : 1;
202b4ad28daSMomchil Velikov     bool StrongNoFrameOnEntry : 1;
203b4ad28daSMomchil Velikov     bool HasFrameOnEntry : 1;
204b4ad28daSMomchil Velikov     bool HasFrameOnExit : 1;
205b4ad28daSMomchil Velikov   };
206*07137ce3SDaniel Hoekwater   SmallVector<BlockFlags, 32> BlockInfo(NumBlocks,
207*07137ce3SDaniel Hoekwater                                         {false, false, false, false});
208b4ad28daSMomchil Velikov   BlockInfo[0].Reachable = true;
209b4ad28daSMomchil Velikov   BlockInfo[0].StrongNoFrameOnEntry = true;
210b4ad28daSMomchil Velikov 
211b4ad28daSMomchil Velikov   // Compute the presence/absence of frame at each basic block.
212b4ad28daSMomchil Velikov   ReversePostOrderTraversal<MachineBasicBlock *> RPOT(&*MF.begin());
213b4ad28daSMomchil Velikov   for (MachineBasicBlock *MBB : RPOT) {
214b4ad28daSMomchil Velikov     BlockFlags &Info = BlockInfo[MBB->getNumber()];
215b4ad28daSMomchil Velikov 
216b4ad28daSMomchil Velikov     // Set to true if the current block contains the prologue or the epilogue,
217b4ad28daSMomchil Velikov     // respectively.
21833374c44SMomchil Velikov     bool HasPrologue = MBB == PrologueBlock;
219b4ad28daSMomchil Velikov     bool HasEpilogue = false;
220b4ad28daSMomchil Velikov 
221b4ad28daSMomchil Velikov     if (Info.HasFrameOnEntry || HasPrologue)
222b4ad28daSMomchil Velikov       HasEpilogue = containsEpilogue(*MBB);
223b4ad28daSMomchil Velikov 
224b4ad28daSMomchil Velikov     // If the function has a call frame at the entry of the current block or the
225b4ad28daSMomchil Velikov     // current block contains the prologue, then the function has a call frame
226b4ad28daSMomchil Velikov     // at the exit of the block, unless the block contains the epilogue.
227b4ad28daSMomchil Velikov     Info.HasFrameOnExit = (Info.HasFrameOnEntry || HasPrologue) && !HasEpilogue;
228b4ad28daSMomchil Velikov 
229b4ad28daSMomchil Velikov     // Set the successors' state on entry.
230b4ad28daSMomchil Velikov     for (MachineBasicBlock *Succ : MBB->successors()) {
231b4ad28daSMomchil Velikov       BlockFlags &SuccInfo = BlockInfo[Succ->getNumber()];
232b4ad28daSMomchil Velikov       SuccInfo.Reachable = true;
233b4ad28daSMomchil Velikov       SuccInfo.StrongNoFrameOnEntry |=
234b4ad28daSMomchil Velikov           Info.StrongNoFrameOnEntry && !HasPrologue;
235b4ad28daSMomchil Velikov       SuccInfo.HasFrameOnEntry = Info.HasFrameOnExit;
236b4ad28daSMomchil Velikov     }
237b4ad28daSMomchil Velikov   }
238b4ad28daSMomchil Velikov 
239b4ad28daSMomchil Velikov   // Walk the blocks of the function in "physical" order.
240b4ad28daSMomchil Velikov   // Every block inherits the frame state (as recorded in the unwind tables)
241b4ad28daSMomchil Velikov   // of the previous block. If the intended frame state is different, insert
242b4ad28daSMomchil Velikov   // compensating CFI instructions.
243b4ad28daSMomchil Velikov   bool Change = false;
244*07137ce3SDaniel Hoekwater   // `InsertPt[sectionID]` always points to the point in a preceding block where
245*07137ce3SDaniel Hoekwater   // we have to insert a `.cfi_remember_state`, in the case that the current
246*07137ce3SDaniel Hoekwater   // block needs a `.cfi_restore_state`.
247*07137ce3SDaniel Hoekwater   SmallDenseMap<MBBSectionID, InsertionPoint> InsertionPts;
248*07137ce3SDaniel Hoekwater   InsertionPts[PrologueBlock->getSectionID()] = {PrologueBlock, PrologueEnd};
249b4ad28daSMomchil Velikov 
2501b8cff9aSDaniel Hoekwater   assert(PrologueEnd != PrologueBlock->begin() &&
251b4ad28daSMomchil Velikov          "Inconsistent notion of \"prologue block\"");
252b4ad28daSMomchil Velikov 
253b4ad28daSMomchil Velikov   // No point starting before the prologue block.
254b4ad28daSMomchil Velikov   // TODO: the unwind tables will still be incorrect if an epilogue physically
255b4ad28daSMomchil Velikov   // preceeds the prologue.
256b4ad28daSMomchil Velikov   MachineFunction::iterator CurrBB = std::next(PrologueBlock->getIterator());
257b4ad28daSMomchil Velikov   bool HasFrame = BlockInfo[PrologueBlock->getNumber()].HasFrameOnExit;
258b4ad28daSMomchil Velikov   while (CurrBB != MF.end()) {
259b4ad28daSMomchil Velikov     const BlockFlags &Info = BlockInfo[CurrBB->getNumber()];
260b4ad28daSMomchil Velikov     if (!Info.Reachable) {
261b4ad28daSMomchil Velikov       ++CurrBB;
262b4ad28daSMomchil Velikov       continue;
263b4ad28daSMomchil Velikov     }
264b4ad28daSMomchil Velikov 
265b4ad28daSMomchil Velikov #ifndef NDEBUG
266b4ad28daSMomchil Velikov     if (!Info.StrongNoFrameOnEntry) {
267b4ad28daSMomchil Velikov       for (auto *Pred : CurrBB->predecessors()) {
268b4ad28daSMomchil Velikov         BlockFlags &PredInfo = BlockInfo[Pred->getNumber()];
269b4ad28daSMomchil Velikov         assert((!PredInfo.Reachable ||
270b4ad28daSMomchil Velikov                 Info.HasFrameOnEntry == PredInfo.HasFrameOnExit) &&
271b4ad28daSMomchil Velikov                "Inconsistent call frame state");
272b4ad28daSMomchil Velikov       }
273b4ad28daSMomchil Velikov     }
274b4ad28daSMomchil Velikov #endif
275*07137ce3SDaniel Hoekwater 
276*07137ce3SDaniel Hoekwater     // If the block is the first block in its section, then it doesn't have a
277*07137ce3SDaniel Hoekwater     // frame on entry.
278*07137ce3SDaniel Hoekwater     HasFrame &= !CurrBB->isBeginSection();
279b4ad28daSMomchil Velikov     if (!Info.StrongNoFrameOnEntry && Info.HasFrameOnEntry && !HasFrame) {
280b4ad28daSMomchil Velikov       // Reset to the "after prologue" state.
281b4ad28daSMomchil Velikov 
282*07137ce3SDaniel Hoekwater       InsertionPoint &InsertPt = InsertionPts[CurrBB->getSectionID()];
283*07137ce3SDaniel Hoekwater       if (InsertPt.MBB == nullptr) {
284*07137ce3SDaniel Hoekwater         // CurBB is the first block in its section, so there is no "after
285*07137ce3SDaniel Hoekwater         // prologue" state. Clone the CFI instructions from the prologue block
286*07137ce3SDaniel Hoekwater         // to create it.
287*07137ce3SDaniel Hoekwater         InsertPt = cloneCfiPrologue({PrologueBlock, PrologueEnd},
288*07137ce3SDaniel Hoekwater                                     {&*CurrBB, CurrBB->begin()});
289*07137ce3SDaniel Hoekwater       } else {
2901b8cff9aSDaniel Hoekwater         // There's an earlier block known to have a stack frame. Insert a
2911b8cff9aSDaniel Hoekwater         // `.cfi_remember_state` instruction into that block and a
292*07137ce3SDaniel Hoekwater         // `.cfi_restore_state` instruction at the beginning of the current
293*07137ce3SDaniel Hoekwater         // block.
294*07137ce3SDaniel Hoekwater         InsertPt =
295*07137ce3SDaniel Hoekwater             insertRememberRestorePair(InsertPt, {&*CurrBB, CurrBB->begin()});
296*07137ce3SDaniel Hoekwater       }
297b4ad28daSMomchil Velikov       Change = true;
298b4ad28daSMomchil Velikov     } else if ((Info.StrongNoFrameOnEntry || !Info.HasFrameOnEntry) &&
299b4ad28daSMomchil Velikov                HasFrame) {
300b4ad28daSMomchil Velikov       // Reset to the state upon function entry.
301b4ad28daSMomchil Velikov       TFL.resetCFIToInitialState(*CurrBB);
302b4ad28daSMomchil Velikov       Change = true;
303b4ad28daSMomchil Velikov     }
304b4ad28daSMomchil Velikov 
305b4ad28daSMomchil Velikov     HasFrame = Info.HasFrameOnExit;
306b4ad28daSMomchil Velikov     ++CurrBB;
307b4ad28daSMomchil Velikov   }
308b4ad28daSMomchil Velikov 
309b4ad28daSMomchil Velikov   return Change;
310b4ad28daSMomchil Velikov }
311