LLVM: lib/DebugInfo/DWARF/DWARFExpression.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

13#include

14#include

15#include

16

17using namespace llvm;

18using namespace dwarf;

19

20namespace llvm {

21

24

26 std::vector Descriptions;

27 Descriptions.resize(0xff);

70 for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA)

72 for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA)

74 for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA)

83 Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3);

87 Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3);

88 Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3);

90 Descriptions[DW_OP_implicit_value] =

93 Descriptions[DW_OP_implicit_pointer] =

99 Descriptions[DW_OP_regval_type] =

101 Descriptions[DW_OP_WASM_location] =

103 Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);

107

108

109

111 return Descriptions;

112}

113

115

116 if (Opcode >= Descriptions.size())

117 return {};

118 return Descriptions[Opcode];

119}

120

123 return getDescImpl(Descriptions, Opcode);

124}

125

127 static constexpr unsigned LlvmUserDescriptionsSize = 1

128#define HANDLE_DW_OP_LLVM_USEROP(ID, NAME) +1

129#include "llvm/BinaryFormat/Dwarf.def"

130 ;

131 std::vector Descriptions;

132 Descriptions.resize(LlvmUserDescriptionsSize);

134 return Descriptions;

135}

136

138 assert(Opcode == DW_OP_LLVM_user);

140 return getDescImpl(Descriptions, SubOpcode);

141}

142

145 std::optional Format) {

147 Opcode = Data.getU8(&Offset);

148

151 return false;

152

155 for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) {

158

161 assert(Operand == 0 && "SubOp operand must be the first operand");

162 Operands[Operand] = Data.getULEB128(&Offset);

165 return false;

167 "SizeSubOpLEB Description must begin with SizeSubOpLEB operand");

168 break;

170 Operands[Operand] = Data.getU8(&Offset);

172 Operands[Operand] = (int8_t)Operands[Operand];

173 break;

175 Operands[Operand] = Data.getU16(&Offset);

177 Operands[Operand] = (int16_t)Operands[Operand];

178 break;

180 Operands[Operand] = Data.getU32(&Offset);

182 Operands[Operand] = (int32_t)Operands[Operand];

183 break;

185 Operands[Operand] = Data.getU64(&Offset);

186 break;

188 Operands[Operand] = Data.getUnsigned(&Offset, AddressSize);

189 break;

191 if (!Format)

192 return false;

193 Operands[Operand] =

195 break;

198 Operands[Operand] = Data.getSLEB128(&Offset);

199 else

200 Operands[Operand] = Data.getULEB128(&Offset);

201 break;

203 Operands[Operand] = Data.getULEB128(&Offset);

204 break;

206 assert(Operand == 1);

207 switch (Operands[0]) {

208 case 0:

209 case 1:

210 case 2:

211 case 4:

212 Operands[Operand] = Data.getULEB128(&Offset);

213 break;

214 case 3:

215 Operands[Operand] = Data.getU32(&Offset);

216 break;

217 default:

218 return false;

219 }

220 break;

222

223 if (Operand == 0)

224 return false;

225

226 Operands[Operand] = Offset;

227 Offset += Operands[Operand - 1];

228 break;

229 default:

231 }

232

233 OperandEndOffsets[Operand] = Offset;

234 }

235

237 return true;

238}

239

243 unsigned Operand) {

244 assert(Operand < Operands.size() && "operand out of bounds");

245 if (!U) {

246 OS << format(" <base_type ref: 0x%" PRIx64 ">", Operands[Operand]);

247 return;

248 }

249 auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]);

250 if (Die && Die.getTag() == dwarf::DW_TAG_base_type) {

251 OS << " (";

254 OS << format("0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]);

256 OS << " \"" << *Name << "\"";

257 } else {

258 OS << format(" <invalid base_type ref: 0x%" PRIx64 ">", Operands[Operand]);

259 }

260}

261

267 return false;

268

270 unsigned OpNum = 0;

271

272 if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx ||

