LLVM 22.0.0git
DWARFExpression.cpp
Go to the documentation of this file.
1//===-- DWARFExpression.cpp -----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include <cassert>
11#include <cstdint>
12#include <vector>
13
14using namespace llvm;
15using namespace dwarf;
16
17namespace llvm {
18
20typedef Op::Description Desc;
21
22static std::vector<Desc> getOpDescriptions() {
23 std::vector<Desc> Descriptions;
24 Descriptions.resize(0xff);
25 Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr);
26 Descriptions[DW_OP_deref] = Desc(Op::Dwarf2);
27 Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1);
28 Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1);
29 Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2);
30 Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2);
31 Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4);
32 Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4);
33 Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8);
34 Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8);
35 Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB);
36 Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
37 Descriptions[DW_OP_dup] = Desc(Op::Dwarf2);
38 Descriptions[DW_OP_drop] = Desc(Op::Dwarf2);
39 Descriptions[DW_OP_over] = Desc(Op::Dwarf2);
40 Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1);
41 Descriptions[DW_OP_swap] = Desc(Op::Dwarf2);
42 Descriptions[DW_OP_rot] = Desc(Op::Dwarf2);
43 Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2);
44 Descriptions[DW_OP_abs] = Desc(Op::Dwarf2);
45 Descriptions[DW_OP_and] = Desc(Op::Dwarf2);
46 Descriptions[DW_OP_div] = Desc(Op::Dwarf2);
47 Descriptions[DW_OP_minus] = Desc(Op::Dwarf2);
48 Descriptions[DW_OP_mod] = Desc(Op::Dwarf2);
49 Descriptions[DW_OP_mul] = Desc(Op::Dwarf2);
50 Descriptions[DW_OP_neg] = Desc(Op::Dwarf2);
51 Descriptions[DW_OP_not] = Desc(Op::Dwarf2);
52 Descriptions[DW_OP_or] = Desc(Op::Dwarf2);
53 Descriptions[DW_OP_plus] = Desc(Op::Dwarf2);
54 Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB);
55 Descriptions[DW_OP_shl] = Desc(Op::Dwarf2);
56 Descriptions[DW_OP_shr] = Desc(Op::Dwarf2);
57 Descriptions[DW_OP_shra] = Desc(Op::Dwarf2);
58 Descriptions[DW_OP_xor] = Desc(Op::Dwarf2);
59 Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2);
60 Descriptions[DW_OP_eq] = Desc(Op::Dwarf2);
61 Descriptions[DW_OP_ge] = Desc(Op::Dwarf2);
62 Descriptions[DW_OP_gt] = Desc(Op::Dwarf2);
63 Descriptions[DW_OP_le] = Desc(Op::Dwarf2);
64 Descriptions[DW_OP_lt] = Desc(Op::Dwarf2);
65 Descriptions[DW_OP_ne] = Desc(Op::Dwarf2);
66 Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2);
67 for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA)
68 Descriptions[LA] = Desc(Op::Dwarf2);
69 for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA)
70 Descriptions[LA] = Desc(Op::Dwarf2);
71 for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA)
72 Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
73 Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB);
74 Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
75 Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB);
76 Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB);
77 Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1);
78 Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1);
79 Descriptions[DW_OP_nop] = Desc(Op::Dwarf2);
80 Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3);
81 Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2);
82 Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4);
83 Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr);
84 Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3);
85 Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3);
86 Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB);
87 Descriptions[DW_OP_implicit_value] =
89 Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf4);
90 Descriptions[DW_OP_implicit_pointer] =
92 Descriptions[DW_OP_addrx] = Desc(Op::Dwarf5, Op::SizeLEB);
93 Descriptions[DW_OP_constx] = Desc(Op::Dwarf5, Op::SizeLEB);
94 Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB);
95 Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef);
96 Descriptions[DW_OP_regval_type] =
98 Descriptions[DW_OP_WASM_location] =
100 Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);
101 Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
102 Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB);
103 Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);
104 Descriptions[DW_OP_GNU_implicit_pointer] =
106 // This Description acts as a marker that getSubOpDesc must be called
107 // to fetch the final Description for the operation. Each such final
108 // Description must share the same first SizeSubOpLEB operand.
109 Descriptions[DW_OP_LLVM_user] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
110 return Descriptions;
111}
112
113static Desc getDescImpl(ArrayRef<Desc> Descriptions, unsigned Opcode) {
114 // Handle possible corrupted or unsupported operation.
115 if (Opcode >= Descriptions.size())
116 return {};
117 return Descriptions[Opcode];
118}
119
120static Desc getOpDesc(unsigned Opcode) {
121 static std::vector<Desc> Descriptions = getOpDescriptions();
122 return getDescImpl(Descriptions, Opcode);
123}
124
125static std::vector<Desc> getSubOpDescriptions() {
126 static constexpr unsigned LlvmUserDescriptionsSize = 1
127#define HANDLE_DW_OP_LLVM_USEROP(ID, NAME) +1
128#include "llvm/BinaryFormat/Dwarf.def"
129 ;
130 std::vector<Desc> Descriptions;
131 Descriptions.resize(LlvmUserDescriptionsSize);
132 Descriptions[DW_OP_LLVM_nop] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
133 Descriptions[DW_OP_LLVM_form_aspace_address] =
135 Descriptions[DW_OP_LLVM_push_lane] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
136 Descriptions[DW_OP_LLVM_offset] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
137 Descriptions[DW_OP_LLVM_offset_uconst] =
139 Descriptions[DW_OP_LLVM_bit_offset] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
140 Descriptions[DW_OP_LLVM_call_frame_entry_reg] =
142 Descriptions[DW_OP_LLVM_undefined] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
143 Descriptions[DW_OP_LLVM_aspace_bregx] =
145 Descriptions[DW_OP_LLVM_piece_end] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
146 Descriptions[DW_OP_LLVM_extend] =
148 Descriptions[DW_OP_LLVM_select_bit_piece] =
150 return Descriptions;
151}
152
153static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode) {
154 assert(Opcode == DW_OP_LLVM_user);
155 static std::vector<Desc> Descriptions = getSubOpDescriptions();
156 return getDescImpl(Descriptions, SubOpcode);
157}
158
159bool DWARFExpression::Operation::extract(DataExtractor Data,
160 uint8_t AddressSize, uint64_t Offset,
161 std::optional<DwarfFormat> Format) {
162 EndOffset = Offset;
163 Opcode = Data.getU8(&Offset);
164
165 Desc = getOpDesc(Opcode);
166 if (Desc.Version == Operation::DwarfNA)
167 return false;
168
169 Operands.resize(Desc.Op.size());
170 OperandEndOffsets.resize(Desc.Op.size());
171 for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) {
172 unsigned Size = Desc.Op[Operand];
173 unsigned Signed = Size & Operation::SignBit;
174
175 switch (Size & ~Operation::SignBit) {
177 assert(Operand == 0 && "SubOp operand must be the first operand");
178 Operands[Operand] = Data.getULEB128(&Offset);
179 Desc = getSubOpDesc(Opcode, Operands[Operand]);
180 if (Desc.Version == Operation::DwarfNA)
181 return false;
182 assert(Desc.Op[Operand] == Operation::SizeSubOpLEB &&
183 "SizeSubOpLEB Description must begin with SizeSubOpLEB operand");
184 Operands.resize(Desc.Op.size());
185 OperandEndOffsets.resize(Desc.Op.size());
186 break;
187 case Operation::Size1:
188 Operands[Operand] = Data.getU8(&Offset);
189 if (Signed)
190 Operands[Operand] = (int8_t)Operands[Operand];
191 break;
192 case Operation::Size2:
193 Operands[Operand] = Data.getU16(&Offset);
194 if (Signed)
195 Operands[Operand] = (int16_t)Operands[Operand];
196 break;
197 case Operation::Size4:
198 Operands[Operand] = Data.getU32(&Offset);
199 if (Signed)
200 Operands[Operand] = (int32_t)Operands[Operand];
201 break;
202 case Operation::Size8:
203 Operands[Operand] = Data.getU64(&Offset);
204 break;
206 Operands[Operand] = Data.getUnsigned(&Offset, AddressSize);
207 break;
209 if (!Format)
210 return false;
211 Operands[Operand] =
212 Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format));
213 break;
215 if (Signed)
216 Operands[Operand] = Data.getSLEB128(&Offset);
217 else
218 Operands[Operand] = Data.getULEB128(&Offset);
219 break;
221 Operands[Operand] = Data.getULEB128(&Offset);
222 break;
224 assert(Operand == 1);
225 switch (Operands[0]) {
226 case 0:
227 case 1:
228 case 2:
229 case 4:
230 Operands[Operand] = Data.getULEB128(&Offset);
231 break;
232 case 3: // global as uint32
233 Operands[Operand] = Data.getU32(&Offset);
234 break;
235 default:
236 return false; // Unknown Wasm location
237 }
238 break;
240 // We need a size, so this cannot be the first operand
241 if (Operand == 0)
242 return false;
243 // Store the offset of the block as the value.
244 Operands[Operand] = Offset;
245 Offset += Operands[Operand - 1];
246 break;
247 default:
248 llvm_unreachable("Unknown DWARFExpression Op size");
249 }
250
251 OperandEndOffsets[Operand] = Offset;
252 }
253
254 EndOffset = Offset;
255 return true;
256}
257
258std::optional<unsigned> DWARFExpression::Operation::getSubCode() const {
259 if (!Desc.Op.size() || Desc.Op[0] != Operation::SizeSubOpLEB)
260 return std::nullopt;
261 return Operands[0];
262}
263
265 if (AddressSize != RHS.AddressSize || Format != RHS.Format)
266 return false;
267 return Data.getData() == RHS.Data.getData();
268}
269
270} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
mir Rename Register Operands
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition ArrayRef.h:147
This class represents an Operation in the Expression.
LLVM_ABI std::optional< unsigned > getSubCode() const
@ DwarfNA
Serves as a marker for unused entries.
@ SizeSubOpLEB
The operand is a ULEB128 encoded SubOpcode.
@ SizeBlock
Preceding operand contains block size.
DWARFExpression(DataExtractor Data, uint8_t AddressSize, std::optional< dwarf::DwarfFormat > Format=std::nullopt)
LLVM_ABI bool operator==(const DWARFExpression &RHS) const
void resize(size_type N)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Calculates the starting offsets for various sections within the .debug_names section.
Definition Dwarf.h:35
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition Dwarf.h:1088
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode)
static std::vector< Desc > getOpDescriptions()
Op::Description Desc
static Desc getDescImpl(ArrayRef< Desc > Descriptions, unsigned Opcode)
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
DWARFExpression::Operation Op
static Desc getOpDesc(unsigned Opcode)
static std::vector< Desc > getSubOpDescriptions()
Description of the encoding of one expression Op.