33 cl::desc(
"Verify Call Frame Information instructions"),
60 if (
unsigned ErrorNum =
verify(MF))
62 " in/out CFI information errors.");
64 bool insertedCFI = insertCFIInstrs(MF);
73 int IncomingCFAOffset = -1;
75 int OutgoingCFAOffset = -1;
77 unsigned IncomingCFARegister = 0;
79 unsigned OutgoingCFARegister = 0;
82 bool Processed =
false;
95 void calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo);
98 void updateSuccCFAInfo(MBBCFAInfo &MBBInfo);
109 return -MBBVector[MBB->
getNumber()].IncomingCFAOffset;
112 void report(
const MBBCFAInfo &Pred,
const MBBCFAInfo &Succ);
123 "Check CFA info and insert CFI instructions if needed",
false,
134 unsigned InitialRegister =
141 MBBInfo.IncomingCFAOffset = InitialOffset;
142 MBBInfo.OutgoingCFAOffset = InitialOffset;
143 MBBInfo.IncomingCFARegister = InitialRegister;
144 MBBInfo.OutgoingCFARegister = InitialRegister;
153 if (
MBBVector[MBB.getNumber()].Processed)
continue;
154 updateSuccCFAInfo(
MBBVector[MBB.getNumber()]);
158 void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
160 int SetOffset = MBBInfo.IncomingCFAOffset;
162 unsigned SetRegister = MBBInfo.IncomingCFARegister;
163 const std::vector<MCCFIInstruction> &Instrs =
164 MBBInfo.MBB->getParent()->getFrameInstructions();
189 "Support for cfi_remember_state not implemented! Value of CFA " 190 "may be incorrect!\n");
197 "Support for cfi_restore_state not implemented! Value of CFA may " 217 MBBInfo.Processed =
true;
220 MBBInfo.OutgoingCFAOffset = SetOffset;
221 MBBInfo.OutgoingCFARegister = SetRegister;
224 void CFIInstrInserter::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) {
231 if (CurrentInfo.Processed)
234 calculateOutgoingCFAInfo(CurrentInfo);
235 for (
auto *Succ : CurrentInfo.MBB->successors()) {
236 MBBCFAInfo &SuccInfo =
MBBVector[Succ->getNumber()];
237 if (!SuccInfo.Processed) {
238 SuccInfo.IncomingCFAOffset = CurrentInfo.OutgoingCFAOffset;
239 SuccInfo.IncomingCFARegister = CurrentInfo.OutgoingCFARegister;
243 }
while (!Stack.
empty());
249 bool InsertedCFIInstr =
false;
253 if (MBB.getNumber() == MF.front().getNumber())
continue;
255 const MBBCFAInfo &MBBInfo =
MBBVector[MBB.getNumber()];
256 auto MBBI = MBBInfo.MBB->begin();
257 DebugLoc DL = MBBInfo.MBB->findDebugLoc(MBBI);
259 if (PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset) {
263 if (PrevMBBInfo->OutgoingCFARegister != MBBInfo.IncomingCFARegister) {
265 nullptr, MBBInfo.IncomingCFARegister, getCorrectCFAOffset(&MBB)));
266 BuildMI(*MBBInfo.MBB, MBBI, DL, TII->
get(TargetOpcode::CFI_INSTRUCTION))
267 .addCFIIndex(CFIIndex);
274 nullptr, getCorrectCFAOffset(&MBB)));
275 BuildMI(*MBBInfo.MBB, MBBI, DL, TII->
get(TargetOpcode::CFI_INSTRUCTION))
276 .addCFIIndex(CFIIndex);
278 InsertedCFIInstr =
true;
282 }
else if (PrevMBBInfo->OutgoingCFARegister !=
283 MBBInfo.IncomingCFARegister) {
286 nullptr, MBBInfo.IncomingCFARegister));
287 BuildMI(*MBBInfo.MBB, MBBI, DL, TII->
get(TargetOpcode::CFI_INSTRUCTION))
288 .addCFIIndex(CFIIndex);
289 InsertedCFIInstr =
true;
291 PrevMBBInfo = &MBBInfo;
293 return InsertedCFIInstr;
296 void CFIInstrInserter::report(
const MBBCFAInfo &Pred,
const MBBCFAInfo &Succ) {
297 errs() <<
"*** Inconsistent CFA register and/or offset between pred and succ " 299 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
300 <<
" in " << Pred.MBB->getParent()->getName()
301 <<
" outgoing CFA Reg:" << Pred.OutgoingCFARegister <<
"\n";
302 errs() <<
"Pred: " << Pred.MBB->getName() <<
" #" << Pred.MBB->getNumber()
303 <<
" in " << Pred.MBB->getParent()->getName()
304 <<
" outgoing CFA Offset:" << Pred.OutgoingCFAOffset <<
"\n";
305 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
306 <<
" incoming CFA Reg:" << Succ.IncomingCFARegister <<
"\n";
307 errs() <<
"Succ: " << Succ.MBB->getName() <<
" #" << Succ.MBB->getNumber()
308 <<
" incoming CFA Offset:" << Succ.IncomingCFAOffset <<
"\n";
312 unsigned ErrorNum = 0;
314 const MBBCFAInfo &CurrMBBInfo =
MBBVector[CurrMBB->getNumber()];
316 const MBBCFAInfo &SuccMBBInfo =
MBBVector[Succ->getNumber()];
319 if (SuccMBBInfo.IncomingCFAOffset != CurrMBBInfo.OutgoingCFAOffset ||
320 SuccMBBInfo.IncomingCFARegister != CurrMBBInfo.OutgoingCFARegister) {
323 if (SuccMBBInfo.MBB->succ_empty() && !SuccMBBInfo.MBB->isReturnBlock())
325 report(CurrMBBInfo, SuccMBBInfo);
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
bool hasDebugInfo() const
Returns true if valid debug info is present.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
bool isCFIInstruction() const
void push_back(const T &Elt)
MachineModuleInfo & getMMI() const
static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset)
.cfi_def_cfa_offset modifies a rule for computing CFA.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
const HexagonInstrInfo * TII
unsigned getCFIIndex() const
SmallVector< MachineBasicBlock *, 4 > MBBVector
static cl::opt< bool > VerifyCFI("verify-cfiinstrs", cl::desc("Verify Call Frame Information instructions"), cl::init(false), cl::Hidden)
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
virtual const TargetInstrInfo * getInstrInfo() const
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
static MCCFIInstruction createDefCfa(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...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register)
.cfi_def_cfa_register modifies a rule for computing CFA.
Represent the analysis usage information of a pass.
OpType getOperation() const
FunctionPass class - This class is used to implement most global optimizations.
void initializeCFIInstrInserterPass(PassRegistry &)
const MachineBasicBlock & front() const
bool verify(const TargetRegisterInfo &TRI) const
Check that information hold by this instance make sense for the given TRI.
unsigned getRegister() const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
LLVM_NODISCARD T pop_back_val()
const Function & getFunction() const
Return the LLVM function that this machine code represents.
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
void setPreservesAll()
Set by analyses that do not transform their input at all.
Representation of each machine instruction.
LLVM_NODISCARD bool empty() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
INITIALIZE_PASS(CFIInstrInserter, "cfi-instr-inserter", "Check CFA info and insert CFI instructions if needed", false, false) FunctionPass *llvm
virtual const TargetFrameLowering * getFrameLowering() const
iterator_range< df_iterator< T > > depth_first(const T &G)
const MachineOperand & getOperand(unsigned i) const
FunctionPass * createCFIInstrInserter()
Creates CFI Instruction Inserter pass.
virtual int getInitialCFAOffset(const MachineFunction &MF) const
Return initial CFA offset value i.e.
virtual unsigned getInitialCFARegister(const MachineFunction &MF) const
Return initial CFA register value i.e.