LLVM: lib/DebugInfo/LogicalView/Core/LVLocation.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

17

18using namespace llvm;

20

21#define DEBUG_TYPE "Location"

22

24

25

26

30

31 auto PrintRegisterInfo = [&](LVSmall Code) {

32

33

34

35 if (dwarf::DW_OP_lit0 <= Code && Code <= dwarf::DW_OP_lit31) {

36 Stream << format("lit%d", Code - dwarf::DW_OP_lit0);

37 return;

38 }

39

40

41

42

43 if (dwarf::DW_OP_breg0 <= Code && Code <= dwarf::DW_OP_breg31) {

45 Stream << format("breg%d+%d%s", Code - dwarf::DW_OP_breg0, Operands[0],

46 RegisterName.c_str());

47 return;

48 }

49

50

51

52

53 if (dwarf::DW_OP_reg0 <= Code && Code <= dwarf::DW_OP_reg31) {

55 Stream << format("reg%d%s", Code - dwarf::DW_OP_reg0,

56 RegisterName.c_str());

57 return;

58 }

59

62 };

63

64 switch (Opcode) {

65

66

67

68 case dwarf::DW_OP_addr:

69 Stream << "addr " << hexString(Operands[0]);

70 break;

71 case dwarf::DW_OP_constu:

72 case dwarf::DW_OP_const1u:

73 case dwarf::DW_OP_const2u:

74 case dwarf::DW_OP_const4u:

75 case dwarf::DW_OP_const8u:

76 Stream << "const_u " << unsigned(Operands[0]);

77 break;

78 case dwarf::DW_OP_consts:

79 case dwarf::DW_OP_const1s:

80 case dwarf::DW_OP_const2s:

81 case dwarf::DW_OP_const4s:

82 case dwarf::DW_OP_const8s:

83 Stream << "const_s " << int(Operands[0]);

84 break;

85 case dwarf::DW_OP_addrx:

86 Stream << "addrx " << unsigned(Operands[0]);

87 break;

88 case dwarf::DW_OP_constx:

89 Stream << "constx " << unsigned(Operands[0]);

90 break;

91 case dwarf::DW_OP_const_type:

92 Stream << "TODO: DW_OP_const_type";

93 break;

94

95

96

97

98 case dwarf::DW_OP_fbreg:

99 Stream << "fbreg " << int(Operands[0]);

100 break;

101 case dwarf::DW_OP_bregx: {

103 Stream << format("bregx %d%s+%d", Operands[0], RegisterName.c_str(),

104 unsigned(Operands[1]));

105 break;

106 }

107 case dwarf::DW_OP_regval_type: {

109 Stream << format("regval_type %d%s+%d", Operands[0], RegisterName.c_str(),

110 unsigned(Operands[1]));

111 break;

112 }

113

114

115

116

117 case dwarf::DW_OP_dup:

118 Stream << "dup";

119 break;

120 case dwarf::DW_OP_drop:

121 Stream << "drop";

122 break;

123 case dwarf::DW_OP_pick:

124 Stream << "pick " << unsigned(Operands[0]);

125 break;

126 case dwarf::DW_OP_over:

127 Stream << "over";

128 break;

129 case dwarf::DW_OP_swap:

130 Stream << "swap";

131 break;

132 case dwarf::DW_OP_rot:

133 Stream << "rot";

134 break;

135 case dwarf::DW_OP_deref:

136 Stream << "deref";

137 break;

138 case dwarf::DW_OP_deref_size:

139 Stream << "deref_size " << unsigned(Operands[0]);

140 break;

141 case dwarf::DW_OP_deref_type:

142 Stream << "deref_type " << unsigned(Operands[0]) << " DIE offset "

144 break;

145 case dwarf::DW_OP_xderef:

146 Stream << "xderef";

147 break;

148 case dwarf::DW_OP_xderef_size:

149 Stream << "xderef_size " << unsigned(Operands[0]);

150 break;

151 case dwarf::DW_OP_xderef_type:

152 Stream << "xderef_type " << unsigned(Operands[0]) << " DIE offset "

154 break;

155 case dwarf::DW_OP_push_object_address:

156 Stream << "push_object_address";

157 break;

158 case dwarf::DW_OP_form_tls_address:

159 Stream << "form_tls_address";

160 break;

161 case dwarf::DW_OP_call_frame_cfa:

162 Stream << "call_frame_cfa";

163 break;

164

165

166

167

168 case dwarf::DW_OP_abs:

169 Stream << "abs";

170 break;

171 case dwarf::DW_OP_and:

172 Stream << "and";

173 break;

174 case dwarf::DW_OP_div:

175 Stream << "div";

176 break;

177 case dwarf::DW_OP_minus:

178 Stream << "minus";

179 break;

180 case dwarf::DW_OP_mod:

181 Stream << "mod";

182 break;

183 case dwarf::DW_OP_mul:

184 Stream << "mul";

185 break;

186 case dwarf::DW_OP_neg:

187 Stream << "neg";

188 break;

189 case dwarf::DW_OP_not:

190 Stream << "not";

191 break;

192 case dwarf::DW_OP_or:

193 Stream << "or";

194 break;

195 case dwarf::DW_OP_plus:

196 Stream << "plus";

197 break;

198 case dwarf::DW_OP_plus_uconst:

199 Stream << "plus_uconst " << unsigned(Operands[0]);

200 break;

201 case dwarf::DW_OP_shl:

202 Stream << "shl";

203 break;

204 case dwarf::DW_OP_shr:

205 Stream << "shr";

206 break;

207 case dwarf::DW_OP_shra:

208 Stream << "shra";

209 break;

210 case dwarf::DW_OP_xor:

211 Stream << "xor";

212 break;

213

214

215

216

217 case dwarf::DW_OP_le:

218 Stream << "le";

219 break;

220 case dwarf::DW_OP_ge:

221 Stream << "ge";

222 break;

223 case dwarf::DW_OP_eq:

224 Stream << "eq";

225 break;

226 case dwarf::DW_OP_lt:

227 Stream << "lt";

228 break;

229 case dwarf::DW_OP_gt:

230 Stream << "gt";

231 break;

232 case dwarf::DW_OP_ne:

233 Stream << "ne";

234 break;

235 case dwarf::DW_OP_skip:

236 Stream << "skip " << signed(Operands[0]);

237 break;

238 case dwarf::DW_OP_bra:

239 Stream << "bra " << signed(Operands[0]);

240 break;

241 case dwarf::DW_OP_call2:

242 Stream << "call2 DIE offset " << hexString(Operands[0]);

243 break;

244 case dwarf::DW_OP_call4:

245 Stream << "call4 DIE offset " << hexString(Operands[0]);

246 break;

247 case dwarf::DW_OP_call_ref:

248 Stream << "call_ref DIE offset " << hexString(Operands[0]);

249 break;

250

251

252

253

254 case dwarf::DW_OP_convert:

255 Stream << "convert DIE offset " << hexString(Operands[0]);

256 break;

257 case dwarf::DW_OP_reinterpret:

258 Stream << "reinterpret DIE offset " << hexString(Operands[0]);

259 break;

260

261

262

263

264 case dwarf::DW_OP_nop:

265 Stream << "nop";

266 break;

267 case dwarf::DW_OP_entry_value:

268 Stream << "TODO: DW_OP_entry_value";

269 break;

270

271

272

273

274 case dwarf::DW_OP_regx:

276 break;

277

278

279

280

281 case dwarf::DW_OP_stack_value:

282 Stream << "stack_value";

283 break;

284 case dwarf::DW_OP_implicit_value:

285 Stream << "TODO: DW_OP_implicit_value";

286 break;

287 case dwarf::DW_OP_implicit_pointer:

288 Stream << "implicit_pointer DIE offset " << hexString(Operands[0]) << " "

289 << int(Operands[1]);

290 break;

291

292

293

294

295 case dwarf::DW_OP_piece:

296 Stream << "piece " << int(Operands[0]);

297 break;

298 case dwarf::DW_OP_bit_piece:

299 Stream << "bit_piece " << int(Operands[0]) << " offset "

300 << int(Operands[1]);

301 break;

302

303

304

305

306 case dwarf::DW_OP_GNU_entry_value:

307 Stream << "gnu_entry_value ";

308 PrintRegisterInfo(dwarf::DW_OP_reg0);

309 break;

310 case dwarf::DW_OP_GNU_push_tls_address:

311 Stream << "gnu_push_tls_address";

312 break;

313 case dwarf::DW_OP_GNU_addr_index:

314 Stream << "gnu_addr_index " << unsigned(Operands[0]);

315 break;

316 case dwarf::DW_OP_GNU_const_index:

317 Stream << "gnu_const_index " << unsigned(Operands[0]);

318 break;

319

320

321

322

324 Stream << "offset " << int(Operands[0]);

325 break;

326

327

328

329

331 Stream << "missing";

332 break;

333

334

335

336

337 default:

338 PrintRegisterInfo(Opcode);

339 break;

340 }

