34 cl::desc(
"Verify Call Frame Information instructions"),
39class CFIInstrInserterImpl {
53 if (
unsigned ErrorNum =
verify(MF))
55 " in/out CFI information errors.");
57 bool insertedCFI = insertCFIInstrs(MF);
64 class CSRSavedLocation {
66 enum Kind { Invalid, Register, CFAOffset };
82 Loc.K = Kind::CFAOffset;
87 static CSRSavedLocation createRegister(
unsigned Reg) {
89 Loc.K = Kind::Register;
94 bool isValid()
const {
return K != Kind::Invalid; }
96 unsigned getRegister()
const {
97 assert(K == Kind::Register);
102 assert(K == Kind::CFAOffset);
113 return getRegister() ==
RHS.getRegister();
114 case Kind::CFAOffset:
120 return !(*
this ==
RHS);
122 void dump(raw_ostream &OS)
const {
128 OS <<
"In Dwarf register: " <<
Reg;
130 case Kind::CFAOffset:
131 OS <<
"At CFA offset: " <<
Offset;
138 MachineBasicBlock *MBB;
140 int64_t IncomingCFAOffset = -1;
142 int64_t OutgoingCFAOffset = -1;
144 unsigned IncomingCFARegister = 0;
146 unsigned OutgoingCFARegister = 0;
148 BitVector IncomingCSRSaved;
150 BitVector OutgoingCSRSaved;
153 bool Processed =
false;
158 std::vector<MBBCFAInfo> MBBVector;
161 SmallDenseMap<unsigned, CSRSavedLocation, 16> CSRLocMap;
169 void calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo);
172 void updateSuccCFAInfo(MBBCFAInfo &MBBInfo);
182 int64_t getCorrectCFAOffset(MachineBasicBlock *
MBB) {
186 void reportCFAError(
const MBBCFAInfo &Pred,
const MBBCFAInfo &Succ);
187 void reportCSRError(
const MBBCFAInfo &Pred,
const MBBCFAInfo &Succ);
199 CFIInstrInserterLegacy() : MachineFunctionPass(ID) {}
201 void getAnalysisUsage(AnalysisUsage &AU)
const override {
207 return CFIInstrInserterImpl().run(MF);
212char CFIInstrInserterLegacy::ID = 0;
214 "Check CFA info and insert CFI instructions if needed",
false,
217 return new CFIInstrInserterLegacy();
223 CFIInstrInserterImpl().run(MF);
237 unsigned DwarfInitialRegister =
TRI.getDwarfRegNum(InitialRegister,
true);
238 unsigned NumRegs =
TRI.getNumSupportedRegs(MF);
244 MBBInfo.IncomingCFAOffset = InitialOffset;
245 MBBInfo.OutgoingCFAOffset = InitialOffset;
246 MBBInfo.IncomingCFARegister = DwarfInitialRegister;
247 MBBInfo.OutgoingCFARegister = DwarfInitialRegister;
248 MBBInfo.IncomingCSRSaved.resize(NumRegs);
249 MBBInfo.OutgoingCSRSaved.resize(NumRegs);
257 updateSuccCFAInfo(
MBBVector[MF.front().getNumber()]);
260void CFIInstrInserterImpl::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
262 int64_t SetOffset = MBBInfo.IncomingCFAOffset;
264 unsigned SetRegister = MBBInfo.IncomingCFARegister;
268 unsigned NumRegs =
TRI.getNumSupportedRegs(*MF);
269 BitVector CSRSaved(NumRegs), CSRRestored(NumRegs);
272 int RememberState = 0;
277 if (
MI.isCFIInstruction()) {
278 std::optional<unsigned> CSRReg;
279 std::optional<int64_t> CSROffset;
280 unsigned CFIIndex =
MI.getOperand(0).getCFIIndex();
312 "Support for cfi_llvm_def_aspace_cfa not implemented! Value of CFA "
313 "may be incorrect!\n");
322 if (RememberState != 1)
325 "Support for cfi_remember_state not implemented! Value of CFA "
326 "may be incorrect!\n");
333 if (RememberState != 0)
336 "Support for cfi_restore_state not implemented! Value of CFA may "
357 assert((!CSRReg.has_value() || !CSROffset.has_value()) &&
358 "A register can only be at an offset from CFA or in another "
359 "register, but not both!");
360 CSRSavedLocation CSRLoc;
362 CSRLoc = CSRSavedLocation::createRegister(*CSRReg);
364 CSRLoc = CSRSavedLocation::createCFAOffset(*CSROffset);
365 if (CSRLoc.isValid()) {
367 if (!Inserted && It->second != CSRLoc)
369 "Different saved locations for the same CSR");
376 if (RememberState != 0)
379 "Support for cfi_remember_state not implemented! Value of CFA may be "
383 MBBInfo.Processed =
true;
386 MBBInfo.OutgoingCFAOffset = SetOffset;
391 MBBInfo.OutgoingCSRSaved, MBBInfo.IncomingCSRSaved, CSRSaved,
395void CFIInstrInserterImpl::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) {
397 Stack.push_back(MBBInfo.MBB);
402 calculateOutgoingCFAInfo(CurrentInfo);
403 for (
auto *Succ : CurrentInfo.MBB->successors()) {
404 MBBCFAInfo &SuccInfo =
MBBVector[Succ->getNumber()];
405 if (!SuccInfo.Processed) {
406 SuccInfo.IncomingCFAOffset = CurrentInfo.OutgoingCFAOffset;
407 SuccInfo.IncomingCFARegister = CurrentInfo.OutgoingCFARegister;
408 SuccInfo.IncomingCSRSaved = CurrentInfo.OutgoingCSRSaved;
409 Stack.push_back(Succ);
412 }
while (!
Stack.empty());
418 bool InsertedCFIInstr =
false;
423 if (
MBB.
getNumber() == MF.front().getNumber())
continue;
426 auto MBBI = MBBInfo.MBB->begin();
433 if ((PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset &&
434 PrevMBBInfo->OutgoingCFARegister != MBBInfo.IncomingCFARegister) ||
441 nullptr, MBBInfo.IncomingCFARegister, getCorrectCFAOffset(&
MBB)));
444 InsertedCFIInstr =
true;
445 }
else if (PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset) {
450 nullptr, getCorrectCFAOffset(&
MBB)));
453 InsertedCFIInstr =
true;
454 }
else if (PrevMBBInfo->OutgoingCFARegister !=
455 MBBInfo.IncomingCFARegister) {
458 nullptr, MBBInfo.IncomingCFARegister));
461 InsertedCFIInstr =
true;
465 MF.getSubtarget().getFrameLowering()->emitCalleeSavedFrameMovesFullCFA(
467 InsertedCFIInstr =
true;
468 PrevMBBInfo = &MBBInfo;
473 PrevMBBInfo->OutgoingCSRSaved, MBBInfo.IncomingCSRSaved);
479 InsertedCFIInstr =
true;
483 MBBInfo.IncomingCSRSaved, PrevMBBInfo->OutgoingCSRSaved);
486 assert(it != CSRLocMap.
end() &&
"Reg should have an entry in CSRLocMap");
488 CSRSavedLocation RO = it->second;
490 case CSRSavedLocation::CFAOffset: {
491 CFIIndex = MF.addFrameInst(
495 case CSRSavedLocation::Register: {
496 CFIIndex = MF.addFrameInst(
505 InsertedCFIInstr =
true;
508 PrevMBBInfo = &MBBInfo;
510 return InsertedCFIInstr;
513void CFIInstrInserterImpl::reportCFAError(
const MBBCFAInfo &Pred,
514 const MBBCFAInfo &Succ) {
515 errs() <<
"*** Inconsistent CFA register and/or offset between pred and succ "
517 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
518 <<
" in " << Pred.MBB->getParent()->getName()
519 <<
" outgoing CFA Reg:" << Pred.OutgoingCFARegister <<
"\n";
520 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
521 <<
" in " << Pred.MBB->getParent()->getName()
522 <<
" outgoing CFA Offset:" << Pred.OutgoingCFAOffset <<
"\n";
523 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
524 <<
" incoming CFA Reg:" << Succ.IncomingCFARegister <<
"\n";
525 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
526 <<
" incoming CFA Offset:" << Succ.IncomingCFAOffset <<
"\n";
529void CFIInstrInserterImpl::reportCSRError(
const MBBCFAInfo &Pred,
530 const MBBCFAInfo &Succ) {
531 errs() <<
"*** Inconsistent CSR Saved between pred and succ in function "
532 << Pred.MBB->getParent()->getName() <<
" ***\n";
533 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
534 <<
" outgoing CSR Saved: ";
535 for (
int Reg : Pred.OutgoingCSRSaved.set_bits())
538 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
539 <<
" incoming CSR Saved: ";
540 for (
int Reg : Succ.IncomingCSRSaved.set_bits())
546 unsigned ErrorNum = 0;
548 const MBBCFAInfo &CurrMBBInfo =
MBBVector[CurrMBB->getNumber()];
550 const MBBCFAInfo &SuccMBBInfo =
MBBVector[Succ->getNumber()];
553 if (SuccMBBInfo.IncomingCFAOffset != CurrMBBInfo.OutgoingCFAOffset ||
554 SuccMBBInfo.IncomingCFARegister != CurrMBBInfo.OutgoingCFARegister) {
557 if (SuccMBBInfo.MBB->succ_empty() && !SuccMBBInfo.MBB->isReturnBlock())
559 reportCFAError(CurrMBBInfo, SuccMBBInfo);
564 if (SuccMBBInfo.IncomingCSRSaved != CurrMBBInfo.OutgoingCSRSaved) {
565 reportCSRError(CurrMBBInfo, SuccMBBInfo);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
SmallVector< MachineBasicBlock *, 4 > MBBVector
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static MachineInstr * SetRegister(MachineInstr &I, Register *TLSBaseAddrReg)
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)
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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
@ OpLLVMVectorRegisterMask
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
int64_t getOffset() const
LLVM_ABI 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...
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.
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
bool usesWindowsUnwindInfo() const
True if this function describes its unwind information with Windows SEH unwind opcodes (....
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.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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 TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
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.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool operator!=(uint64_t V1, const APInt &V2)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
LLVM_ABI FunctionPass * createCFIInstrInserterLegacy()
Creates CFI Instruction Inserter pass.
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
MCCFIInstruction createCFAOffset(const TargetRegisterInfo &MRI, unsigned Reg, const StackOffset &OffsetFromDefCFA, std::optional< int64_t > IncomingVGOffsetFromDefCFA)
iterator_range< df_iterator< T > > depth_first(const T &G)