70
70
#include " llvm/ADT/DenseMap.h"
71
71
#include " llvm/ADT/PostOrderIterator.h"
72
72
#include " llvm/ADT/STLExtras.h"
73
+ #include " llvm/ADT/SmallVector.h"
73
74
#include " llvm/ADT/iterator_range.h"
74
75
#include " llvm/CodeGen/MachineBasicBlock.h"
75
76
#include " llvm/CodeGen/MachineFunction.h"
@@ -122,6 +123,57 @@ findPrologueEnd(MachineFunction &MF, MachineBasicBlock::iterator &PrologueEnd) {
122
123
return nullptr ;
123
124
}
124
125
126
+ // Represents a basic block's relationship to the call frame. This metadata
127
+ // reflects what the state *should* be, which may differ from the actual state
128
+ // after final machine basic block layout.
129
+ struct BlockFlags {
130
+ bool Reachable : 1 ;
131
+ bool StrongNoFrameOnEntry : 1 ;
132
+ bool HasFrameOnEntry : 1 ;
133
+ bool HasFrameOnExit : 1 ;
134
+ };
135
+
136
+ // Computes the frame information for each block in the function. Frame info
137
+ // for a block is inferred from its predecessors.
138
+ static SmallVector<BlockFlags>
139
+ computeBlockInfo (const MachineFunction &MF,
140
+ const MachineBasicBlock *PrologueBlock) {
141
+ SmallVector<BlockFlags, 32 > BlockInfo (MF.getNumBlockIDs (),
142
+ {false , false , false , false });
143
+ BlockInfo[0 ].Reachable = true ;
144
+ BlockInfo[0 ].StrongNoFrameOnEntry = true ;
145
+
146
+ // Compute the presence/absence of frame at each basic block.
147
+ ReversePostOrderTraversal<const MachineBasicBlock *> RPOT (&*MF.begin ());
148
+ for (const MachineBasicBlock *MBB : RPOT) {
149
+ BlockFlags &Info = BlockInfo[MBB->getNumber ()];
150
+
151
+ // Set to true if the current block contains the prologue or the epilogue,
152
+ // respectively.
153
+ bool HasPrologue = MBB == PrologueBlock;
154
+ bool HasEpilogue = false ;
155
+
156
+ if (Info.HasFrameOnEntry || HasPrologue)
157
+ HasEpilogue = containsEpilogue (*MBB);
158
+
159
+ // If the function has a call frame at the entry of the current block or the
160
+ // current block contains the prologue, then the function has a call frame
161
+ // at the exit of the block, unless the block contains the epilogue.
162
+ Info.HasFrameOnExit = (Info.HasFrameOnEntry || HasPrologue) && !HasEpilogue;
163
+
164
+ // Set the successors' state on entry.
165
+ for (MachineBasicBlock *Succ : MBB->successors ()) {
166
+ BlockFlags &SuccInfo = BlockInfo[Succ->getNumber ()];
167
+ SuccInfo.Reachable = true ;
168
+ SuccInfo.StrongNoFrameOnEntry |=
169
+ Info.StrongNoFrameOnEntry && !HasPrologue;
170
+ SuccInfo.HasFrameOnEntry = Info.HasFrameOnExit ;
171
+ }
172
+ }
173
+
174
+ return BlockInfo;
175
+ }
176
+
125
177
// Represents the point within a basic block where we can insert an instruction.
126
178
// Note that we need the MachineBasicBlock* as well as the iterator since the
127
179
// iterator can point to the end of the block. Instructions are inserted
@@ -181,13 +233,69 @@ static InsertionPoint cloneCfiPrologue(const InsertionPoint &PrologueEnd,
181
233
return DstInsertPt;
182
234
}
183
235
184
- bool CFIFixup::runOnMachineFunction (MachineFunction &MF) {
236
+ // Fixes up the CFI instructions in a basic block to be consistent with the
237
+ // intended frame state, adding or removing CFI instructions as necessary.
238
+ // Returns true if a change was made and false otherwise.
239
+ static bool
240
+ fixupBlock (MachineBasicBlock &CurrBB, const SmallVector<BlockFlags> &BlockInfo,
241
+ SmallDenseMap<MBBSectionID, InsertionPoint> &InsertionPts,
242
+ const InsertionPoint &Prologue) {
243
+ const MachineFunction &MF = *CurrBB.getParent ();
185
244
const TargetFrameLowering &TFL = *MF.getSubtarget ().getFrameLowering ();
186
- if (!TFL.enableCFIFixup (MF))
245
+ const BlockFlags &Info = BlockInfo[CurrBB.getNumber ()];
246
+
247
+ if (!Info.Reachable )
248
+ return false ;
249
+
250
+ // If the previous block and the current block are in the same section,
251
+ // the frame info will propagate from the previous block to the current one.
252
+ const BlockFlags &PrevInfo =
253
+ BlockInfo[std::prev (CurrBB.getIterator ())->getNumber ()];
254
+ bool HasFrame = PrevInfo.HasFrameOnExit && !CurrBB.isBeginSection ();
255
+ bool NeedsFrame = Info.HasFrameOnEntry && !Info.StrongNoFrameOnEntry ;
256
+
257
+ #ifndef NDEBUG
258
+ if (!Info.StrongNoFrameOnEntry ) {
259
+ for (auto *Pred : CurrBB.predecessors ()) {
260
+ const BlockFlags &PredInfo = BlockInfo[Pred->getNumber ()];
261
+ assert ((!PredInfo.Reachable ||
262
+ Info.HasFrameOnEntry == PredInfo.HasFrameOnExit ) &&
263
+ " Inconsistent call frame state" );
264
+ }
265
+ }
266
+ #endif
267
+
268
+ if (HasFrame == NeedsFrame)
269
+ return false ;
270
+
271
+ if (!NeedsFrame) {
272
+ // Reset to the state upon function entry.
273
+ TFL.resetCFIToInitialState (CurrBB);
274
+ return true ;
275
+ }
276
+
277
+ // Reset to the "after prologue" state.
278
+ InsertionPoint &InsertPt = InsertionPts[CurrBB.getSectionID ()];
279
+ if (InsertPt.MBB == nullptr ) {
280
+ // CurBB is the first block in its section, so there is no "after
281
+ // prologue" state. Clone the CFI instructions from the prologue block
282
+ // to create it.
283
+ InsertPt = cloneCfiPrologue (Prologue, {&CurrBB, CurrBB.begin ()});
284
+ } else {
285
+ // There's an earlier block known to have a stack frame. Insert a
286
+ // `.cfi_remember_state` instruction into that block and a
287
+ // `.cfi_restore_state` instruction at the beginning of the current
288
+ // block.
289
+ InsertPt = insertRememberRestorePair (InsertPt, {&CurrBB, CurrBB.begin ()});
290
+ }
291
+ return true ;
292
+ }
293
+
294
+ bool CFIFixup::runOnMachineFunction (MachineFunction &MF) {
295
+ if (!MF.getSubtarget ().getFrameLowering ()->enableCFIFixup (MF))
187
296
return false ;
188
297
189
- const unsigned NumBlocks = MF.getNumBlockIDs ();
190
- if (NumBlocks < 2 )
298
+ if (MF.getNumBlockIDs () < 2 )
191
299
return false ;
192
300
193
301
// Find the prologue and the point where we can issue the first
@@ -197,44 +305,7 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
197
305
if (PrologueBlock == nullptr )
198
306
return false ;
199
307
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
- }
308
+ SmallVector<BlockFlags> BlockInfo = computeBlockInfo (MF, PrologueBlock);
238
309
239
310
// Walk the blocks of the function in "physical" order.
240
311
// Every block inherits the frame state (as recorded in the unwind tables)
@@ -253,57 +324,10 @@ bool CFIFixup::runOnMachineFunction(MachineFunction &MF) {
253
324
// No point starting before the prologue block.
254
325
// TODO: the unwind tables will still be incorrect if an epilogue physically
255
326
// 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;
327
+ for (MachineBasicBlock &MBB :
328
+ make_range (std::next (PrologueBlock->getIterator ()), MF.end ())) {
329
+ Change |=
330
+ fixupBlock (MBB, BlockInfo, InsertionPts, {PrologueBlock, PrologueEnd});
307
331
}
308
332
309
333
return Change;
0 commit comments