341

343}

344

345

346

350

351

353

354 switch (OperationCode) {

355

356 case codeview::SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL:

357 Stream << "frame_pointer_rel " << int(Operands[0]);

358 break;

359 case codeview::SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:

360 Stream << "frame_pointer_rel_full_scope " << int(Operands[0]);

361 break;

362

363

364 case codeview::SymbolKind::S_DEFRANGE_REGISTER:

366 break;

367 case codeview::SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER:

368 Stream << "subfield_register "

370 break;

371

372

373 case codeview::SymbolKind::S_DEFRANGE_REGISTER_REL:

375 << " offset " << int(Operands[1]);

376 break;

377

378

379 case codeview::SymbolKind::S_DEFRANGE:

380 Stream << "frame " << int(Operands[0]);

381 break;

382 case codeview::SymbolKind::S_DEFRANGE_SUBFIELD:

383 Stream << "subfield " << int(Operands[0]);

384 break;

385

386 default:

387 Stream << format("#0x%02x: ", Opcode) << hexString(Operands[0]) << " "

388 << hexString(Operands[1]) << "#";

389 break;

390 }

391

393}

394

395namespace {

396const char *const KindBaseClassOffset = "BaseClassOffset";

397const char *const KindBaseClassStep = "BaseClassStep";

398const char *const KindClassOffset = "ClassOffset";

399const char *const KindFixedAddress = "FixedAddress";

400const char *const KindMissingInfo = "Missing";

401const char *const KindOperation = "Operation";

402const char *const KindOperationList = "OperationList";

403const char *const KindRegister = "Register";

404const char *const KindUndefined = "Undefined";

405}