273 Opcode == DW_OP_regval_type)

274 DwarfRegNum = Operands[OpNum++];

275 else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx)

276 DwarfRegNum = Opcode - DW_OP_breg0;

277 else

278 DwarfRegNum = Opcode - DW_OP_reg0;

279

282 if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||

283 Opcode == DW_OP_bregx)

285 else

287

288 if (Opcode == DW_OP_regval_type)

290 return true;

291 }

292

293 return false;

294}

295

298 return std::nullopt;

300}

301

306 OS << "";

307 return false;

308 }

309

311 assert(Name.empty() && "DW_OP has no name!");

313

314 if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||

315 (Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) ||

316 Opcode == DW_OP_bregx || Opcode == DW_OP_regx ||

317 Opcode == DW_OP_regval_type)

319 return true;

320

321 for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) {

324

327 assert(!SubName.empty() && "DW_OP SubOp has no name!");

328 OS << " " << SubName;

330

331

332

333 if (Opcode == DW_OP_convert && Operands[Operand] == 0)

334 OS << " 0x0";

335 else

338 assert(Operand == 1);

340 case 0:

341 case 1:

342 case 2:

343 case 3:

344 case 4:

346 break;

347 default: assert(false);

348 }

351 for (unsigned i = 0; i < Operands[Operand - 1]; ++i)

353 } else {

356 else if (Opcode != DW_OP_entry_value &&

357 Opcode != DW_OP_GNU_entry_value)

359 }

360 }

361 return true;

362}

363

366 uint32_t EntryValExprSize = 0;

367 uint64_t EntryValStartOffset = 0;

368 if (Data.getData().empty())

369 OS << "";

370

371 for (auto &Op : *this) {

372 DumpOpts.IsEH = IsEH;

373 if (Op.print(OS, DumpOpts, this, U)) {

375 while (FailOffset < Data.getData().size())

376 OS << format(" %02x", Data.getU8(&FailOffset));

377 return;

378 }

379

380 if (Op.getCode() == DW_OP_entry_value ||

381 Op.getCode() == DW_OP_GNU_entry_value) {

382 OS << "(";

385 continue;

386 }

387

388 if (EntryValExprSize) {

389 EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset;

390 if (EntryValExprSize == 0)

391 OS << ")";

392 }

393

395 OS << ", ";

396 }

397}

398

400 for (unsigned Operand = 0; Operand < Op.Desc.Op.size(); ++Operand) {

401 unsigned Size = Op.Desc.Op[Operand];

402

404

405

406

407

408 if (Op.Opcode == DW_OP_convert && Op.Operands[Operand] == 0)

409 continue;

410 auto Die = U->getDIEForOffset(U->getOffset() + Op.Operands[Operand]);

411 if (!Die || Die.getTag() != dwarf::DW_TAG_base_type)

412 return false;

413 }

414 }

415

416 return true;

417}

418

420 for (auto &Op : *this)

422 return false;

423

424 return true;

425}

426

427

428

429

434 };

437

439};

440

444 std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg =

445 nullptr) {

447

448 while (I != E) {

451 switch (Opcode) {

452 case dwarf::DW_OP_regx: {

453

454

456 auto RegName = GetNameForDWARFReg(DwarfRegNum, false);

458 return false;

461 break;

462 }

463 case dwarf::DW_OP_bregx: {

466 auto RegName = GetNameForDWARFReg(DwarfRegNum, false);

468 return false;

473 break;

474 }

475 case dwarf::DW_OP_entry_value:

476 case dwarf::DW_OP_GNU_entry_value: {

477

478

481 ++I;

483 S << "entry(";

485 S << ")";

486 I = SubExprEnd;

487 continue;

488 }

489 case dwarf::DW_OP_stack_value: {

490

491

492 assert(!Stack.empty());

494 break;

495 }

496 case dwarf::DW_OP_nop: {

497 break;

498 }

499 case dwarf::DW_OP_LLVM_user: {

501 break;

502 }

503 default:

504 if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) {

505

506

507 uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0;

508 auto RegName = GetNameForDWARFReg(DwarfRegNum, false);

510 return false;

513 } else if (Opcode >= dwarf::DW_OP_breg0 &&

514 Opcode <= dwarf::DW_OP_breg31) {

515 int DwarfRegNum = Opcode - dwarf::DW_OP_breg0;

517 auto RegName = GetNameForDWARFReg(DwarfRegNum, false);

519 return false;

524 } else {

525

526

528 << (int)Opcode << ")>";

529 return false;

530 }

531 break;

532 }

533 ++I;

534 }

