46static std::optional<CFARegOffsetInfo>
49 if (CFALocation.getLocation() !=
50 dwarf::UnwindLocation::Location::RegPlusOffset)
59 assert(MaybeLoc &&
"the register should be included in the unwinding row");
62 switch (Loc.getLocation()) {
63 case dwarf::UnwindLocation::Location::Unspecified:
64 case dwarf::UnwindLocation::Location::Undefined:
65 case dwarf::UnwindLocation::Location::Constant:
66 case dwarf::UnwindLocation::Location::CFAPlusOffset:
70 case dwarf::UnwindLocation::Location::DWARFExpr:
75 case dwarf::UnwindLocation::Location::Same:
77 case dwarf::UnwindLocation::Location::RegPlusOffset:
78 return {Loc.getRegister()};
87 MCRI(
Context->getRegisterInfo()), IsEH(IsEH) {
105 for (
auto &&InitialFrameStateCFIDirective :
106 Context->getAsmInfo()->getInitialFrameState())
107 State.
update(InitialFrameStateCFIDirective);
110 assert(MaybeCurrentRow &&
"there should be at least one row");
113 "the CFA information should be describable in [reg + offset] in here");
114 auto CFA = *MaybeCFA;
130 assert(MaybePrevRow &&
"the analysis should have initialized the "
131 "state with at least one row by now");
132 auto PrevRow = *MaybePrevRow;
151 else if (
Op.getReg())
158 assert(MaybeNextRow &&
"previous row existed, so should the current row");
159 auto NextRow = *MaybeNextRow;
161 checkCFADiff(Inst, PrevRow, NextRow, Reads,
Writes);
166 checkRegDiff(Inst, Reg, PrevRow, NextRow, Reads,
Writes);
181 assert(!MaybeNextLoc &&
"the register unwind info suddenly appeared here");
184 assert(MaybeNextLoc &&
"the register unwind info suddenly vanished here");
186 auto PrevLoc = MaybePrevLoc.value();
187 auto NextLoc = MaybeNextLoc.value();
191 if (!(PrevLoc == NextLoc))
194 formatv(
"the dwarf register {0} does not have a LLVM number, but its "
195 "unwind info changed. Ignoring this change",
209 if (PrevLoc == NextLoc) {
211 if (
Writes.count(UsedReg)) {
213 assert(MaybeLLVMUsedReg &&
"instructions will always write to a "
214 "register that has an LLVM register number");
217 formatv(
"changed register {1}, that register {0}'s unwinding rule "
218 "uses, but there is no CFI directives about it",
225 if (PrevLoc.getLocation() != NextLoc.getLocation()) {
228 formatv(
"validating changes happening to register {0} unwinding "
229 "rule structure is not implemented yet",
237 formatv(
"validating changes happening to register {0} unwinding "
238 "rule register set is not implemented yet",
244 if (
Writes.count(UsedReg)) {
247 formatv(
"register {0} unwinding rule's offset is changed, and one of "
248 "the rule's registers is modified, but validating the "
249 "modification amount is not implemented yet",
255 Inst.
getLoc(),
formatv(
"register {0} unwinding rule's offset is changed, "
256 "but not any of the rule's registers are modified",
260void DWARFCFIAnalysis::checkCFADiff(
const MCInst &Inst,
272 "CFA rule changed to [reg + offset], this "
273 "transition will not be checked");
278 "CFA rule is not [reg + offset], not checking it");
284 "CFA rule changed from [reg + offset], this "
285 "transition will not be checked");
289 auto PrevCFA = *MaybePrevCFA;
290 auto NextCFA = *MaybeNextCFA;
292 auto MaybeLLVMPrevReg = MCRI->
getLLVMRegNum(PrevCFA.Reg, IsEH);
293 const char *PrevCFARegName =
294 MaybeLLVMPrevReg ? MCRI->
getName(*MaybeLLVMPrevReg) :
"";
295 auto MaybeLLVMNextReg = MCRI->
getLLVMRegNum(NextCFA.Reg, IsEH);
296 const char *NextCFARegName =
297 MaybeLLVMNextReg ? MCRI->
getName(*MaybeLLVMNextReg) :
"";
299 if (PrevCFA == NextCFA) {
300 if (!
Writes.count(PrevCFA.Reg))
305 formatv(
"modified CFA register {0} but not changed CFA rule",
310 if (PrevCFA.Reg != NextCFA.Reg) {
313 formatv(
"CFA register changed from register {0} to register {1}, "
314 "validating this change is not implemented yet",
315 PrevCFARegName, NextCFARegName));
319 if (
Writes.count(PrevCFA.Reg)) {
321 Inst.
getLoc(),
formatv(
"CFA offset is changed from {0} to {1}, and CFA "
322 "register {2} is modified, but validating the "
323 "modification amount is not implemented yet",
324 PrevCFA.Offset, NextCFA.Offset, PrevCFARegName));
330 formatv(
"did not modify CFA register {0} but changed CFA rule",
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.
SmallVector< uint32_t, 0 > Writes
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.
ArrayRef - 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)
LLVM_ABI std::optional< dwarf::UnwindRow > getCurrentUnwindRow() const
LLVM_ABI void update(const MCCFIInstruction &Directive)
This method updates the state by applying Directive to the current state.
This class represents an Operation in the Expression.
static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_undefined From now on the previous value of Register can't be restored anymore.
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.
static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_same_value Current value of Register is the same as in the previous frame.
Context object for machine code objects.
LLVM_ABI void reportWarning(SMLoc L, const Twine &Msg)
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
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 char NumImplicitUses
unsigned char NumImplicitDefs
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.
ArrayRef< MCPhysReg > implicit_uses() const
Return a list of registers that are potentially read by any instance of this machine instruction.
Interface to description of machine instruction set.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
MCRegister getProgramCounter() const
Return the register which is the program counter.
const MCRegisterDesc & get(MCRegister Reg) const
Provide a get method, equivalent to [], but more useful with a pointer to this object.
const char * getName(MCRegister RegNo) const
Return the human-readable symbolic target-specific name for the specified physical register.
virtual int64_t getDwarfRegNum(MCRegister RegNum, bool isEH) const
Map a target register to an equivalent dwarf register number.
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...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
iterator insert(iterator I, T &&Elt)
std::optional< UnwindLocation > getRegisterLocation(uint32_t RegNum) const
Return the location for the register in RegNum if there is a location.
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)
MCPhysReg getSuperReg(const MCRegisterInfo *MCRI, MCPhysReg Reg)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
bool operator==(const CFARegOffsetInfo &RHS) const
CFARegOffsetInfo(DWARFRegNum Reg, int64_t Offset)