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 "
267 if (CSRReg || CSROffset) {
269 if (It == CSRLocMap.end()) {
271 {CFI.
getRegister(), CSRSavedLocation(CSRReg, CSROffset)});
272 }
else if (It->second.Reg != CSRReg || It->second.Offset != CSROffset) {
281 if (RememberState != 0)
284 "Support for cfi_remember_state not implemented! Value of CFA may be "
288 MBBInfo.Processed =
true;
291 MBBInfo.OutgoingCFAOffset = SetOffset;
292 MBBInfo.OutgoingCFARegister = SetRegister;
296 MBBInfo.OutgoingCSRSaved, MBBInfo.IncomingCSRSaved, CSRSaved,
300void CFIInstrInserter::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) {
302 Stack.push_back(MBBInfo.MBB);
307 calculateOutgoingCFAInfo(CurrentInfo);
308 for (
auto *Succ : CurrentInfo.MBB->successors()) {
309 MBBCFAInfo &SuccInfo =
MBBVector[Succ->getNumber()];
310 if (!SuccInfo.Processed) {
311 SuccInfo.IncomingCFAOffset = CurrentInfo.OutgoingCFAOffset;
312 SuccInfo.IncomingCFARegister = CurrentInfo.OutgoingCFARegister;
313 SuccInfo.IncomingCSRSaved = CurrentInfo.OutgoingCSRSaved;
314 Stack.push_back(Succ);
317 }
while (!
Stack.empty());
323 bool InsertedCFIInstr =
false;
328 if (
MBB.
getNumber() == MF.front().getNumber())
continue;
338 if ((PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset &&
339 PrevMBBInfo->OutgoingCFARegister != MBBInfo.IncomingCFARegister) ||
346 nullptr, MBBInfo.IncomingCFARegister, getCorrectCFAOffset(&
MBB)));
349 InsertedCFIInstr =
true;
350 }
else if (PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset) {
355 nullptr, getCorrectCFAOffset(&
MBB)));
358 InsertedCFIInstr =
true;
359 }
else if (PrevMBBInfo->OutgoingCFARegister !=
360 MBBInfo.IncomingCFARegister) {
363 nullptr, MBBInfo.IncomingCFARegister));
366 InsertedCFIInstr =
true;
370 MF.getSubtarget().getFrameLowering()->emitCalleeSavedFrameMovesFullCFA(
372 InsertedCFIInstr =
true;
373 PrevMBBInfo = &MBBInfo;
378 PrevMBBInfo->OutgoingCSRSaved, MBBInfo.IncomingCSRSaved);
379 for (
int Reg : SetDifference.
set_bits()) {
384 InsertedCFIInstr =
true;
388 MBBInfo.IncomingCSRSaved, PrevMBBInfo->OutgoingCSRSaved);
389 for (
int Reg : SetDifference.
set_bits()) {
390 auto it = CSRLocMap.find(Reg);
391 assert(it != CSRLocMap.end() &&
"Reg should have an entry in CSRLocMap");
393 CSRSavedLocation RO = it->second;
394 if (!RO.Reg && RO.Offset) {
395 CFIIndex = MF.addFrameInst(
397 }
else if (RO.Reg && !RO.Offset) {
398 CFIIndex = MF.addFrameInst(
405 InsertedCFIInstr =
true;
408 PrevMBBInfo = &MBBInfo;
410 return InsertedCFIInstr;
413void CFIInstrInserter::reportCFAError(
const MBBCFAInfo &Pred,
414 const MBBCFAInfo &Succ) {
415 errs() <<
"*** Inconsistent CFA register and/or offset between pred and succ "
417 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
418 <<
" in " << Pred.MBB->getParent()->getName()
419 <<
" outgoing CFA Reg:" << Pred.OutgoingCFARegister <<
"\n";
420 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
421 <<
" in " << Pred.MBB->getParent()->getName()
422 <<
" outgoing CFA Offset:" << Pred.OutgoingCFAOffset <<
"\n";
423 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
424 <<
" incoming CFA Reg:" << Succ.IncomingCFARegister <<
"\n";
425 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
426 <<
" incoming CFA Offset:" << Succ.IncomingCFAOffset <<
"\n";
429void CFIInstrInserter::reportCSRError(
const MBBCFAInfo &Pred,
430 const MBBCFAInfo &Succ) {
431 errs() <<
"*** Inconsistent CSR Saved between pred and succ in function "
432 << Pred.MBB->getParent()->getName() <<
" ***\n";
433 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
434 <<
" outgoing CSR Saved: ";
435 for (
int Reg : Pred.OutgoingCSRSaved.set_bits())
438 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
439 <<
" incoming CSR Saved: ";
440 for (
int Reg : Succ.IncomingCSRSaved.set_bits())
446 unsigned ErrorNum = 0;
448 const MBBCFAInfo &CurrMBBInfo =
MBBVector[CurrMBB->getNumber()];
450 const MBBCFAInfo &SuccMBBInfo =
MBBVector[Succ->getNumber()];
453 if (SuccMBBInfo.IncomingCFAOffset != CurrMBBInfo.OutgoingCFAOffset ||
454 SuccMBBInfo.IncomingCFARegister != CurrMBBInfo.OutgoingCFARegister) {
457 if (SuccMBBInfo.MBB->succ_empty() && !SuccMBBInfo.MBB->isReturnBlock())
459 reportCFAError(CurrMBBInfo, SuccMBBInfo);
464 if (SuccMBBInfo.IncomingCSRSaved != CurrMBBInfo.OutgoingCSRSaved) {
465 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 &)