535

536 if (Stack.size() != 1) {

537 OS << "<stack of size " << Stack.size() << ", expected 1>";

538 return false;

539 }

540

542 OS << "[" << Stack.front().String << "]";

543 else

544 OS << Stack.front().String;

545

546 return true;

547}

548

551 std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {

553}

554

556 if (AddressSize != RHS.AddressSize || Format != RHS.Format)

557 return false;

558 return Data.getData() == RHS.Data.getData();

559}

560

561}

mir Rename Register Operands

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallString class.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

This class represents an Operation in the Expression.

std::optional< unsigned > getSubCode() const

@ DwarfNA

Serves as a marker for unused entries.

static bool verify(const Operation &Op, DWARFUnit *U)

Verify Op. Does not affect the return of isError().

bool print(raw_ostream &OS, DIDumpOptions DumpOpts, const DWARFExpression *Expr, DWARFUnit *U) const

uint64_t getEndOffset() const

@ SizeSubOpLEB

The operand is a ULEB128 encoded SubOpcode.

@ SizeBlock

Preceding operand contains block size.

uint64_t getRawOperand(unsigned Idx) const

An iterator to go through the expression operations.

bool verify(DWARFUnit *U)

bool printCompact(raw_ostream &OS, std::function< StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg=nullptr)

Print the expression in a format intended to be compact and useful to a user, but not perfectly unamb...

bool operator==(const DWARFExpression &RHS) const

void print(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFUnit *U, bool IsEH=false) const

static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, DIDumpOptions DumpOpts, uint8_t Opcode, const ArrayRef< uint64_t > Operands)

Lightweight error class with error context and mandatory checking.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

constexpr bool empty() const

empty - Check if the string is empty.

This class implements an extremely fast bulk output stream that can only output to a stream.

A raw_ostream that writes to an SmallVector or SmallString.

StringRef SubOperationEncodingString(unsigned OpEncoding, unsigned SubOpEncoding)

StringRef OperationEncodingString(unsigned Encoding)

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)

Take an optional DWARFFormValue and try to extract a string value from it.

uint8_t getDwarfOffsetByteSize(DwarfFormat Format)

The size of a reference determined by the DWARF 32/64-bit format.

This is an optimization pass for GlobalISel generic memory operations.

static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode)

static std::vector< Desc > getOpDescriptions()

static bool printCompactDWARFExpr(raw_ostream &OS, DWARFExpression::iterator I, const DWARFExpression::iterator E, std::function< StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg=nullptr)

static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS, DIDumpOptions DumpOpts, ArrayRef< uint64_t > Operands, unsigned Operand)

format_object< Ts... > format(const char *Fmt, const Ts &... Vals)

These are helper functions used to produce formatted output.

static Desc getDescImpl(ArrayRef< Desc > Descriptions, unsigned Opcode)

DWARFExpression::Operation Op

static Desc getOpDesc(unsigned Opcode)

static std::vector< Desc > getSubOpDescriptions()

Container for dump options that control which debug information will be dumped.

std::function< llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)> GetNameForDWARFReg

Description of the encoding of one expression Op.

DwarfVersion Version

Dwarf version where the Op was introduced.

SmallVector< Encoding > Op

Encoding for Op operands.

A user-facing string representation of a DWARF expression.

PrintedExpr(ExprKind K=Address)