406

407

408

409

411 const char *Kind = KindUndefined;

412 if (getIsBaseClassOffset())

413 Kind = KindBaseClassOffset;

414 else if (getIsBaseClassStep())

415 Kind = KindBaseClassStep;

416 else if (getIsClassOffset())

417 Kind = KindClassOffset;

418 else if (getIsFixedAddress())

419 Kind = KindFixedAddress;

420 else if (getIsGapEntry())

421 Kind = KindMissingInfo;

422 else if (getIsOperation())

423 Kind = KindOperation;

424 else if (getIsOperationList())

425 Kind = KindOperationList;

426 else if (getIsRegister())

427 Kind = KindRegister;

429}

430

432 static const char *const Question = "?";

435 if (getIsAddressRange())

436 Stream << "{Range}";

437

438 auto PrintLine = [&](const LVLine *Line) {

440 std::string TheLine;

441 TheLine = Line->lineNumberAsStringStripped();

442 Stream << TheLine.c_str();

443 } else {

444 Stream << Question;

445 }

446 };

447

448 Stream << " Lines ";

450 Stream << ":";

452

453 if (options().getAttributeOffset())

454

457

459}

460

461

463

464

465

466

467

468

469 if (!hasAssociatedRange())

470 return true;

471

475 if (LowLine)

477 else {

478 setIsInvalidLower();

479 return false;

480 }

481 if (HighLine)

483 else {

484 setIsInvalidUpper();

485 return false;

486 }

487

489 setIsInvalidRange();

490 return false;

491 }

492

493 return true;

494}

495

497 float &Percentage) {

499 return false;

500

501

502

504

506

507

509 if (Location->getIsLocationSimple()) {

510 Factor = 100;

511 Percentage = 100;

512 return true;

513 }

514 }

515

516

520

521 if (Location->getIsGapEntry()) {

522 LowerAddress = Location->getLowerAddress();

523 UpperAddress = Location->getUpperAddress();

524 Factor += (UpperAddress > LowerAddress) ? UpperAddress - LowerAddress

525 : LowerAddress - UpperAddress;

526 }

527

528 Percentage = 0;

529 return false;

530}

531

539

541 if (hasAssociatedRange())

543}

544

546 if (getReader().doPrintLocation(this)) {

549 }

550}

551

556

557

558

559

560

566

567

568 setOffset(LocDescOffset ? LocDescOffset : SectionOffset);

569

570

572 setIsDiscardedRange();

573

574

576}

577

578

581 if (!Entries)

582 Entries = std::make_unique();

583 Entries->push_back(getReader().createOperation(Opcode, Operands));

584}

585

586

589 case dwarf::DW_AT_data_member_location:

