18
18
// ===----------------------------------------------------------------------===//
19
19
20
20
#include " llvm/ADT/DepthFirstIterator.h"
21
+ #include " llvm/ADT/SetOperations.h"
21
22
#include " llvm/CodeGen/MachineFunctionPass.h"
22
23
#include " llvm/CodeGen/MachineInstrBuilder.h"
23
24
#include " llvm/CodeGen/MachineModuleInfo.h"
@@ -76,6 +77,10 @@ class CFIInstrInserter : public MachineFunctionPass {
76
77
unsigned IncomingCFARegister = 0 ;
77
78
// / Value of cfa register valid at basic block exit.
78
79
unsigned OutgoingCFARegister = 0 ;
80
+ // / Set of callee saved registers saved at basic block entry.
81
+ BitVector IncomingCSRSaved;
82
+ // / Set of callee saved registers saved at basic block exit.
83
+ BitVector OutgoingCSRSaved;
79
84
// / If in/out cfa offset and register values for this block have already
80
85
// / been set or not.
81
86
bool Processed = false ;
@@ -108,7 +113,8 @@ class CFIInstrInserter : public MachineFunctionPass {
108
113
return -MBBVector[MBB->getNumber ()].IncomingCFAOffset ;
109
114
}
110
115
111
- void report (const MBBCFAInfo &Pred, const MBBCFAInfo &Succ);
116
+ void reportCFAError (const MBBCFAInfo &Pred, const MBBCFAInfo &Succ);
117
+ void reportCSRError (const MBBCFAInfo &Pred, const MBBCFAInfo &Succ);
112
118
// / Go through each MBB in a function and check that outgoing offset and
113
119
// / register of its predecessors match incoming offset and register of that
114
120
// / MBB, as well as that incoming offset and register of its successors match
@@ -132,6 +138,8 @@ void CFIInstrInserter::calculateCFAInfo(MachineFunction &MF) {
132
138
// function.
133
139
unsigned InitialRegister =
134
140
MF.getSubtarget ().getFrameLowering ()->getInitialCFARegister (MF);
141
+ const TargetRegisterInfo &TRI = *MF.getSubtarget ().getRegisterInfo ();
142
+ unsigned NumRegs = TRI.getNumRegs ();
135
143
136
144
// Initialize MBBMap.
137
145
for (MachineBasicBlock &MBB : MF) {
@@ -141,6 +149,8 @@ void CFIInstrInserter::calculateCFAInfo(MachineFunction &MF) {
141
149
MBBInfo.OutgoingCFAOffset = InitialOffset;
142
150
MBBInfo.IncomingCFARegister = InitialRegister;
143
151
MBBInfo.OutgoingCFARegister = InitialRegister;
152
+ MBBInfo.IncomingCSRSaved .resize (NumRegs);
153
+ MBBInfo.OutgoingCSRSaved .resize (NumRegs);
144
154
MBBVector[MBB.getNumber ()] = MBBInfo;
145
155
}
146
156
@@ -159,8 +169,11 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
159
169
int SetOffset = MBBInfo.IncomingCFAOffset ;
160
170
// Outgoing cfa register set by the block.
161
171
unsigned SetRegister = MBBInfo.IncomingCFARegister ;
162
- const std::vector<MCCFIInstruction> &Instrs =
163
- MBBInfo.MBB ->getParent ()->getFrameInstructions ();
172
+ MachineFunction *MF = MBBInfo.MBB ->getParent ();
173
+ const std::vector<MCCFIInstruction> &Instrs = MF->getFrameInstructions ();
174
+ const TargetRegisterInfo &TRI = *MF->getSubtarget ().getRegisterInfo ();
175
+ unsigned NumRegs = TRI.getNumRegs ();
176
+ BitVector CSRSaved (NumRegs), CSRRestored (NumRegs);
164
177
165
178
// Determine cfa offset and register set by the block.
166
179
for (MachineInstr &MI : *MBBInfo.MBB ) {
@@ -181,6 +194,15 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
181
194
SetRegister = CFI.getRegister ();
182
195
SetOffset = CFI.getOffset ();
183
196
break ;
197
+ case MCCFIInstruction::OpOffset:
198
+ case MCCFIInstruction::OpRegister:
199
+ case MCCFIInstruction::OpRelOffset:
200
+ CSRSaved.set (CFI.getRegister ());
201
+ break ;
202
+ case MCCFIInstruction::OpRestore:
203
+ case MCCFIInstruction::OpUndefined:
204
+ CSRRestored.set (CFI.getRegister ());
205
+ break ;
184
206
case MCCFIInstruction::OpRememberState:
185
207
// TODO: Add support for handling cfi_remember_state.
186
208
#ifndef NDEBUG
@@ -199,12 +221,7 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
199
221
break ;
200
222
// Other CFI directives do not affect CFA value.
201
223
case MCCFIInstruction::OpSameValue:
202
- case MCCFIInstruction::OpOffset:
203
- case MCCFIInstruction::OpRelOffset:
204
224
case MCCFIInstruction::OpEscape:
205
- case MCCFIInstruction::OpRestore:
206
- case MCCFIInstruction::OpUndefined:
207
- case MCCFIInstruction::OpRegister:
208
225
case MCCFIInstruction::OpWindowSave:
209
226
case MCCFIInstruction::OpNegateRAState:
210
227
case MCCFIInstruction::OpGnuArgsSize:
@@ -218,6 +235,11 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
218
235
// Update outgoing CFA info.
219
236
MBBInfo.OutgoingCFAOffset = SetOffset;
220
237
MBBInfo.OutgoingCFARegister = SetRegister;
238
+
239
+ // Update outgoing CSR info.
240
+ MBBInfo.OutgoingCSRSaved = MBBInfo.IncomingCSRSaved ;
241
+ MBBInfo.OutgoingCSRSaved |= CSRSaved;
242
+ MBBInfo.OutgoingCSRSaved .reset (CSRRestored);
221
243
}
222
244
223
245
void CFIInstrInserter::updateSuccCFAInfo (MBBCFAInfo &MBBInfo) {
@@ -236,6 +258,7 @@ void CFIInstrInserter::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) {
236
258
if (!SuccInfo.Processed ) {
237
259
SuccInfo.IncomingCFAOffset = CurrentInfo.OutgoingCFAOffset ;
238
260
SuccInfo.IncomingCFARegister = CurrentInfo.OutgoingCFARegister ;
261
+ SuccInfo.IncomingCSRSaved = CurrentInfo.OutgoingCSRSaved ;
239
262
Stack.push_back (Succ);
240
263
}
241
264
}
@@ -287,12 +310,23 @@ bool CFIInstrInserter::insertCFIInstrs(MachineFunction &MF) {
287
310
.addCFIIndex (CFIIndex);
288
311
InsertedCFIInstr = true ;
289
312
}
313
+
314
+ BitVector SetDifference = PrevMBBInfo->OutgoingCSRSaved ;
315
+ SetDifference.reset (MBBInfo.IncomingCSRSaved );
316
+ for (int Reg : SetDifference.set_bits ()) {
317
+ unsigned CFIIndex =
318
+ MF.addFrameInst (MCCFIInstruction::createRestore (nullptr , Reg));
319
+ BuildMI (*MBBInfo.MBB , MBBI, DL, TII->get (TargetOpcode::CFI_INSTRUCTION))
320
+ .addCFIIndex (CFIIndex);
321
+ InsertedCFIInstr = true ;
322
+ }
290
323
PrevMBBInfo = &MBBInfo;
291
324
}
292
325
return InsertedCFIInstr;
293
326
}
294
327
295
- void CFIInstrInserter::report (const MBBCFAInfo &Pred, const MBBCFAInfo &Succ) {
328
+ void CFIInstrInserter::reportCFAError (const MBBCFAInfo &Pred,
329
+ const MBBCFAInfo &Succ) {
296
330
errs () << " *** Inconsistent CFA register and/or offset between pred and succ "
297
331
" ***\n " ;
298
332
errs () << " Pred: " << Pred.MBB ->getName () << " #" << Pred.MBB ->getNumber ()
@@ -307,6 +341,22 @@ void CFIInstrInserter::report(const MBBCFAInfo &Pred, const MBBCFAInfo &Succ) {
307
341
<< " incoming CFA Offset:" << Succ.IncomingCFAOffset << " \n " ;
308
342
}
309
343
344
+ void CFIInstrInserter::reportCSRError (const MBBCFAInfo &Pred,
345
+ const MBBCFAInfo &Succ) {
346
+ errs () << " *** Inconsistent CSR Saved between pred and succ in function "
347
+ << Pred.MBB ->getParent ()->getName () << " ***\n " ;
348
+ errs () << " Pred: " << Pred.MBB ->getName () << " #" << Pred.MBB ->getNumber ()
349
+ << " outgoing CSR Saved: " ;
350
+ for (int Reg : Pred.OutgoingCSRSaved .set_bits ())
351
+ errs () << Reg << " " ;
352
+ errs () << " \n " ;
353
+ errs () << " Succ: " << Succ.MBB ->getName () << " #" << Succ.MBB ->getNumber ()
354
+ << " incoming CSR Saved: " ;
355
+ for (int Reg : Succ.IncomingCSRSaved .set_bits ())
356
+ errs () << Reg << " " ;
357
+ errs () << " \n " ;
358
+ }
359
+
310
360
unsigned CFIInstrInserter::verify (MachineFunction &MF) {
311
361
unsigned ErrorNum = 0 ;
312
362
for (auto *CurrMBB : depth_first (&MF)) {
@@ -321,7 +371,13 @@ unsigned CFIInstrInserter::verify(MachineFunction &MF) {
321
371
// we don't generate epilogues inside such blocks.
322
372
if (SuccMBBInfo.MBB ->succ_empty () && !SuccMBBInfo.MBB ->isReturnBlock ())
323
373
continue ;
324
- report (CurrMBBInfo, SuccMBBInfo);
374
+ reportCFAError (CurrMBBInfo, SuccMBBInfo);
375
+ ErrorNum++;
376
+ }
377
+ // Check that IncomingCSRSaved of every successor matches the
378
+ // OutgoingCSRSaved of CurrMBB
379
+ if (SuccMBBInfo.IncomingCSRSaved != CurrMBBInfo.OutgoingCSRSaved ) {
380
+ reportCSRError (CurrMBBInfo, SuccMBBInfo);
325
381
ErrorNum++;
326
382
}
327
383
}
0 commit comments