42 return Reg == RHS.Reg &&
Offset == RHS.Offset;
46static std::optional<CFARegOffsetInfo>
49 if (CFALocation.getLocation() !=
59 assert(MaybeLoc &&
"the register should be included in the unwinding row");
62 switch (
Loc.getLocation()) {
78 return {
Loc.getRegister()};
86 : State(Context), Context(Context), MCII(MCII),
87 MCRI(Context->getRegisterInfo()), IsEH(IsEH) {
90 if (MCRI->get(LLVMReg).IsArtificial || MCRI->get(LLVMReg).IsConstant)
93 DWARFRegNum Reg = MCRI->getDwarfRegNum(LLVMReg, IsEH);
104 nullptr, MCRI->getDwarfRegNum(MCRI->getProgramCounter(), IsEH)));
106 for (
auto &&InitialFrameStateCFIDirective :
107 Context->getAsmInfo().getInitialFrameState())
108 State.update(InitialFrameStateCFIDirective);
119 auto MaybePrevRow = State.getCurrentUnwindRow();
120 assert(MaybePrevRow &&
"the analysis should have initialized the "
121 "state with at least one row by now");
122 auto PrevRow = *MaybePrevRow;
129 Writes.
insert(MCRI->getDwarfRegNum(
141 auto MaybeNextRow = State.getCurrentUnwindRow();
142 assert(MaybeNextRow &&
"previous row existed, so should the current row");
143 auto NextRow = *MaybeNextRow;
145 checkCFADiff(Inst, PrevRow, NextRow, Writes);
148 DWARFRegNum Reg = MCRI->getDwarfRegNum(LLVMReg, IsEH);
150 checkRegDiff(Inst, Reg, PrevRow, NextRow, Writes);
164 assert(!MaybeNextLoc &&
"the register unwind info suddenly appeared here");
167 assert(MaybeNextLoc &&
"the register unwind info suddenly vanished here");
169 auto PrevLoc = MaybePrevLoc.value();
170 auto NextLoc = MaybeNextLoc.value();
174 if (!(PrevLoc == NextLoc))
175 Context->reportWarning(
177 formatv(
"the dwarf register {0} does not have a LLVM number, but its "
178 "unwind info changed. Ignoring this change",
182 const char *
RegName = MCRI->getName(*MaybeLLVMReg);
192 if (PrevLoc == NextLoc) {
194 if (Writes.
count(UsedReg)) {
195 auto MaybeLLVMUsedReg = MCRI->getLLVMRegNum(UsedReg, IsEH);
196 assert(MaybeLLVMUsedReg &&
"instructions will always write to a "
197 "register that has an LLVM register number");
198 Context->reportError(
200 formatv(
"changed register {1}, that register {0}'s unwinding rule "
201 "uses, but there is no CFI directives about it",
202 RegName, MCRI->getName(*MaybeLLVMUsedReg)));
208 if (PrevLoc.getLocation() != NextLoc.getLocation()) {
209 Context->reportWarning(
211 formatv(
"validating changes happening to register {0} unwinding "
212 "rule structure is not implemented yet",
218 Context->reportWarning(
220 formatv(
"validating changes happening to register {0} unwinding "
221 "rule register set is not implemented yet",
227 if (Writes.
count(UsedReg)) {
228 Context->reportWarning(
230 formatv(
"register {0} unwinding rule's offset is changed, and one of "
231 "the rule's registers is modified, but validating the "
232 "modification amount is not implemented yet",
237 Context->reportError(
238 Inst.
getLoc(),
formatv(
"register {0} unwinding rule's offset is changed, "
239 "but not any of the rule's registers are modified",
243void DWARFCFIAnalysis::checkCFADiff(
const MCInst &Inst,
253 Context->reportWarning(Inst.
getLoc(),
254 "CFA rule changed to [reg + offset], this "
255 "transition will not be checked");
259 Context->reportWarning(Inst.
getLoc(),
260 "CFA rule is not [reg + offset], not checking it");
265 Context->reportWarning(Inst.
getLoc(),
266 "CFA rule changed from [reg + offset], this "
267 "transition will not be checked");
271 auto PrevCFA = *MaybePrevCFA;
272 auto NextCFA = *MaybeNextCFA;
274 auto MaybeLLVMPrevReg = MCRI->getLLVMRegNum(PrevCFA.Reg, IsEH);
275 const char *PrevCFARegName =
276 MaybeLLVMPrevReg ? MCRI->getName(*MaybeLLVMPrevReg) :
"";
277 auto MaybeLLVMNextReg = MCRI->getLLVMRegNum(NextCFA.Reg, IsEH);
278 const char *NextCFARegName =
279 MaybeLLVMNextReg ? MCRI->getName(*MaybeLLVMNextReg) :
"";
281 if (PrevCFA == NextCFA) {
282 if (!Writes.
count(PrevCFA.Reg))
285 Context->reportError(
287 formatv(
"modified CFA register {0} but not changed CFA rule",
292 if (PrevCFA.Reg != NextCFA.Reg) {
293 Context->reportWarning(
295 formatv(
"CFA register changed from register {0} to register {1}, "
296 "validating this change is not implemented yet",
297 PrevCFARegName, NextCFARegName));
301 if (Writes.
count(PrevCFA.Reg)) {
302 Context->reportWarning(
303 Inst.
getLoc(),
formatv(
"CFA offset is changed from {0} to {1}, and CFA "
304 "register {2} is modified, but validating the "
305 "modification amount is not implemented yet",
306 PrevCFA.Offset, NextCFA.Offset, PrevCFARegName));
310 Context->reportError(
312 formatv(
"did not modify CFA register {0} but changed CFA rule",
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static std::optional< CFARegOffsetInfo > getCFARegOffsetInfo(const dwarf::UnwindRow &UnwindRow)
static SmallSet< DWARFRegNum, 4 > getUnwindRuleRegSet(const dwarf::UnwindRow &UnwindRow, DWARFRegNum Reg)
This file declares DWARFCFIAnalysis class.
This file declares DWARFCFIState class.
This file contains helper functions to find and list registers that are tracked by the unwinding info...
This file defines the SmallSet class.
This file defines the SmallVector class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM_ABI void update(const MCInst &Inst, ArrayRef< MCCFIInstruction > Directives)
LLVM_ABI DWARFCFIAnalysis(MCContext *Context, MCInstrInfo const &MCII, bool IsEH, ArrayRef< MCCFIInstruction > Prologue)
static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_undefined From now on the previous value of Register can't be restored anymore.
Context object for machine code objects.
Instances of this class represent a single low-level machine instruction.
unsigned getNumOperands() const
unsigned getOpcode() const
const MCOperand & getOperand(unsigned i) const
Describe properties that are true of each instruction in the target description file.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
ArrayRef< MCPhysReg > implicit_defs() const
Return a list of registers that are potentially written by any instance of this machine instruction.
Interface to description of machine instruction set.
std::optional< MCRegister > getLLVMRegNum(uint64_t RegNum, bool isEH) const
Map a dwarf register back to a target register.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
std::optional< UnwindLocation > getRegisterLocation(uint32_t RegNum) const
Return the location for the register in RegNum if there is a location.
@ Undefined
Register is not available and can't be recovered.
@ Constant
Value is a constant value contained in "Offset": reg = Offset.
@ DWARFExpr
Register or CFA value is in or at a value found by evaluating a DWARF expression: reg = eval(dwarf_ex...
@ Same
Register value is in the register, nothing needs to be done to unwind it: reg = reg.
@ CFAPlusOffset
Register is in or at the CFA plus an offset: reg = CFA + offset reg = defef(CFA + offset)
@ Unspecified
Not specified.
@ RegPlusOffset
Register or CFA is in or at a register plus offset, optionally in an address space: reg = reg + offse...
A class that represents a single row in the unwind table that is decoded by parsing the DWARF Call Fr...
UnwindLocation & getCFAValue()
RegisterLocations & getRegisterLocations()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
SmallVector< MCPhysReg > getTrackingRegs(const MCRegisterInfo *MCRI)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
DWARFExpression::Operation Op
MCRegister getSuperReg(const MCRegisterInfo *MCRI, MCRegister Reg)
bool operator==(const CFARegOffsetInfo &RHS) const
CFARegOffsetInfo(DWARFRegNum Reg, int64_t Offset)