33 cl::desc(
"Verify Call Frame Information instructions"),
59 if (
unsigned ErrorNum =
verify(MF))
61 " in/out CFI information errors.");
63 bool insertedCFI = insertCFIInstrs(MF);
72 int64_t IncomingCFAOffset = -1;
74 int64_t OutgoingCFAOffset = -1;
76 unsigned IncomingCFARegister = 0;
78 unsigned OutgoingCFARegister = 0;
85 bool Processed =
false;
88#define INVALID_REG UINT_MAX
89#define INVALID_OFFSET INT_MAX
91 struct CSRSavedLocation {
92 CSRSavedLocation(std::optional<unsigned> R, std::optional<int> O)
93 : Reg(R), Offset(O) {}
94 std::optional<unsigned> Reg;
95 std::optional<int> Offset;
111 void calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo);
114 void updateSuccCFAInfo(MBBCFAInfo &MBBInfo);
128 void reportCFAError(
const MBBCFAInfo &Pred,
const MBBCFAInfo &Succ);
129 void reportCSRError(
const MBBCFAInfo &Pred,
const MBBCFAInfo &Succ);
138char CFIInstrInserter::ID = 0;
140 "Check CFA info and insert CFI instructions if needed",
false,
154 InitialRegister =
TRI.getDwarfRegNum(InitialRegister,
true);
155 unsigned NumRegs =
TRI.getNumSupportedRegs(MF);
161 MBBInfo.IncomingCFAOffset = InitialOffset;
162 MBBInfo.OutgoingCFAOffset = InitialOffset;
163 MBBInfo.IncomingCFARegister = InitialRegister;
164 MBBInfo.OutgoingCFARegister = InitialRegister;
165 MBBInfo.IncomingCSRSaved.resize(NumRegs);
166 MBBInfo.OutgoingCSRSaved.resize(NumRegs);
174 updateSuccCFAInfo(
MBBVector[MF.front().getNumber()]);
177void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
179 int64_t SetOffset = MBBInfo.IncomingCFAOffset;
181 unsigned SetRegister = MBBInfo.IncomingCFARegister;
185 unsigned NumRegs =
TRI.getNumSupportedRegs(*MF);
186 BitVector CSRSaved(NumRegs), CSRRestored(NumRegs);
189 int RememberState = 0;
194 if (
MI.isCFIInstruction()) {
195 std::optional<unsigned> CSRReg;
196 std::optional<int64_t> CSROffset;
197 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
229 "Support for cfi_llvm_def_aspace_cfa not implemented! Value of CFA "
230 "may be incorrect!\n");
239 if (RememberState != 1)
242 "Support for cfi_remember_state not implemented! Value of CFA "
243 "may be incorrect!\n");
250 if (RememberState != 0)
253 "Support for cfi_restore_state not implemented! Value of CFA may "
269 if (CSRReg || CSROffset) {
271 if (It == CSRLocMap.end()) {
273 {CFI.
getRegister(), CSRSavedLocation(CSRReg, CSROffset)});
274 }
else if (It->second.Reg != CSRReg || It->second.Offset != CSROffset) {
283 if (RememberState != 0)
286 "Support for cfi_remember_state not implemented! Value of CFA may be "
290 MBBInfo.Processed =
true;
293 MBBInfo.OutgoingCFAOffset = SetOffset;
294 MBBInfo.OutgoingCFARegister = SetRegister;
298 MBBInfo.OutgoingCSRSaved, MBBInfo.IncomingCSRSaved, CSRSaved,
302void CFIInstrInserter::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) {
304 Stack.push_back(MBBInfo.MBB);
309 calculateOutgoingCFAInfo(CurrentInfo);
310 for (
auto *Succ : CurrentInfo.MBB->successors()) {
311 MBBCFAInfo &SuccInfo =
MBBVector[Succ->getNumber()];
312 if (!SuccInfo.Processed) {
313 SuccInfo.IncomingCFAOffset = CurrentInfo.OutgoingCFAOffset;
314 SuccInfo.IncomingCFARegister = CurrentInfo.OutgoingCFARegister;
315 SuccInfo.IncomingCSRSaved = CurrentInfo.OutgoingCSRSaved;
316 Stack.push_back(Succ);
319 }
while (!
Stack.empty());
325 bool InsertedCFIInstr =
false;
330 if (
MBB.
getNumber() == MF.front().getNumber())
continue;
340 if ((PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset &&
341 PrevMBBInfo->OutgoingCFARegister != MBBInfo.IncomingCFARegister) ||
348 nullptr, MBBInfo.IncomingCFARegister, getCorrectCFAOffset(&
MBB)));
351 InsertedCFIInstr =
true;
352 }
else if (PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset) {
357 nullptr, getCorrectCFAOffset(&
MBB)));
360 InsertedCFIInstr =
true;
361 }
else if (PrevMBBInfo->OutgoingCFARegister !=
362 MBBInfo.IncomingCFARegister) {
365 nullptr, MBBInfo.IncomingCFARegister));
368 InsertedCFIInstr =
true;
372 MF.getSubtarget().getFrameLowering()->emitCalleeSavedFrameMovesFullCFA(
374 InsertedCFIInstr =
true;
375 PrevMBBInfo = &MBBInfo;
380 PrevMBBInfo->OutgoingCSRSaved, MBBInfo.IncomingCSRSaved);
381 for (
int Reg : SetDifference.
set_bits()) {
386 InsertedCFIInstr =
true;
390 MBBInfo.IncomingCSRSaved, PrevMBBInfo->OutgoingCSRSaved);
391 for (
int Reg : SetDifference.
set_bits()) {
392 auto it = CSRLocMap.find(Reg);
393 assert(it != CSRLocMap.end() &&
"Reg should have an entry in CSRLocMap");
395 CSRSavedLocation RO = it->second;
396 if (!RO.Reg && RO.Offset) {
397 CFIIndex = MF.addFrameInst(
399 }
else if (RO.Reg && !RO.Offset) {
400 CFIIndex = MF.addFrameInst(
407 InsertedCFIInstr =
true;
410 PrevMBBInfo = &MBBInfo;
412 return InsertedCFIInstr;
415void CFIInstrInserter::reportCFAError(
const MBBCFAInfo &Pred,
416 const MBBCFAInfo &Succ) {
417 errs() <<
"*** Inconsistent CFA register and/or offset between pred and succ "
419 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
420 <<
" in " << Pred.MBB->getParent()->getName()
421 <<
" outgoing CFA Reg:" << Pred.OutgoingCFARegister <<
"\n";
422 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
423 <<
" in " << Pred.MBB->getParent()->getName()
424 <<
" outgoing CFA Offset:" << Pred.OutgoingCFAOffset <<
"\n";
425 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
426 <<
" incoming CFA Reg:" << Succ.IncomingCFARegister <<
"\n";
427 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
428 <<
" incoming CFA Offset:" << Succ.IncomingCFAOffset <<
"\n";
431void CFIInstrInserter::reportCSRError(
const MBBCFAInfo &Pred,
432 const MBBCFAInfo &Succ) {
433 errs() <<
"*** Inconsistent CSR Saved between pred and succ in function "
434 << Pred.MBB->getParent()->getName() <<
" ***\n";
435 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
436 <<
" outgoing CSR Saved: ";
437 for (
int Reg : Pred.OutgoingCSRSaved.set_bits())
440 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
441 <<
" incoming CSR Saved: ";
442 for (
int Reg : Succ.IncomingCSRSaved.set_bits())
448 unsigned ErrorNum = 0;
450 const MBBCFAInfo &CurrMBBInfo =
MBBVector[CurrMBB->getNumber()];
452 const MBBCFAInfo &SuccMBBInfo =
MBBVector[Succ->getNumber()];
455 if (SuccMBBInfo.IncomingCFAOffset != CurrMBBInfo.OutgoingCFAOffset ||
456 SuccMBBInfo.IncomingCFARegister != CurrMBBInfo.OutgoingCFARegister) {
459 if (SuccMBBInfo.MBB->succ_empty() && !SuccMBBInfo.MBB->isReturnBlock())
461 reportCFAError(CurrMBBInfo, SuccMBBInfo);
466 if (SuccMBBInfo.IncomingCSRSaved != CurrMBBInfo.OutgoingCSRSaved) {
467 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 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.
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.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, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
OpType getOperation() const
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
int64_t getOffset() const
void reportError(SMLoc L, const Twine &Msg)
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.
MCContext & getContext() const
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.
Represents a location in source code.
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 &)