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.getNumSupportedRegs(MF);
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.getNumSupportedRegs(*MF);
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 "
254 if (CSRReg || CSROffset) {
256 if (It == CSRLocMap.end()) {
258 {CFI.
getRegister(), CSRSavedLocation(CSRReg, CSROffset)});
259 }
else if (It->second.Reg != CSRReg || It->second.Offset != CSROffset) {
267 MBBInfo.Processed =
true;
270 MBBInfo.OutgoingCFAOffset = SetOffset;
271 MBBInfo.OutgoingCFARegister = SetRegister;
275 MBBInfo.OutgoingCSRSaved, MBBInfo.IncomingCSRSaved, CSRSaved,
279void CFIInstrInserter::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) {
281 Stack.push_back(MBBInfo.MBB);
286 calculateOutgoingCFAInfo(CurrentInfo);
287 for (
auto *Succ : CurrentInfo.MBB->successors()) {
288 MBBCFAInfo &SuccInfo =
MBBVector[Succ->getNumber()];
289 if (!SuccInfo.Processed) {
290 SuccInfo.IncomingCFAOffset = CurrentInfo.OutgoingCFAOffset;
291 SuccInfo.IncomingCFARegister = CurrentInfo.OutgoingCFARegister;
292 SuccInfo.IncomingCSRSaved = CurrentInfo.OutgoingCSRSaved;
293 Stack.push_back(Succ);
296 }
while (!
Stack.empty());
302 bool InsertedCFIInstr =
false;
307 if (
MBB.
getNumber() == MF.front().getNumber())
continue;
317 if ((PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset &&
318 PrevMBBInfo->OutgoingCFARegister != MBBInfo.IncomingCFARegister) ||
325 nullptr, MBBInfo.IncomingCFARegister, getCorrectCFAOffset(&
MBB)));
328 InsertedCFIInstr =
true;
329 }
else if (PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset) {
334 nullptr, getCorrectCFAOffset(&
MBB)));
337 InsertedCFIInstr =
true;
338 }
else if (PrevMBBInfo->OutgoingCFARegister !=
339 MBBInfo.IncomingCFARegister) {
342 nullptr, MBBInfo.IncomingCFARegister));
345 InsertedCFIInstr =
true;
349 MF.getSubtarget().getFrameLowering()->emitCalleeSavedFrameMovesFullCFA(
351 InsertedCFIInstr =
true;
352 PrevMBBInfo = &MBBInfo;
357 PrevMBBInfo->OutgoingCSRSaved, MBBInfo.IncomingCSRSaved);
358 for (
int Reg : SetDifference.
set_bits()) {
363 InsertedCFIInstr =
true;
367 MBBInfo.IncomingCSRSaved, PrevMBBInfo->OutgoingCSRSaved);
368 for (
int Reg : SetDifference.
set_bits()) {
369 auto it = CSRLocMap.find(Reg);
370 assert(it != CSRLocMap.end() &&
"Reg should have an entry in CSRLocMap");
372 CSRSavedLocation RO = it->second;
373 if (!RO.Reg && RO.Offset) {
374 CFIIndex = MF.addFrameInst(
376 }
else if (RO.Reg && !RO.Offset) {
377 CFIIndex = MF.addFrameInst(
384 InsertedCFIInstr =
true;
387 PrevMBBInfo = &MBBInfo;
389 return InsertedCFIInstr;
392void CFIInstrInserter::reportCFAError(
const MBBCFAInfo &Pred,
393 const MBBCFAInfo &Succ) {
394 errs() <<
"*** Inconsistent CFA register and/or offset between pred and succ "
396 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
397 <<
" in " << Pred.MBB->getParent()->getName()
398 <<
" outgoing CFA Reg:" << Pred.OutgoingCFARegister <<
"\n";
399 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
400 <<
" in " << Pred.MBB->getParent()->getName()
401 <<
" outgoing CFA Offset:" << Pred.OutgoingCFAOffset <<
"\n";
402 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
403 <<
" incoming CFA Reg:" << Succ.IncomingCFARegister <<
"\n";
404 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
405 <<
" incoming CFA Offset:" << Succ.IncomingCFAOffset <<
"\n";
408void CFIInstrInserter::reportCSRError(
const MBBCFAInfo &Pred,
409 const MBBCFAInfo &Succ) {
410 errs() <<
"*** Inconsistent CSR Saved between pred and succ in function "
411 << Pred.MBB->getParent()->getName() <<
" ***\n";
412 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
413 <<
" outgoing CSR Saved: ";
414 for (
int Reg : Pred.OutgoingCSRSaved.set_bits())
417 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
418 <<
" incoming CSR Saved: ";
419 for (
int Reg : Succ.IncomingCSRSaved.set_bits())
425 unsigned ErrorNum = 0;
427 const MBBCFAInfo &CurrMBBInfo =
MBBVector[CurrMBB->getNumber()];
429 const MBBCFAInfo &SuccMBBInfo =
MBBVector[Succ->getNumber()];
432 if (SuccMBBInfo.IncomingCFAOffset != CurrMBBInfo.OutgoingCFAOffset ||
433 SuccMBBInfo.IncomingCFARegister != CurrMBBInfo.OutgoingCFARegister) {
436 if (SuccMBBInfo.MBB->succ_empty() && !SuccMBBInfo.MBB->isReturnBlock())
438 reportCFAError(CurrMBBInfo, SuccMBBInfo);
443 if (SuccMBBInfo.IncomingCSRSaved != CurrMBBInfo.OutgoingCSRSaved) {
444 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 createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register, SMLoc Loc={})
.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 createRegister(MCSymbol *L, unsigned Register1, unsigned Register2, SMLoc Loc={})
.cfi_register Previous value of Register1 is saved in register Register2.
OpType getOperation() const
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
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 &)