590 setIsClassOffset();

591 break;

592 case dwarf::DW_AT_location:

593

594 setIsFixedAddress();

595 break;

596 default:

597 break;

598 }

599

600

601

602 if (hasAssociatedRange())

604}

605

607

608 if (Entries && Entries->size() == 1) {

609 if (dwarf::DW_OP_fbreg == Entries->front()->getOpcode())

610 setIsStackOffset();

611 }

612}

613

619

620

623 return;

624

625

626 if (options().getAttributeCoverage()) {

627

628

631 float Percentage = Symbol->getCoveragePercentage();

632

633

636 Stream << format("%.2f%%", Percentage);

637 if (Location->getIsLocationSimple())

638 Stream << format(" (%d/%d)", Symbol->getCoverageFactor(),

639 Symbol->getParentScope()->getCoverageFactor());

641 false,

642 false);

643 }

644

645

646 if (getReader().doPrintLocation(nullptr))

649}

650

652 OS << "{Location}";

653 if (getIsCallSite())

654 OS << " -> CallSite";

656 OS << "\n";

657

658

659 if (Full && Entries) {

660 bool CodeViewLocation = getParentSymbol()->getHasCodeViewLocation();

661 std::stringstream Stream;

662 std::string Leading;

664 Stream << Leading

665 << (CodeViewLocation ? Operation->getOperandsCodeViewInfo()

666 : Operation->getOperandsDWARFInfo());

667 Leading = ", ";

668 }

671 false,

672 false);

673 }

674}

static std::string getRegisterName(const TargetRegisterInfo *TRI, Register Reg)

PowerPC Reduce CR logical Operation

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

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

void printExtra(raw_ostream &OS, bool Full=true) const override

Definition LVLocation.cpp:651

void printRawExtra(raw_ostream &OS, bool Full=true) const override

Definition LVLocation.cpp:614

void addObject(LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset, uint64_t LocDescOffset) override

Definition LVLocation.cpp:561

const char * kind() const override

Definition LVLocation.cpp:410

static bool calculateCoverage(LVLocations *Locations, unsigned &Factor, float &Percentage)

Definition LVLocation.cpp:496

void setUpperAddress(LVAddress Address) override

const LVLine * getLowerLine() const

void setUpperLine(LVLine *Line)

virtual void updateKind()

std::string getIntervalInfo() const

Definition LVLocation.cpp:431

virtual void printRawExtra(raw_ostream &OS, bool Full=true) const

void printRaw(raw_ostream &OS, bool Full=true) const

Definition LVLocation.cpp:532

LVAddress getLowerAddress() const override

void setKind()

Definition LVLocation.cpp:587

bool validateRanges()

Definition LVLocation.cpp:462

const LVLine * getUpperLine() const

void printExtra(raw_ostream &OS, bool Full=true) const override

Definition LVLocation.cpp:552

static void print(LVLocations *Locations, raw_ostream &OS, bool Full=true)

Definition LVLocation.cpp:621

void setLowerLine(LVLine *Line)

LVAddress getUpperAddress() const override

void printInterval(raw_ostream &OS, bool Full=true) const

Definition LVLocation.cpp:540

void setLowerAddress(LVAddress Address) override

virtual void print(raw_ostream &OS, bool Full=true) const

void printAttributes(raw_ostream &OS, bool Full=true) const

dwarf::Attribute getAttr() const

LVSymbol * getParentSymbol() const

uint32_t getLineNumber() const

void setOffset(LVOffset DieOffset)

LLVM_ABI void print(raw_ostream &OS, bool Full=true) const

Definition LVLocation.cpp:23

LLVM_ABI std::string getOperandsDWARFInfo()

Definition LVLocation.cpp:27

LLVM_ABI std::string getOperandsCodeViewInfo()

Definition LVLocation.cpp:347

virtual std::string getRegisterName(LVSmall Opcode, ArrayRef< uint64_t > Operands)

LVLineRange lineRange(LVLocation *Location) const

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

A raw_ostream that writes to an std::string.

std::string hexString(uint64_t Value, size_t Width=HEX_WIDTH)

uint16_t getCodeViewOperationCode(uint8_t Code)

LVScopeCompileUnit * getReaderCompileUnit()

std::pair< LVLine *, LVLine * > LVLineRange

const LVSmall LVLocationMemberOffset

SmallVector< LVLocation *, 8 > LVLocations

This is an optimization pass for GlobalISel generic memory operations.

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

These are helper functions used to produce formatted output.