32 cl::desc(
"Verify Call Frame Information instructions"),
58 if (
unsigned ErrorNum =
verify(MF))
60 " in/out CFI information errors.");
62 bool insertedCFI = insertCFIInstrs(MF);
71 int IncomingCFAOffset = -1;
73 int OutgoingCFAOffset = -1;
75 unsigned IncomingCFARegister = 0;
77 unsigned OutgoingCFARegister = 0;
84 bool Processed =
false;
87#define INVALID_REG UINT_MAX
88#define INVALID_OFFSET INT_MAX
90 struct CSRSavedLocation {
91 CSRSavedLocation(std::optional<unsigned> R, std::optional<int> O)
92 : Reg(R), Offset(O) {}
93 std::optional<unsigned> Reg;
94 std::optional<int> Offset;
110 void calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo);
113 void updateSuccCFAInfo(MBBCFAInfo &MBBInfo);
127 void reportCFAError(
const MBBCFAInfo &Pred,
const MBBCFAInfo &Succ);
128 void reportCSRError(
const MBBCFAInfo &Pred,
const MBBCFAInfo &Succ);
137char CFIInstrInserter::ID = 0;
139 "Check CFA info and insert CFI instructions if needed",
false,
153 InitialRegister =
TRI.getDwarfRegNum(InitialRegister,
true);
154 unsigned NumRegs =
TRI.getNumRegs();
160 MBBInfo.IncomingCFAOffset = InitialOffset;
161 MBBInfo.OutgoingCFAOffset = InitialOffset;
162 MBBInfo.IncomingCFARegister = InitialRegister;
163 MBBInfo.OutgoingCFARegister = InitialRegister;
164 MBBInfo.IncomingCSRSaved.resize(NumRegs);
165 MBBInfo.OutgoingCSRSaved.resize(NumRegs);
173 updateSuccCFAInfo(
MBBVector[MF.front().getNumber()]);
176void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
178 int SetOffset = MBBInfo.IncomingCFAOffset;
180 unsigned SetRegister = MBBInfo.IncomingCFARegister;
184 unsigned NumRegs =
TRI.getNumRegs();
185 BitVector CSRSaved(NumRegs), CSRRestored(NumRegs);
189 if (
MI.isCFIInstruction()) {
190 std::optional<unsigned> CSRReg;
191 std::optional<int> CSROffset;
192 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
224 "Support for cfi_llvm_def_aspace_cfa not implemented! Value of CFA "
225 "may be incorrect!\n");
232 "Support for cfi_remember_state not implemented! Value of CFA "
233 "may be incorrect!\n");
240 "Support for cfi_restore_state not implemented! Value of CFA may "
253 if (CSRReg || CSROffset) {
255 if (It == CSRLocMap.end()) {
257 {CFI.
getRegister(), CSRSavedLocation(CSRReg, CSROffset)});
258 }
else if (It->second.Reg != CSRReg || It->second.Offset != CSROffset) {
266 MBBInfo.Processed =
true;
269 MBBInfo.OutgoingCFAOffset = SetOffset;
270 MBBInfo.OutgoingCFARegister = SetRegister;
274 MBBInfo.OutgoingCSRSaved, MBBInfo.IncomingCSRSaved, CSRSaved,
278void CFIInstrInserter::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) {
280 Stack.push_back(MBBInfo.MBB);
285 calculateOutgoingCFAInfo(CurrentInfo);
286 for (
auto *Succ : CurrentInfo.MBB->successors()) {
287 MBBCFAInfo &SuccInfo =
MBBVector[Succ->getNumber()];
288 if (!SuccInfo.Processed) {
289 SuccInfo.IncomingCFAOffset = CurrentInfo.OutgoingCFAOffset;
290 SuccInfo.IncomingCFARegister = CurrentInfo.OutgoingCFARegister;
291 SuccInfo.IncomingCSRSaved = CurrentInfo.OutgoingCSRSaved;
292 Stack.push_back(Succ);
295 }
while (!
Stack.empty());
301 bool InsertedCFIInstr =
false;
306 if (
MBB.
getNumber() == MF.front().getNumber())
continue;
316 if ((PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset &&
317 PrevMBBInfo->OutgoingCFARegister != MBBInfo.IncomingCFARegister) ||
324 nullptr, MBBInfo.IncomingCFARegister, getCorrectCFAOffset(&
MBB)));
327 InsertedCFIInstr =
true;
328 }
else if (PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset) {
333 nullptr, getCorrectCFAOffset(&
MBB)));
336 InsertedCFIInstr =
true;
337 }
else if (PrevMBBInfo->OutgoingCFARegister !=
338 MBBInfo.IncomingCFARegister) {
341 nullptr, MBBInfo.IncomingCFARegister));
344 InsertedCFIInstr =
true;
348 MF.getSubtarget().getFrameLowering()->emitCalleeSavedFrameMovesFullCFA(
350 InsertedCFIInstr =
true;
351 PrevMBBInfo = &MBBInfo;
356 PrevMBBInfo->OutgoingCSRSaved, MBBInfo.IncomingCSRSaved);
357 for (
int Reg : SetDifference.
set_bits()) {
362 InsertedCFIInstr =
true;
366 MBBInfo.IncomingCSRSaved, PrevMBBInfo->OutgoingCSRSaved);
367 for (
int Reg : SetDifference.
set_bits()) {
368 auto it = CSRLocMap.find(Reg);
369 assert(it != CSRLocMap.end() &&
"Reg should have an entry in CSRLocMap");
371 CSRSavedLocation RO = it->second;
372 if (!RO.Reg && RO.Offset) {
373 CFIIndex = MF.addFrameInst(
375 }
else if (RO.Reg && !RO.Offset) {
376 CFIIndex = MF.addFrameInst(
383 InsertedCFIInstr =
true;
386 PrevMBBInfo = &MBBInfo;
388 return InsertedCFIInstr;
391void CFIInstrInserter::reportCFAError(
const MBBCFAInfo &Pred,
392 const MBBCFAInfo &Succ) {
393 errs() <<
"*** Inconsistent CFA register and/or offset between pred and succ "
395 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
396 <<
" in " << Pred.MBB->getParent()->getName()
397 <<
" outgoing CFA Reg:" << Pred.OutgoingCFARegister <<
"\n";
398 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
399 <<
" in " << Pred.MBB->getParent()->getName()
400 <<
" outgoing CFA Offset:" << Pred.OutgoingCFAOffset <<
"\n";
401 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
402 <<
" incoming CFA Reg:" << Succ.IncomingCFARegister <<
"\n";
403 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
404 <<
" incoming CFA Offset:" << Succ.IncomingCFAOffset <<
"\n";
407void CFIInstrInserter::reportCSRError(
const MBBCFAInfo &Pred,
408 const MBBCFAInfo &Succ) {
409 errs() <<
"*** Inconsistent CSR Saved between pred and succ in function "
410 << Pred.MBB->getParent()->getName() <<
" ***\n";
411 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
412 <<
" outgoing CSR Saved: ";
413 for (
int Reg : Pred.OutgoingCSRSaved.set_bits())
416 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
417 <<
" incoming CSR Saved: ";
418 for (
int Reg : Succ.IncomingCSRSaved.set_bits())
424 unsigned ErrorNum = 0;
426 const MBBCFAInfo &CurrMBBInfo =
MBBVector[CurrMBB->getNumber()];
428 const MBBCFAInfo &SuccMBBInfo =
MBBVector[Succ->getNumber()];
431 if (SuccMBBInfo.IncomingCFAOffset != CurrMBBInfo.OutgoingCFAOffset ||
432 SuccMBBInfo.IncomingCFARegister != CurrMBBInfo.OutgoingCFARegister) {
435 if (SuccMBBInfo.MBB->succ_empty() && !SuccMBBInfo.MBB->isReturnBlock())
437 reportCFAError(CurrMBBInfo, SuccMBBInfo);
442 if (SuccMBBInfo.IncomingCSRSaved != CurrMBBInfo.OutgoingCSRSaved) {
443 reportCSRError(CurrMBBInfo, SuccMBBInfo);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< bool > VerifyCFI("verify-cfiinstrs", cl::desc("Verify Call Frame Information instructions"), cl::init(false), cl::Hidden)
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
SmallVector< MachineBasicBlock *, 4 > MBBVector
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
iterator_range< const_set_bits_iterator > set_bits() const
static BitVector & apply(F &&f, BitVector &Out, BitVector const &Arg, ArgTys const &...Args)
FunctionPass class - This class is used to implement most global optimizations.
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset)
.cfi_def_cfa_offset modifies a rule for computing CFA.
static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register)
.cfi_restore says that the rule for Register is now the same as it was at the beginning of the functi...
unsigned getRegister2() const
unsigned getRegister() const
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register)
.cfi_def_cfa_register modifies a rule for computing CFA.
OpType getOperation() const
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int Offset)
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset)
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, unsigned Register2)
.cfi_register Previous value of Register1 is saved in register Register2.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
bool isBeginSection() const
Returns true if this block begins any section.
iterator_range< succ_iterator > successors()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const std::vector< MCCFIInstruction > & getFrameInstructions() const
Returns a reference to a list of cfi instructions in the function's prologue.
bool needsFrameMoves() const
True if this function needs frame moves for debug or exceptions.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const MachineBasicBlock & front() const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
Representation of each machine instruction.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Wrapper class representing virtual and physical registers.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
virtual Register getInitialCFARegister(const MachineFunction &MF) const
Return initial CFA register value i.e.
virtual int getInitialCFAOffset(const MachineFunction &MF) const
Return initial CFA offset value i.e.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createCFIInstrInserter()
Creates CFI Instruction Inserter pass.
iterator_range< df_iterator< T > > depth_first(const T &G)
void initializeCFIInstrInserterPass(PassRegistry &)