41 std::optional<uint32_t> AddrSpace) {
47 std::optional<uint32_t> AddrSpace) {
68 return Offset ==
RHS.Offset && Dereference ==
RHS.Dereference;
70 return RegNum ==
RHS.RegNum && Offset ==
RHS.Offset &&
71 Dereference ==
RHS.Dereference;
73 return *Expr == *
RHS.Expr && Dereference ==
RHS.Dereference;
75 return Offset ==
RHS.Offset;
87 std::vector<std::pair<UnwindLocation, RegisterLocations>> States;
89 switch (Inst.Opcode) {
90 case dwarf::DW_CFA_set_loc: {
101 if (*NewAddress <= Row.getAddress())
104 "%s with adrress 0x%" PRIx64
" which must be greater than the "
105 "current row address 0x%" PRIx64,
109 Row.setAddress(*NewAddress);
113 case dwarf::DW_CFA_advance_loc:
114 case dwarf::DW_CFA_advance_loc1:
115 case dwarf::DW_CFA_advance_loc2:
116 case dwarf::DW_CFA_advance_loc4: {
126 return Offset.takeError();
127 Row.slideAddress(*
Offset);
131 case dwarf::DW_CFA_restore:
132 case dwarf::DW_CFA_restore_extended: {
137 if (InitialLocs ==
nullptr)
144 if (std::optional<UnwindLocation> O =
146 Row.getRegisterLocations().setRegisterLocation(*RegNum, *O);
148 Row.getRegisterLocations().removeRegisterLocation(*RegNum);
152 case dwarf::DW_CFA_offset:
153 case dwarf::DW_CFA_offset_extended:
154 case dwarf::DW_CFA_offset_extended_sf: {
160 return Offset.takeError();
161 Row.getRegisterLocations().setRegisterLocation(
166 case dwarf::DW_CFA_nop:
169 case dwarf::DW_CFA_remember_state:
171 std::make_pair(Row.getCFAValue(), Row.getRegisterLocations()));
174 case dwarf::DW_CFA_restore_state:
177 "DW_CFA_restore_state without a matching "
178 "previous DW_CFA_remember_state");
179 Row.getCFAValue() = States.back().first;
180 Row.getRegisterLocations() = States.back().second;
184 case dwarf::DW_CFA_GNU_window_save:
195 constexpr uint32_t AArch64DWARFPAuthRaState = 34;
196 auto LRLoc = Row.getRegisterLocations().getRegisterLocation(
197 AArch64DWARFPAuthRaState);
201 LRLoc->setConstant(LRLoc->getConstant() ^ 1);
202 Row.getRegisterLocations().setRegisterLocation(
203 AArch64DWARFPAuthRaState, *LRLoc);
207 "%s encountered when existing rule for this register is not "
212 Row.getRegisterLocations().setRegisterLocation(
221 for (
uint32_t RegNum = 16; RegNum < 32; ++RegNum) {
222 Row.getRegisterLocations().setRegisterLocation(
230 "DW_CFA opcode %#x is not supported for architecture %s",
238 case dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc: {
239 constexpr uint32_t AArch64DWARFPAuthRaState = 34;
240 auto LRLoc = Row.getRegisterLocations().getRegisterLocation(
241 AArch64DWARFPAuthRaState);
245 LRLoc->setConstant(LRLoc->getConstant() ^ 0x3);
249 "%s encountered when existing rule for this register is not "
254 Row.getRegisterLocations().setRegisterLocation(
260 case dwarf::DW_CFA_undefined: {
264 Row.getRegisterLocations().setRegisterLocation(
269 case dwarf::DW_CFA_same_value: {
273 Row.getRegisterLocations().setRegisterLocation(
278 case dwarf::DW_CFA_GNU_args_size:
281 case dwarf::DW_CFA_register: {
288 Row.getRegisterLocations().setRegisterLocation(
293 case dwarf::DW_CFA_val_offset:
294 case dwarf::DW_CFA_val_offset_sf: {
300 return Offset.takeError();
301 Row.getRegisterLocations().setRegisterLocation(
306 case dwarf::DW_CFA_expression: {
310 Row.getRegisterLocations().setRegisterLocation(
315 case dwarf::DW_CFA_val_expression: {
319 Row.getRegisterLocations().setRegisterLocation(
324 case dwarf::DW_CFA_def_cfa_register: {
332 Row.getCFAValue().setRegister(*RegNum);
336 case dwarf::DW_CFA_def_cfa_offset:
337 case dwarf::DW_CFA_def_cfa_offset_sf: {
340 return Offset.takeError();
344 "%s found when CFA rule was not RegPlusOffset",
347 Row.getCFAValue().setOffset(*
Offset);
351 case dwarf::DW_CFA_def_cfa:
352 case dwarf::DW_CFA_def_cfa_sf: {
358 return Offset.takeError();
364 case dwarf::DW_CFA_LLVM_def_aspace_cfa:
365 case dwarf::DW_CFA_LLVM_def_aspace_cfa_sf: {
371 return Offset.takeError();
373 Inst.getOperandAsUnsigned(CFIP, 2);
377 *RegNum, *
Offset, *CFAAddrSpace);
381 case dwarf::DW_CFA_def_cfa_expression:
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
std::string str() const
str - Get the contents as an std::string.
static LLVM_ABI StringRef getArchTypeName(ArchType Kind)
Get the canonical name for the Kind architecture.
LLVM Value Representation.
Represent a sequence of Call Frame Information instructions that, when read in order,...
Triple::ArchType triple() const
LLVM_ABI StringRef callFrameString(unsigned Opcode) const
Get a DWARF CFI call frame string for the given DW_CFA opcode.
A class that can track all registers with locations in a UnwindRow object.
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 location for the Call Frame Address (CFA) or a register.
static LLVM_ABI UnwindLocation createUndefined()
Create a location where the value is undefined and not available.
static LLVM_ABI UnwindLocation createAtRegisterPlusOffset(uint32_t Reg, int32_t Off, std::optional< uint32_t > AddrSpace=std::nullopt)
static LLVM_ABI UnwindLocation createIsRegisterPlusOffset(uint32_t Reg, int32_t Off, std::optional< uint32_t > AddrSpace=std::nullopt)
Create a location where the saved value is in (Deref == false) or at (Deref == true) a regiser plus a...
static LLVM_ABI UnwindLocation createAtDWARFExpression(DWARFExpression Expr)
static LLVM_ABI UnwindLocation createUnspecified()
Create a location whose rule is set to Unspecified.
LLVM_ABI bool operator==(const UnwindLocation &RHS) const
static LLVM_ABI UnwindLocation createIsDWARFExpression(DWARFExpression Expr)
Create a location whose value is the result of evaluating a DWARF expression.
@ 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...
static LLVM_ABI UnwindLocation createIsConstant(int32_t Value)
static LLVM_ABI UnwindLocation createAtCFAPlusOffset(int32_t Off)
static LLVM_ABI UnwindLocation createSame()
Create a location where the value is known to be in the register itself.
static LLVM_ABI UnwindLocation createIsCFAPlusOffset(int32_t Off)
Create a location that is in (Deref == false) or at (Deref == true) the CFA plus an offset.
A class that represents a single row in the unwind table that is decoded by parsing the DWARF Call Fr...
std::vector< UnwindRow > RowContainer
constexpr uint32_t InvalidRegisterNumber
LLVM_ABI Expected< UnwindTable::RowContainer > parseRows(const CFIProgram &CFIP, UnwindRow &CurrRow, const RegisterLocations *InitialLocs)
Parse the information in the CFIProgram and update the CurrRow object that the state machine describe...
This is an optimization pass for GlobalISel generic memory operations.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
An instruction consists of a DWARF CFI opcode and an optional sequence of operands.