1a058736cSReid Kleckner //===-- DWARFExpression.cpp -----------------------------------------------===//
2a058736cSReid Kleckner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a058736cSReid Kleckner //
7a058736cSReid Kleckner //===----------------------------------------------------------------------===//
8a058736cSReid Kleckner 
9a058736cSReid Kleckner #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
1076dda218SMarkus Lavin #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
11a058736cSReid Kleckner #include "llvm/MC/MCRegisterInfo.h"
12a058736cSReid Kleckner #include "llvm/Support/Format.h"
13a058736cSReid Kleckner #include <cassert>
14a058736cSReid Kleckner #include <cstdint>
15a058736cSReid Kleckner #include <vector>
16a058736cSReid Kleckner 
17a058736cSReid Kleckner using namespace llvm;
18a058736cSReid Kleckner using namespace dwarf;
19a058736cSReid Kleckner 
20a058736cSReid Kleckner namespace llvm {
21a058736cSReid Kleckner 
22a058736cSReid Kleckner typedef std::vector<DWARFExpression::Operation::Description> DescVector;
23a058736cSReid Kleckner 
getDescriptions()24a058736cSReid Kleckner static DescVector getDescriptions() {
25a058736cSReid Kleckner   DescVector Descriptions;
26a058736cSReid Kleckner   typedef DWARFExpression::Operation Op;
27a058736cSReid Kleckner   typedef Op::Description Desc;
28a058736cSReid Kleckner 
29a058736cSReid Kleckner   Descriptions.resize(0xff);
30a058736cSReid Kleckner   Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr);
31a058736cSReid Kleckner   Descriptions[DW_OP_deref] = Desc(Op::Dwarf2);
32a058736cSReid Kleckner   Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1);
33a058736cSReid Kleckner   Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1);
34a058736cSReid Kleckner   Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2);
35a058736cSReid Kleckner   Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2);
36a058736cSReid Kleckner   Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4);
37a058736cSReid Kleckner   Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4);
38a058736cSReid Kleckner   Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8);
39a058736cSReid Kleckner   Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8);
40a058736cSReid Kleckner   Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB);
41a058736cSReid Kleckner   Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
42a058736cSReid Kleckner   Descriptions[DW_OP_dup] = Desc(Op::Dwarf2);
43a058736cSReid Kleckner   Descriptions[DW_OP_drop] = Desc(Op::Dwarf2);
44a058736cSReid Kleckner   Descriptions[DW_OP_over] = Desc(Op::Dwarf2);
45a058736cSReid Kleckner   Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1);
46a058736cSReid Kleckner   Descriptions[DW_OP_swap] = Desc(Op::Dwarf2);
47a058736cSReid Kleckner   Descriptions[DW_OP_rot] = Desc(Op::Dwarf2);
48a058736cSReid Kleckner   Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2);
49a058736cSReid Kleckner   Descriptions[DW_OP_abs] = Desc(Op::Dwarf2);
50a058736cSReid Kleckner   Descriptions[DW_OP_and] = Desc(Op::Dwarf2);
51a058736cSReid Kleckner   Descriptions[DW_OP_div] = Desc(Op::Dwarf2);
52a058736cSReid Kleckner   Descriptions[DW_OP_minus] = Desc(Op::Dwarf2);
53a058736cSReid Kleckner   Descriptions[DW_OP_mod] = Desc(Op::Dwarf2);
54a058736cSReid Kleckner   Descriptions[DW_OP_mul] = Desc(Op::Dwarf2);
55a058736cSReid Kleckner   Descriptions[DW_OP_neg] = Desc(Op::Dwarf2);
56a058736cSReid Kleckner   Descriptions[DW_OP_not] = Desc(Op::Dwarf2);
57a058736cSReid Kleckner   Descriptions[DW_OP_or] = Desc(Op::Dwarf2);
58a058736cSReid Kleckner   Descriptions[DW_OP_plus] = Desc(Op::Dwarf2);
59a058736cSReid Kleckner   Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB);
60a058736cSReid Kleckner   Descriptions[DW_OP_shl] = Desc(Op::Dwarf2);
61a058736cSReid Kleckner   Descriptions[DW_OP_shr] = Desc(Op::Dwarf2);
62a058736cSReid Kleckner   Descriptions[DW_OP_shra] = Desc(Op::Dwarf2);
63a058736cSReid Kleckner   Descriptions[DW_OP_xor] = Desc(Op::Dwarf2);
64a058736cSReid Kleckner   Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2);
65a058736cSReid Kleckner   Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2);
66a058736cSReid Kleckner   Descriptions[DW_OP_eq] = Desc(Op::Dwarf2);
67a058736cSReid Kleckner   Descriptions[DW_OP_ge] = Desc(Op::Dwarf2);
68a058736cSReid Kleckner   Descriptions[DW_OP_gt] = Desc(Op::Dwarf2);
69a058736cSReid Kleckner   Descriptions[DW_OP_le] = Desc(Op::Dwarf2);
70a058736cSReid Kleckner   Descriptions[DW_OP_lt] = Desc(Op::Dwarf2);
71a058736cSReid Kleckner   Descriptions[DW_OP_ne] = Desc(Op::Dwarf2);
72a058736cSReid Kleckner   for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA)
73a058736cSReid Kleckner     Descriptions[LA] = Desc(Op::Dwarf2);
74a058736cSReid Kleckner   for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA)
75a058736cSReid Kleckner     Descriptions[LA] = Desc(Op::Dwarf2);
76a058736cSReid Kleckner   for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA)
77a058736cSReid Kleckner     Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
78a058736cSReid Kleckner   Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB);
79a058736cSReid Kleckner   Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
80a058736cSReid Kleckner   Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB);
81a058736cSReid Kleckner   Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB);
82a058736cSReid Kleckner   Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1);
83a058736cSReid Kleckner   Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1);
84a058736cSReid Kleckner   Descriptions[DW_OP_nop] = Desc(Op::Dwarf2);
85a058736cSReid Kleckner   Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3);
86a058736cSReid Kleckner   Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2);
87a058736cSReid Kleckner   Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4);
88a058736cSReid Kleckner   Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr);
89a058736cSReid Kleckner   Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3);
90a058736cSReid Kleckner   Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3);
91a058736cSReid Kleckner   Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB);
92a058736cSReid Kleckner   Descriptions[DW_OP_implicit_value] =
93a058736cSReid Kleckner       Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeBlock);
94a058736cSReid Kleckner   Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf3);
95adf7a0a5SYury Delendik   Descriptions[DW_OP_WASM_location] =
9648139ebcSWouter van Oortmerssen       Desc(Op::Dwarf4, Op::SizeLEB, Op::WasmLocationArg);
97a058736cSReid Kleckner   Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);
982df23a4eSDavid Blaikie   Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB);
99a058736cSReid Kleckner   Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
100a058736cSReid Kleckner   Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB);
101a0d45058SDjordje Todorovic   Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);
10276dda218SMarkus Lavin 
10376dda218SMarkus Lavin   Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef);
104a0d45058SDjordje Todorovic   Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB);
105aa6ec19cSAdrian Prantl   Descriptions[DW_OP_regval_type] =
106aa6ec19cSAdrian Prantl       Desc(Op::Dwarf5, Op::SizeLEB, Op::BaseTypeRef);
10776dda218SMarkus Lavin 
108a058736cSReid Kleckner   return Descriptions;
109a058736cSReid Kleckner }
110a058736cSReid Kleckner 
getOpDesc(unsigned OpCode)111a058736cSReid Kleckner static DWARFExpression::Operation::Description getOpDesc(unsigned OpCode) {
112a058736cSReid Kleckner   // FIXME: Make this constexpr once all compilers are smart enough to do it.
113a058736cSReid Kleckner   static DescVector Descriptions = getDescriptions();
114144e4c5aSGeorge Rimar   // Handle possible corrupted or unsupported operation.
115144e4c5aSGeorge Rimar   if (OpCode >= Descriptions.size())
116144e4c5aSGeorge Rimar     return {};
117a058736cSReid Kleckner   return Descriptions[OpCode];
118a058736cSReid Kleckner }
119a058736cSReid Kleckner 
extract(DataExtractor Data,uint8_t AddressSize,uint64_t Offset,Optional<DwarfFormat> Format)1208f3d47c5SIgor Kudrin bool DWARFExpression::Operation::extract(DataExtractor Data,
121befbc99aSFangrui Song                                          uint8_t AddressSize, uint64_t Offset,
122befbc99aSFangrui Song                                          Optional<DwarfFormat> Format) {
123c6ed1fcfSIgor Kudrin   EndOffset = Offset;
124a058736cSReid Kleckner   Opcode = Data.getU8(&Offset);
125a058736cSReid Kleckner 
126a058736cSReid Kleckner   Desc = getOpDesc(Opcode);
127c6ed1fcfSIgor Kudrin   if (Desc.Version == Operation::DwarfNA)
128a058736cSReid Kleckner     return false;
129a058736cSReid Kleckner 
130a058736cSReid Kleckner   for (unsigned Operand = 0; Operand < 2; ++Operand) {
131a058736cSReid Kleckner     unsigned Size = Desc.Op[Operand];
132a058736cSReid Kleckner     unsigned Signed = Size & Operation::SignBit;
133a058736cSReid Kleckner 
134a058736cSReid Kleckner     if (Size == Operation::SizeNA)
135a058736cSReid Kleckner       break;
136a058736cSReid Kleckner 
137a058736cSReid Kleckner     switch (Size & ~Operation::SignBit) {
138a058736cSReid Kleckner     case Operation::Size1:
139a058736cSReid Kleckner       Operands[Operand] = Data.getU8(&Offset);
140a058736cSReid Kleckner       if (Signed)
141a058736cSReid Kleckner         Operands[Operand] = (int8_t)Operands[Operand];
142a058736cSReid Kleckner       break;
143a058736cSReid Kleckner     case Operation::Size2:
144a058736cSReid Kleckner       Operands[Operand] = Data.getU16(&Offset);
145a058736cSReid Kleckner       if (Signed)
146a058736cSReid Kleckner         Operands[Operand] = (int16_t)Operands[Operand];
147a058736cSReid Kleckner       break;
148a058736cSReid Kleckner     case Operation::Size4:
149a058736cSReid Kleckner       Operands[Operand] = Data.getU32(&Offset);
150a058736cSReid Kleckner       if (Signed)
151a058736cSReid Kleckner         Operands[Operand] = (int32_t)Operands[Operand];
152a058736cSReid Kleckner       break;
153a058736cSReid Kleckner     case Operation::Size8:
154a058736cSReid Kleckner       Operands[Operand] = Data.getU64(&Offset);
155a058736cSReid Kleckner       break;
156a058736cSReid Kleckner     case Operation::SizeAddr:
157548553eaSIgor Kudrin       Operands[Operand] = Data.getUnsigned(&Offset, AddressSize);
158a058736cSReid Kleckner       break;
159a058736cSReid Kleckner     case Operation::SizeRefAddr:
160befbc99aSFangrui Song       if (!Format)
161befbc99aSFangrui Song         return false;
162befbc99aSFangrui Song       Operands[Operand] =
163befbc99aSFangrui Song           Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format));
164a058736cSReid Kleckner       break;
165a058736cSReid Kleckner     case Operation::SizeLEB:
166a058736cSReid Kleckner       if (Signed)
167a058736cSReid Kleckner         Operands[Operand] = Data.getSLEB128(&Offset);
168a058736cSReid Kleckner       else
169a058736cSReid Kleckner         Operands[Operand] = Data.getULEB128(&Offset);
170a058736cSReid Kleckner       break;
17176dda218SMarkus Lavin     case Operation::BaseTypeRef:
17276dda218SMarkus Lavin       Operands[Operand] = Data.getULEB128(&Offset);
17376dda218SMarkus Lavin       break;
17448139ebcSWouter van Oortmerssen     case Operation::WasmLocationArg:
17548139ebcSWouter van Oortmerssen       assert(Operand == 1);
17648139ebcSWouter van Oortmerssen       switch (Operands[0]) {
177e3c0b0feSWouter van Oortmerssen       case 0:
178e3c0b0feSWouter van Oortmerssen       case 1:
179e3c0b0feSWouter van Oortmerssen       case 2:
180e3c0b0feSWouter van Oortmerssen       case 4:
18148139ebcSWouter van Oortmerssen         Operands[Operand] = Data.getULEB128(&Offset);
18248139ebcSWouter van Oortmerssen         break;
18348139ebcSWouter van Oortmerssen       case 3: // global as uint32
18448139ebcSWouter van Oortmerssen          Operands[Operand] = Data.getU32(&Offset);
18548139ebcSWouter van Oortmerssen          break;
18648139ebcSWouter van Oortmerssen       default:
18748139ebcSWouter van Oortmerssen         return false; // Unknown Wasm location
18848139ebcSWouter van Oortmerssen       }
18948139ebcSWouter van Oortmerssen       break;
190a058736cSReid Kleckner     case Operation::SizeBlock:
191a058736cSReid Kleckner       // We need a size, so this cannot be the first operand
192a058736cSReid Kleckner       if (Operand == 0)
193a058736cSReid Kleckner         return false;
194a058736cSReid Kleckner       // Store the offset of the block as the value.
195a058736cSReid Kleckner       Operands[Operand] = Offset;
196a058736cSReid Kleckner       Offset += Operands[Operand - 1];
197a058736cSReid Kleckner       break;
198a058736cSReid Kleckner     default:
199a058736cSReid Kleckner       llvm_unreachable("Unknown DWARFExpression Op size");
200a058736cSReid Kleckner     }
201b86ce219SMarkus Lavin 
202b86ce219SMarkus Lavin     OperandEndOffsets[Operand] = Offset;
203a058736cSReid Kleckner   }
204a058736cSReid Kleckner 
205a058736cSReid Kleckner   EndOffset = Offset;
206a058736cSReid Kleckner   return true;
207a058736cSReid Kleckner }
208a058736cSReid Kleckner 
prettyPrintBaseTypeRef(DWARFUnit * U,raw_ostream & OS,DIDumpOptions DumpOpts,const uint64_t Operands[2],unsigned Operand)209aa6ec19cSAdrian Prantl static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS,
21079df4101SDuncan P. N. Exon Smith                                    DIDumpOptions DumpOpts,
21179df4101SDuncan P. N. Exon Smith                                    const uint64_t Operands[2],
2120ec5baa1SDavid Blaikie                                    unsigned Operand) {
213aa6ec19cSAdrian Prantl   assert(Operand < 2 && "operand out of bounds");
214aa6ec19cSAdrian Prantl   auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]);
215aa6ec19cSAdrian Prantl   if (Die && Die.getTag() == dwarf::DW_TAG_base_type) {
2160ec5baa1SDavid Blaikie     OS << " (";
2170ec5baa1SDavid Blaikie     if (DumpOpts.Verbose)
2180ec5baa1SDavid Blaikie       OS << format("0x%08" PRIx64 " -> ", Operands[Operand]);
2190ec5baa1SDavid Blaikie     OS << format("0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]);
220*71e5488aSDavid Blaikie     if (auto Name = dwarf::toString(Die.find(dwarf::DW_AT_name)))
221*71e5488aSDavid Blaikie       OS << " \"" << *Name << "\"";
222aa6ec19cSAdrian Prantl   } else {
223aa6ec19cSAdrian Prantl     OS << format(" <invalid base_type ref: 0x%" PRIx64 ">",
224aa6ec19cSAdrian Prantl                  Operands[Operand]);
225aa6ec19cSAdrian Prantl   }
226aa6ec19cSAdrian Prantl }
227aa6ec19cSAdrian Prantl 
prettyPrintRegisterOp(DWARFUnit * U,raw_ostream & OS,DIDumpOptions DumpOpts,uint8_t Opcode,const uint64_t Operands[2],const MCRegisterInfo * MRI,bool isEH)2280ec5baa1SDavid Blaikie static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
2290ec5baa1SDavid Blaikie                                   DIDumpOptions DumpOpts, uint8_t Opcode,
23079df4101SDuncan P. N. Exon Smith                                   const uint64_t Operands[2],
231a058736cSReid Kleckner                                   const MCRegisterInfo *MRI, bool isEH) {
232a058736cSReid Kleckner   if (!MRI)
233a058736cSReid Kleckner     return false;
234a058736cSReid Kleckner 
235a058736cSReid Kleckner   uint64_t DwarfRegNum;
236a058736cSReid Kleckner   unsigned OpNum = 0;
237a058736cSReid Kleckner 
238aa6ec19cSAdrian Prantl   if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx ||
239aa6ec19cSAdrian Prantl       Opcode == DW_OP_regval_type)
240a058736cSReid Kleckner     DwarfRegNum = Operands[OpNum++];
241a058736cSReid Kleckner   else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx)
242a058736cSReid Kleckner     DwarfRegNum = Opcode - DW_OP_breg0;
243a058736cSReid Kleckner   else
244a058736cSReid Kleckner     DwarfRegNum = Opcode - DW_OP_reg0;
245a058736cSReid Kleckner 
246aaff1a63SPavel Labath   if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(DwarfRegNum, isEH)) {
247aaff1a63SPavel Labath     if (const char *RegName = MRI->getName(*LLVMRegNum)) {
248a058736cSReid Kleckner       if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
249a058736cSReid Kleckner           Opcode == DW_OP_bregx)
250a058736cSReid Kleckner         OS << format(" %s%+" PRId64, RegName, Operands[OpNum]);
251a058736cSReid Kleckner       else
252a058736cSReid Kleckner         OS << ' ' << RegName;
253aa6ec19cSAdrian Prantl 
254aa6ec19cSAdrian Prantl       if (Opcode == DW_OP_regval_type)
2550ec5baa1SDavid Blaikie         prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1);
256a058736cSReid Kleckner       return true;
257a058736cSReid Kleckner     }
258a058736cSReid Kleckner   }
259a058736cSReid Kleckner 
260a058736cSReid Kleckner   return false;
261a058736cSReid Kleckner }
262a058736cSReid Kleckner 
print(raw_ostream & OS,DIDumpOptions DumpOpts,const DWARFExpression * Expr,const MCRegisterInfo * RegInfo,DWARFUnit * U,bool isEH) const2630ec5baa1SDavid Blaikie bool DWARFExpression::Operation::print(raw_ostream &OS, DIDumpOptions DumpOpts,
264a058736cSReid Kleckner                                        const DWARFExpression *Expr,
265a058736cSReid Kleckner                                        const MCRegisterInfo *RegInfo,
26679df4101SDuncan P. N. Exon Smith                                        DWARFUnit *U, bool isEH) const {
267a058736cSReid Kleckner   if (Error) {
268144e4c5aSGeorge Rimar     OS << "<decoding error>";
269a058736cSReid Kleckner     return false;
270a058736cSReid Kleckner   }
271a058736cSReid Kleckner 
272a058736cSReid Kleckner   StringRef Name = OperationEncodingString(Opcode);
273a058736cSReid Kleckner   assert(!Name.empty() && "DW_OP has no name!");
274a058736cSReid Kleckner   OS << Name;
275a058736cSReid Kleckner 
276a058736cSReid Kleckner   if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
277a058736cSReid Kleckner       (Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) ||
278aa6ec19cSAdrian Prantl       Opcode == DW_OP_bregx || Opcode == DW_OP_regx ||
279aa6ec19cSAdrian Prantl       Opcode == DW_OP_regval_type)
2800ec5baa1SDavid Blaikie     if (prettyPrintRegisterOp(U, OS, DumpOpts, Opcode, Operands, RegInfo, isEH))
281a058736cSReid Kleckner       return true;
282a058736cSReid Kleckner 
283a058736cSReid Kleckner   for (unsigned Operand = 0; Operand < 2; ++Operand) {
284a058736cSReid Kleckner     unsigned Size = Desc.Op[Operand];
285a058736cSReid Kleckner     unsigned Signed = Size & Operation::SignBit;
286a058736cSReid Kleckner 
287a058736cSReid Kleckner     if (Size == Operation::SizeNA)
288a058736cSReid Kleckner       break;
289a058736cSReid Kleckner 
29076dda218SMarkus Lavin     if (Size == Operation::BaseTypeRef && U) {
291c9365251SDavid Stenberg       // For DW_OP_convert the operand may be 0 to indicate that conversion to
292c9365251SDavid Stenberg       // the generic type should be done. The same holds for DW_OP_reinterpret,
293c9365251SDavid Stenberg       // which is currently not supported.
294c9365251SDavid Stenberg       if (Opcode == DW_OP_convert && Operands[Operand] == 0)
295c9365251SDavid Stenberg         OS << " 0x0";
296c9365251SDavid Stenberg       else
2970ec5baa1SDavid Blaikie         prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, Operand);
29848139ebcSWouter van Oortmerssen     } else if (Size == Operation::WasmLocationArg) {
29948139ebcSWouter van Oortmerssen       assert(Operand == 1);
30048139ebcSWouter van Oortmerssen       switch (Operands[0]) {
301e3c0b0feSWouter van Oortmerssen       case 0:
302e3c0b0feSWouter van Oortmerssen       case 1:
303e3c0b0feSWouter van Oortmerssen       case 2:
30448139ebcSWouter van Oortmerssen       case 3: // global as uint32
305e3c0b0feSWouter van Oortmerssen       case 4:
30648139ebcSWouter van Oortmerssen         OS << format(" 0x%" PRIx64, Operands[Operand]);
30748139ebcSWouter van Oortmerssen         break;
30848139ebcSWouter van Oortmerssen       default: assert(false);
30948139ebcSWouter van Oortmerssen       }
31076dda218SMarkus Lavin     } else if (Size == Operation::SizeBlock) {
311f26a70a5SIgor Kudrin       uint64_t Offset = Operands[Operand];
312a058736cSReid Kleckner       for (unsigned i = 0; i < Operands[Operand - 1]; ++i)
313a058736cSReid Kleckner         OS << format(" 0x%02x", Expr->Data.getU8(&Offset));
314a058736cSReid Kleckner     } else {
315a058736cSReid Kleckner       if (Signed)
316a058736cSReid Kleckner         OS << format(" %+" PRId64, (int64_t)Operands[Operand]);
317a0d45058SDjordje Todorovic       else if (Opcode != DW_OP_entry_value &&
318a0d45058SDjordje Todorovic                Opcode != DW_OP_GNU_entry_value)
319a058736cSReid Kleckner         OS << format(" 0x%" PRIx64, Operands[Operand]);
320a058736cSReid Kleckner     }
321a058736cSReid Kleckner   }
322a058736cSReid Kleckner   return true;
323a058736cSReid Kleckner }
324a058736cSReid Kleckner 
print(raw_ostream & OS,DIDumpOptions DumpOpts,const MCRegisterInfo * RegInfo,DWARFUnit * U,bool IsEH) const3250ec5baa1SDavid Blaikie void DWARFExpression::print(raw_ostream &OS, DIDumpOptions DumpOpts,
3260ec5baa1SDavid Blaikie                             const MCRegisterInfo *RegInfo, DWARFUnit *U,
3270ec5baa1SDavid Blaikie                             bool IsEH) const {
328a0d45058SDjordje Todorovic   uint32_t EntryValExprSize = 0;
32997dbab87SAdrian Prantl   uint64_t EntryValStartOffset = 0;
33051d969dcSSoham Dixit   if (Data.getData().empty())
33151d969dcSSoham Dixit     OS << "<empty>";
33251d969dcSSoham Dixit 
333a058736cSReid Kleckner   for (auto &Op : *this) {
3340ec5baa1SDavid Blaikie     if (!Op.print(OS, DumpOpts, this, RegInfo, U, IsEH)) {
335f26a70a5SIgor Kudrin       uint64_t FailOffset = Op.getEndOffset();
336a058736cSReid Kleckner       while (FailOffset < Data.getData().size())
337a058736cSReid Kleckner         OS << format(" %02x", Data.getU8(&FailOffset));
338a058736cSReid Kleckner       return;
339a058736cSReid Kleckner     }
340a0d45058SDjordje Todorovic 
341a0d45058SDjordje Todorovic     if (Op.getCode() == DW_OP_entry_value ||
342a0d45058SDjordje Todorovic         Op.getCode() == DW_OP_GNU_entry_value) {
343a0d45058SDjordje Todorovic       OS << "(";
344a0d45058SDjordje Todorovic       EntryValExprSize = Op.getRawOperand(0);
34597dbab87SAdrian Prantl       EntryValStartOffset = Op.getEndOffset();
346a0d45058SDjordje Todorovic       continue;
347a0d45058SDjordje Todorovic     }
348a0d45058SDjordje Todorovic 
349a0d45058SDjordje Todorovic     if (EntryValExprSize) {
35097dbab87SAdrian Prantl       EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset;
351a0d45058SDjordje Todorovic       if (EntryValExprSize == 0)
352a0d45058SDjordje Todorovic         OS << ")";
353a0d45058SDjordje Todorovic     }
354a0d45058SDjordje Todorovic 
355a058736cSReid Kleckner     if (Op.getEndOffset() < Data.getData().size())
356a058736cSReid Kleckner       OS << ", ";
357a058736cSReid Kleckner   }
358a058736cSReid Kleckner }
359a058736cSReid Kleckner 
verify(const Operation & Op,DWARFUnit * U)360a0f1f171SDuncan P. N. Exon Smith bool DWARFExpression::Operation::verify(const Operation &Op, DWARFUnit *U) {
36176dda218SMarkus Lavin   for (unsigned Operand = 0; Operand < 2; ++Operand) {
362a0f1f171SDuncan P. N. Exon Smith     unsigned Size = Op.Desc.Op[Operand];
36376dda218SMarkus Lavin 
36476dda218SMarkus Lavin     if (Size == Operation::SizeNA)
36576dda218SMarkus Lavin       break;
36676dda218SMarkus Lavin 
36776dda218SMarkus Lavin     if (Size == Operation::BaseTypeRef) {
368c9365251SDavid Stenberg       // For DW_OP_convert the operand may be 0 to indicate that conversion to
369c9365251SDavid Stenberg       // the generic type should be done, so don't look up a base type in that
370c9365251SDavid Stenberg       // case. The same holds for DW_OP_reinterpret, which is currently not
371c9365251SDavid Stenberg       // supported.
372a0f1f171SDuncan P. N. Exon Smith       if (Op.Opcode == DW_OP_convert && Op.Operands[Operand] == 0)
373c9365251SDavid Stenberg         continue;
374a0f1f171SDuncan P. N. Exon Smith       auto Die = U->getDIEForOffset(U->getOffset() + Op.Operands[Operand]);
375a0f1f171SDuncan P. N. Exon Smith       if (!Die || Die.getTag() != dwarf::DW_TAG_base_type)
37676dda218SMarkus Lavin         return false;
37776dda218SMarkus Lavin     }
37876dda218SMarkus Lavin   }
37976dda218SMarkus Lavin 
38076dda218SMarkus Lavin   return true;
38176dda218SMarkus Lavin }
38276dda218SMarkus Lavin 
verify(DWARFUnit * U)38376dda218SMarkus Lavin bool DWARFExpression::verify(DWARFUnit *U) {
38476dda218SMarkus Lavin   for (auto &Op : *this)
385a0f1f171SDuncan P. N. Exon Smith     if (!Operation::verify(Op, U))
38676dda218SMarkus Lavin       return false;
38776dda218SMarkus Lavin 
38876dda218SMarkus Lavin   return true;
38976dda218SMarkus Lavin }
39076dda218SMarkus Lavin 
391dc4a6f5dSOliver Stannard /// A user-facing string representation of a DWARF expression. This might be an
392dc4a6f5dSOliver Stannard /// Address expression, in which case it will be implicitly dereferenced, or a
393dc4a6f5dSOliver Stannard /// Value expression.
394dc4a6f5dSOliver Stannard struct PrintedExpr {
395dc4a6f5dSOliver Stannard   enum ExprKind {
396dc4a6f5dSOliver Stannard     Address,
397dc4a6f5dSOliver Stannard     Value,
398dc4a6f5dSOliver Stannard   };
399dc4a6f5dSOliver Stannard   ExprKind Kind;
400dc4a6f5dSOliver Stannard   SmallString<16> String;
401dc4a6f5dSOliver Stannard 
PrintedExprllvm::PrintedExpr402dc4a6f5dSOliver Stannard   PrintedExpr(ExprKind K = Address) : Kind(K) {}
403dc4a6f5dSOliver Stannard };
404dc4a6f5dSOliver Stannard 
printCompactDWARFExpr(raw_ostream & OS,DWARFExpression::iterator I,const DWARFExpression::iterator E,const MCRegisterInfo & MRI)405dc4a6f5dSOliver Stannard static bool printCompactDWARFExpr(raw_ostream &OS, DWARFExpression::iterator I,
406dc4a6f5dSOliver Stannard                                   const DWARFExpression::iterator E,
407dc4a6f5dSOliver Stannard                                   const MCRegisterInfo &MRI) {
408dc4a6f5dSOliver Stannard   SmallVector<PrintedExpr, 4> Stack;
409dc4a6f5dSOliver Stannard 
410dc4a6f5dSOliver Stannard   while (I != E) {
411fd601807SDuncan P. N. Exon Smith     const DWARFExpression::Operation &Op = *I;
412dc4a6f5dSOliver Stannard     uint8_t Opcode = Op.getCode();
413dc4a6f5dSOliver Stannard     switch (Opcode) {
414dc4a6f5dSOliver Stannard     case dwarf::DW_OP_regx: {
415dc4a6f5dSOliver Stannard       // DW_OP_regx: A register, with the register num given as an operand.
416dc4a6f5dSOliver Stannard       // Printed as the plain register name.
417dc4a6f5dSOliver Stannard       uint64_t DwarfRegNum = Op.getRawOperand(0);
418dc4a6f5dSOliver Stannard       Optional<unsigned> LLVMRegNum = MRI.getLLVMRegNum(DwarfRegNum, false);
419dc4a6f5dSOliver Stannard       if (!LLVMRegNum) {
420dc4a6f5dSOliver Stannard         OS << "<unknown register " << DwarfRegNum << ">";
421dc4a6f5dSOliver Stannard         return false;
422dc4a6f5dSOliver Stannard       }
423dc4a6f5dSOliver Stannard       raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String);
424dc4a6f5dSOliver Stannard       S << MRI.getName(*LLVMRegNum);
425dc4a6f5dSOliver Stannard       break;
426dc4a6f5dSOliver Stannard     }
4271d7311e0SOliver Stannard     case dwarf::DW_OP_bregx: {
4281d7311e0SOliver Stannard       int DwarfRegNum = Op.getRawOperand(0);
4291d7311e0SOliver Stannard       int64_t Offset = Op.getRawOperand(1);
4301d7311e0SOliver Stannard       Optional<unsigned> LLVMRegNum = MRI.getLLVMRegNum(DwarfRegNum, false);
4311d7311e0SOliver Stannard       if (!LLVMRegNum) {
4321d7311e0SOliver Stannard         OS << "<unknown register " << DwarfRegNum << ">";
4331d7311e0SOliver Stannard         return false;
4341d7311e0SOliver Stannard       }
4351d7311e0SOliver Stannard       raw_svector_ostream S(Stack.emplace_back().String);
4361d7311e0SOliver Stannard       S << MRI.getName(*LLVMRegNum);
4371d7311e0SOliver Stannard       if (Offset)
4381d7311e0SOliver Stannard         S << format("%+" PRId64, Offset);
4391d7311e0SOliver Stannard       break;
4401d7311e0SOliver Stannard     }
44157909b0aSOliver Stannard     case dwarf::DW_OP_entry_value:
44257909b0aSOliver Stannard     case dwarf::DW_OP_GNU_entry_value: {
44357909b0aSOliver Stannard       // DW_OP_entry_value contains a sub-expression which must be rendered
44457909b0aSOliver Stannard       // separately.
44557909b0aSOliver Stannard       uint64_t SubExprLength = Op.getRawOperand(0);
44657909b0aSOliver Stannard       DWARFExpression::iterator SubExprEnd = I.skipBytes(SubExprLength);
44757909b0aSOliver Stannard       ++I;
44857909b0aSOliver Stannard       raw_svector_ostream S(Stack.emplace_back().String);
44957909b0aSOliver Stannard       S << "entry(";
45057909b0aSOliver Stannard       printCompactDWARFExpr(S, I, SubExprEnd, MRI);
45157909b0aSOliver Stannard       S << ")";
45257909b0aSOliver Stannard       I = SubExprEnd;
45357909b0aSOliver Stannard       continue;
45457909b0aSOliver Stannard     }
45557909b0aSOliver Stannard     case dwarf::DW_OP_stack_value: {
45657909b0aSOliver Stannard       // The top stack entry should be treated as the actual value of tne
45757909b0aSOliver Stannard       // variable, rather than the address of the variable in memory.
45857909b0aSOliver Stannard       assert(!Stack.empty());
45957909b0aSOliver Stannard       Stack.back().Kind = PrintedExpr::Value;
46057909b0aSOliver Stannard       break;
46157909b0aSOliver Stannard     }
462dc4a6f5dSOliver Stannard     default:
463dc4a6f5dSOliver Stannard       if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) {
464dc4a6f5dSOliver Stannard         // DW_OP_reg<N>: A register, with the register num implied by the
465dc4a6f5dSOliver Stannard         // opcode. Printed as the plain register name.
466dc4a6f5dSOliver Stannard         uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0;
467dc4a6f5dSOliver Stannard         Optional<unsigned> LLVMRegNum = MRI.getLLVMRegNum(DwarfRegNum, false);
468dc4a6f5dSOliver Stannard         if (!LLVMRegNum) {
469dc4a6f5dSOliver Stannard           OS << "<unknown register " << DwarfRegNum << ">";
470dc4a6f5dSOliver Stannard           return false;
471dc4a6f5dSOliver Stannard         }
472dc4a6f5dSOliver Stannard         raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String);
473dc4a6f5dSOliver Stannard         S << MRI.getName(*LLVMRegNum);
4741d7311e0SOliver Stannard       } else if (Opcode >= dwarf::DW_OP_breg0 &&
4751d7311e0SOliver Stannard                  Opcode <= dwarf::DW_OP_breg31) {
4761d7311e0SOliver Stannard         int DwarfRegNum = Opcode - dwarf::DW_OP_breg0;
4771d7311e0SOliver Stannard         int64_t Offset = Op.getRawOperand(0);
4781d7311e0SOliver Stannard         Optional<unsigned> LLVMRegNum = MRI.getLLVMRegNum(DwarfRegNum, false);
4791d7311e0SOliver Stannard         if (!LLVMRegNum) {
4801d7311e0SOliver Stannard           OS << "<unknown register " << DwarfRegNum << ">";
4811d7311e0SOliver Stannard           return false;
4821d7311e0SOliver Stannard         }
4831d7311e0SOliver Stannard         raw_svector_ostream S(Stack.emplace_back().String);
4841d7311e0SOliver Stannard         S << MRI.getName(*LLVMRegNum);
4851d7311e0SOliver Stannard         if (Offset)
4861d7311e0SOliver Stannard           S << format("%+" PRId64, Offset);
487dc4a6f5dSOliver Stannard       } else {
488dc4a6f5dSOliver Stannard         // If we hit an unknown operand, we don't know its effect on the stack,
489dc4a6f5dSOliver Stannard         // so bail out on the whole expression.
490dc4a6f5dSOliver Stannard         OS << "<unknown op " << dwarf::OperationEncodingString(Opcode) << " ("
491dc4a6f5dSOliver Stannard            << (int)Opcode << ")>";
492dc4a6f5dSOliver Stannard         return false;
493dc4a6f5dSOliver Stannard       }
494dc4a6f5dSOliver Stannard       break;
495dc4a6f5dSOliver Stannard     }
496dc4a6f5dSOliver Stannard     ++I;
497dc4a6f5dSOliver Stannard   }
498dc4a6f5dSOliver Stannard 
499dc4a6f5dSOliver Stannard   assert(Stack.size() == 1 && "expected one value on stack");
5001d7311e0SOliver Stannard 
5011d7311e0SOliver Stannard   if (Stack.front().Kind == PrintedExpr::Address)
5021d7311e0SOliver Stannard     OS << "[" << Stack.front().String << "]";
5031d7311e0SOliver Stannard   else
504dc4a6f5dSOliver Stannard     OS << Stack.front().String;
505dc4a6f5dSOliver Stannard 
506dc4a6f5dSOliver Stannard   return true;
507dc4a6f5dSOliver Stannard }
508dc4a6f5dSOliver Stannard 
printCompact(raw_ostream & OS,const MCRegisterInfo & MRI)509dc4a6f5dSOliver Stannard bool DWARFExpression::printCompact(raw_ostream &OS, const MCRegisterInfo &MRI) {
510dc4a6f5dSOliver Stannard   return printCompactDWARFExpr(OS, begin(), end(), MRI);
511dc4a6f5dSOliver Stannard }
512dc4a6f5dSOliver Stannard 
operator ==(const DWARFExpression & RHS) const513f8122d35SGreg Clayton bool DWARFExpression::operator==(const DWARFExpression &RHS) const {
514f8122d35SGreg Clayton   if (AddressSize != RHS.AddressSize || Format != RHS.Format)
515f8122d35SGreg Clayton     return false;
516f8122d35SGreg Clayton   return Data.getData() == RHS.Data.getData();
517f8122d35SGreg Clayton }
518f8122d35SGreg Clayton 
519a058736cSReid Kleckner } // namespace llvm
520