LLVM: lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

33

34using namespace llvm;

39

40#define DEBUG_TYPE "CodeViewUtilities"

41

42namespace llvm {

43namespace logicalview {

44

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

70 return TI;

71}

72

74#define CV_TYPE(enum, val) {#enum, enum},

75#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"

76};

77

78

79

82 return {};

83

86 auto GetName = [&](auto Record) {

90 else

92 };

93

95 if (RK == TypeRecordKind::Class || RK == TypeRecordKind::Struct)

97 else if (RK == TypeRecordKind::Union)

99 else if (RK == TypeRecordKind::Enum)

101

102 return RecordName;

103}

104

105}

106}

107

108#undef DEBUG_TYPE

109#define DEBUG_TYPE "CodeViewDataVisitor"

110

111namespace llvm {

112namespace logicalview {

113

114

116

117namespace {

118

119class LVTypeRecords {

121

122

123 using RecordEntry = std::pair<TypeLeafKind, LVElement *>;

124 using RecordTable = std::map<TypeIndex, RecordEntry>;

125 RecordTable RecordFromTypes;

126 RecordTable RecordFromIds;

127

128 using NameTable = std::map<StringRef, TypeIndex>;

129 NameTable NameFromTypes;

130 NameTable NameFromIds;

131

132public:

133 LVTypeRecords(LVShared *Shared) : Shared(Shared) {}

134

140};

141

142class LVForwardReferences {

143

144 using ForwardEntry = std::pair<TypeIndex, TypeIndex>;

145 using ForwardTypeNames = std::map<StringRef, ForwardEntry>;

146 ForwardTypeNames ForwardTypesNames;

147

148

149 using ForwardType = std::map<TypeIndex, TypeIndex>;

150 ForwardType ForwardTypes;

151

152

154 ForwardTypes.emplace(TIForward, TIReference);

155 }

156

158 if (ForwardTypesNames.find(Name) == ForwardTypesNames.end()) {

159 ForwardTypesNames.emplace(

160 std::piecewise_construct, std::forward_as_tuple(Name),

162 } else {

163

164 ForwardTypesNames[Name].first = TIForward;

165 add(TIForward, ForwardTypesNames[Name].second);

166 }

167 }

168

169

171 auto It = ForwardTypesNames.find(Name);

172 if (It != ForwardTypesNames.end()) {

173

174 It->second.second = TIReference;

175 add(It->second.first, TIReference);

176 } else {

177

178 ForwardTypesNames.emplace(

179 std::piecewise_construct, std::forward_as_tuple(Name),

181 }

182 }

183

184public:

185 LVForwardReferences() = default;

186

188

189

190

191 (IsForwardRef) ? add(Name, TI) : update(Name, TI);

192 }

193

195 auto It = ForwardTypes.find(TIForward);

196 return It != ForwardTypes.end() ? It->second : TypeIndex::None();

197 }

198

200 auto It = ForwardTypesNames.find(Name);

201 return It != ForwardTypesNames.end() ? It->second.second

203 }

204

205

206

209 return Forward.isNoneType() ? TI : Forward;

210 }

211};

212

213

214class LVNamespaceDeduction {

216

217 using Names = std::map<StringRef, LVScope *>;

218 Names NamespaceNames;

219

220 using LookupSet = std::set;

221 LookupSet DeducedScopes;

222 LookupSet UnresolvedScopes;

223 LookupSet IdentifiedNamespaces;

224

226 if (NamespaceNames.find(Name) == NamespaceNames.end())

227 NamespaceNames.emplace(Name, Namespace);

228 }

229

230public:

231 LVNamespaceDeduction(LVShared *Shared) : Shared(Shared) {}

232

233 void init();

237

238

240 auto It = NamespaceNames.find(Name);

241 LVScope *Namespace = It != NamespaceNames.end() ? It->second : nullptr;

242 return Namespace;

243 }

244

245

246

247

249 if (Components.empty())

250 return {};

251

252 LVStringRefs::size_type FirstNamespace = 0;

253 LVStringRefs::size_type FirstNonNamespace;

254 for (LVStringRefs::size_type Index = 0; Index < Components.size();

255 ++Index) {

256 FirstNonNamespace = Index;

257 LookupSet::iterator Iter = IdentifiedNamespaces.find(Components[Index]);

258 if (Iter == IdentifiedNamespaces.end())

259

260 break;

261 }

262 return std::make_tuple(FirstNamespace, FirstNonNamespace);

263 }

264};

265

266

267class LVStringRecords {

268 using StringEntry = std::tuple<uint32_t, std::string, LVScopeCompileUnit *>;

269 using StringIds = std::map<TypeIndex, StringEntry>;

270 StringIds Strings;

271

272public:

273 LVStringRecords() = default;

274

277 if (Strings.find(TI) == Strings.end())

278 Strings.emplace(

279 std::piecewise_construct, std::forward_as_tuple(TI),

280 std::forward_as_tuple(++Index, std::string(String), nullptr));

281 }

282

284 StringIds::iterator Iter = Strings.find(TI);

285 return Iter != Strings.end() ? std::get<1>(Iter->second) : StringRef{};

286 }

287

289 StringIds::iterator Iter = Strings.find(TI);

290 return Iter != Strings.end() ? std::get<0>(Iter->second) : 0;

291 }

292

293

294 void addFilenames();

296};

297}

298

301

302

303

304

305

314

315

316

317

318

321

326};

327}

328}

329

332 RecordTable &Target =

333 (StreamIdx == StreamTPI) ? RecordFromTypes : RecordFromIds;

334 Target.emplace(std::piecewise_construct, std::forward_as_tuple(TI),

335 std::forward_as_tuple(Kind, Element));

336}

337

339 NameTable &Target = (StreamIdx == StreamTPI) ? NameFromTypes : NameFromIds;

341}

342

344 RecordTable &Target =

345 (StreamIdx == StreamTPI) ? RecordFromTypes : RecordFromIds;

346

348 RecordTable::iterator Iter = Target.find(TI);

349 if (Iter != Target.end()) {

350 Element = Iter->second.second;

351 if (Element || !Create)

352 return Element;

353

354

356 if (Element) {

358 Element->setOffsetFromTypeIndex();

359 Target[TI].second = Element;

360 }

361 }

362 return Element;

363}

364

366 NameTable &Target = (StreamIdx == StreamTPI) ? NameFromTypes : NameFromIds;

367 NameTable::iterator Iter = Target.find(Name);

369}

370

371void LVStringRecords::addFilenames() {

372 for (StringIds::const_reference Entry : Strings) {

376 }

377 Strings.clear();

378}

379

381 for (StringIds::reference Entry : Strings)

382 if (!std::get<2>(Entry.second))

384}

385

390 DeducedScopes.insert(InnerComponent);

391 if (OuterComponent.size())

392 UnresolvedScopes.insert(OuterComponent);

393}

394

395void LVNamespaceDeduction::init() {

396

397

398

399

400

402 for (const StringRef &Unresolved : UnresolvedScopes) {

404 for (const StringRef &Component : Components) {

405 LookupSet::iterator Iter = DeducedScopes.find(Component);

406 if (Iter == DeducedScopes.end())

407 IdentifiedNamespaces.insert(Component);

408 }

409 }

410

412 auto Print = [&](LookupSet &Container, const char *Title) {

413 auto Header = [&]() {

417 };

418 Header();

419 for (const StringRef &Item : Container)

420 dbgs() << formatv("'{0}'\n", Item.str().c_str());

421 };

422

423 Print(DeducedScopes, "Deducted Scopes");

424 Print(UnresolvedScopes, "Unresolved Scopes");

425 Print(IdentifiedNamespaces, "Namespaces");

426 });

427}

428

431 for (const StringRef &Component : Components)

433 });

434

435 if (Components.empty())

436 return nullptr;

437

438

439 LVScope *Namespace = nullptr;

441 for (const StringRef &Component : Components) {

442

443 Namespace = find(Component);

444 if (!Namespace) {

445

446

447 Namespace = Shared->Reader->createScopeNamespace();

448 Namespace->setTag(dwarf::DW_TAG_namespace);

449 Namespace->setName(Component);

452 add(Component, Namespace);

453 }

454 Parent = Namespace;

455 }

456 return Parent;

457}

458

459LVScope *LVNamespaceDeduction::get(StringRef ScopedName, bool CheckScope) {

461 if (CheckScope)

463 LookupSet::iterator Iter = IdentifiedNamespaces.find(Component);

464 return Iter == IdentifiedNamespaces.end();

465 });

466

468 { dbgs() << formatv("ScopedName: '{0}'\n", ScopedName.str().c_str()); });

469

470 return get(Components);

471}

472

473#undef DEBUG_TYPE

474#define DEBUG_TYPE "CodeViewTypeVisitor"

475

476

477

478

482 StreamIdx == StreamTPI ? Types : Ids);

483}

484

487}

488

493 });

494

495 if (options().getInternalTag())

497

498

499

500 CurrentTypeIndex = TI;

503}

504

508}

509

515 });

517}

518

523 });

525}

526

530}

531

532

534

538 for (TypeIndex Arg : Args.getArgs())

539 printTypeIndex("ArgType", Arg, StreamIPI);

540 });

541

542

543

544

547

548

549 TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::CurrentDirectory];

553

554

555 TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile];

560

562}

563

564

567 printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI);

568 printTypeIndex("FieldListType", Class.getFieldList(), StreamTPI);

570 });

571

572

575 CurrentTypeIndex);

576

577

578 Shared->TypeRecords.add(StreamIdx, CurrentTypeIndex, Class.getName());

580}

581

582

585 printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI);

586 printTypeIndex("FieldListType", Enum.getFieldList(), StreamTPI);

588 });

589

590

593}

594

595

598 printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI);

599 printTypeIndex("Type", Func.getFunctionType(), StreamTPI);

600 printTypeIndex("Parent", Func.getParentScope(), StreamTPI);

602 });

603

604

607}

608

609

612 printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI);

616 });

617

618

621}

622

623

625

629 });

631}

632

633

636

639 printTypeIndex("SourceFile", Line.getSourceFile(), StreamIPI);

641 });

642

643 Shared->LineRecords.push_back(CurrentTypeIndex);

645}

646

647

651 printTypeIndex("FieldList", Union.getFieldList(), StreamTPI);

654 if (Union.hasUniqueName())

656 });

657

658

661 CurrentTypeIndex);

662

663

664 Shared->TypeRecords.add(StreamIdx, CurrentTypeIndex, Union.getName());

666}

667

668#undef DEBUG_TYPE

669#define DEBUG_TYPE "CodeViewSymbolVisitor"

670

671

672

673

678 Reader->printRelocatedField(Label, CoffSection, RelocOffset, Offset,

679 RelocSym);

680}

681

686}

687

693 return {};

694 }

695 return *Name;

696}

697

699 return Reader->CVStringTable;

700}

701

702void LVSymbolVisitor::printLocalVariableAddrRange(

704 DictScope S(W, "LocalVariableAddrRange");

705 if (ObjDelegate)

707 Range.OffsetStart);

710}

711

712void LVSymbolVisitor::printLocalVariableAddrGap(

715 ListScope S(W, "LocalVariableAddrGap");

716 W.printHex("GapStartOffset", Gap.GapStartOffset);

717 W.printHex("Range", Gap.Range);

718 }

719}

720

721void LVSymbolVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {

723}

724

727}

728

734 });

735

736 if (options().getInternalTag())

738

742

743

744 });

746 }

747

748

749 CurrentOffset = Offset;

750 IsCompileUnit = false;

751 if (!LogicalVisitor->CurrentElement->getOffsetFromTypeIndex())

756 } else {

761 }

762

764}

765

770

773 }

774

776}

777

781}

782

783

789 });

790

793 if (ObjDelegate)

797

798 if (options().getGeneralCollectRanges()) {

799

804 Scope->addObject(LowPC, HighPC);

805 }

806 }

807

809}

810

811

815 printTypeIndex("Type", Local.Type);

818 });

819

821 Symbol->setName(Local.Name);

822

823

824

825

826

827

828

829 Symbol->resetIsVariable();

830

831 if (Local.Name == "this") {

832 Symbol->setIsParameter();

833 Symbol->setIsArtificial();

834 } else {

835

836 bool(Local.Offset > 0) ? Symbol->setIsParameter()

837 : Symbol->setIsVariable();

838 }

839

840

841 if (Symbol->getIsParameter())

842 Symbol->setTag(dwarf::DW_TAG_formal_parameter);

843

845 if (Element && Element->getIsScoped()) {

846

847 LVScope *Parent = Symbol->getFunctionParent();

848

849

850

851

852

853

854

858 }

859 }

860 Symbol->setType(Element);

861 }

862

864}

865

866

870 printTypeIndex("Type", Local.Type);

873 });

874

876 Symbol->setName(Local.Name);

877

878

879 Symbol->resetIsVariable();

880

881

882 if (Local.Name == "this") {

883 Symbol->setIsArtificial();

884 Symbol->setIsParameter();

885 } else {

886

887 determineSymbolKind(Symbol, Local.Register);

888 }

889

890

891 if (Symbol->getIsParameter())

892 Symbol->setTag(dwarf::DW_TAG_formal_parameter);

893

895 if (Element && Element->getIsScoped()) {

896

897 LVScope *Parent = Symbol->getFunctionParent();

898

899

900

901

902

903

904

908 }

909 }

910 Symbol->setType(Element);

911 }

912

914}

915

916

920

924 return Err;

925

927}

928

929

939 });

940

941

942

943

944

945

946

947

948

949

950

951

952

954

956 Scope->setName(CurrentObjectName);

957 if (options().getAttributeProducer())

958 Scope->setProducer(Compile2.Version);

960

961

962

964

965

967 }

968

969

970 CurrentObjectName = "";

972}

973

974

984 });

985

986

987

988

989

990

991

992

993

994

995

996

997

999

1001 Scope->setName(CurrentObjectName);

1002 if (options().getAttributeProducer())

1003 Scope->setProducer(Compile3.Version);

1005

1006

1007

1009

1010

1012 }

1013

1014

1015 CurrentObjectName = "";

1017}

1018

1019

1023 printTypeIndex("Type", Constant.Type);

1026 });

1027

1029 Symbol->setName(Constant.Name);

1031 Symbol->resetIncludeInPrint();

1032 }

1033

1035}

1036

1037

1041

1043 if (LocalSymbol)

1045

1046 W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset);

1047 });

1048

1049 if (LVSymbol *Symbol = LocalSymbol) {

1050 Symbol->setHasCodeViewLocation();

1051 LocalSymbol = nullptr;

1052

1053

1055 dwarf::Attribute(SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE);

1056

1057 uint64_t Operand1 = DefRangeFramePointerRelFullScope.Offset;

1058 Symbol->addLocation(Attr, 0, 0, 0, 0);

1059 Symbol->addLocationOperands(LVSmall(Attr), {Operand1});

1060 }

1061

1063}

1064

1065

1068

1070 if (LocalSymbol)

1072

1074 printLocalVariableAddrRange(DefRangeFramePointerRel.Range,

1076 printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);

1077 });

1078

1079

1080

1081

1082

1083 if (LVSymbol *Symbol = LocalSymbol) {

1084 Symbol->setHasCodeViewLocation();

1085 LocalSymbol = nullptr;

1086

1087

1091

1095

1097 Symbol->addLocationOperands(LVSmall(Attr), {Operand1});

1098 }

1099

1101}

1102

1103

1106

1108 if (LocalSymbol)

1110

1116 printLocalVariableAddrRange(DefRangeRegisterRel.Range,

1118 printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);

1119 });

1120

1121 if (LVSymbol *Symbol = LocalSymbol) {

1122 Symbol->setHasCodeViewLocation();

1123 LocalSymbol = nullptr;

1124

1125

1130

1134

1136 Symbol->addLocationOperands(LVSmall(Attr), {Operand1, Operand2});

1137 }

1138

1140}

1141

1142

1145

1147 if (LocalSymbol)

1149

1153 printLocalVariableAddrRange(DefRangeRegister.Range,

1155 printLocalVariableAddrGap(DefRangeRegister.Gaps);

1156 });

1157

1158 if (LVSymbol *Symbol = LocalSymbol) {

1159 Symbol->setHasCodeViewLocation();

1160 LocalSymbol = nullptr;

1161

1162

1165

1169

1171 Symbol->addLocationOperands(LVSmall(Attr), {Operand1});

1172 }

1173

1175}

1176

1177

1180

1182 if (LocalSymbol)

1184

1190 printLocalVariableAddrRange(DefRangeSubfieldRegister.Range,

1192 printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);

1193 });

1194

1195 if (LVSymbol *Symbol = LocalSymbol) {

1196 Symbol->setHasCodeViewLocation();

1197 LocalSymbol = nullptr;

1198

1199

1203

1207

1209 Symbol->addLocationOperands(LVSmall(Attr), {Operand1});

1210 }

1211

1213}

1214

1215

1218

1220 if (LocalSymbol)

1222

1223 if (ObjDelegate) {

1225 auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program);

1226 if (!ExpectedProgram) {

1228 return llvm::make_error(

1229 "String table offset outside of bounds of String Table!");

1230 }

1231 W.printString("Program", *ExpectedProgram);

1232 }

1234 printLocalVariableAddrRange(DefRangeSubfield.Range,

1236 printLocalVariableAddrGap(DefRangeSubfield.Gaps);

1237 });

1238

1239 if (LVSymbol *Symbol = LocalSymbol) {

1240 Symbol->setHasCodeViewLocation();

1241 LocalSymbol = nullptr;

1242

1243

1246

1250

1252 Symbol->addLocationOperands(LVSmall(Attr), {Operand1, 0});

1253 }

1254

1256}

1257

1258

1261

1263 if (LocalSymbol)

1265

1266 if (ObjDelegate) {

1268 auto ExpectedProgram = Strings.getString(DefRange.Program);

1269 if (!ExpectedProgram) {

1271 return llvm::make_error(

1272 "String table offset outside of bounds of String Table!");

1273 }

1274 W.printString("Program", *ExpectedProgram);

1275 }

1277 printLocalVariableAddrGap(DefRange.Gaps);

1278 });

1279

1280 if (LVSymbol *Symbol = LocalSymbol) {

1281 Symbol->setHasCodeViewLocation();

1282 LocalSymbol = nullptr;

1283

1284

1287

1291

1293 Symbol->addLocationOperands(LVSmall(Attr), {Operand1, 0});

1294 }

1295

1297}

1298

1299

1303

1304

1305

1306

1307

1308

1309

1310

1311

1313 if (FrameProcedureOptions::MarkedInline ==

1314 (Flags & FrameProcedureOptions::MarkedInline))

1316 if (FrameProcedureOptions::Inlined ==

1317 (Flags & FrameProcedureOptions::Inlined))

1319

1320

1321

1322

1323

1327 }

1328

1330}

1331

1332

1335 printTypeIndex("Type", Data.Type);

1337 });

1338

1341 if (ObjDelegate)

1344

1345 Symbol->setName(Data.Name);

1347

1348

1349

1350

1351

1352

1353

1355 Symbol->resetIncludeInPrint();

1357 }

1358

1360

1361

1362 if (Symbol->getParentScope()->removeElement(Symbol))

1364 }

1365

1367 if (Record.kind() == SymbolKind::S_GDATA32)

1368 Symbol->setIsExternal();

1369 }

1370

1372}

1373

1374

1378

1380 LVScope *AbstractFunction = Reader->createScopeFunction();

1381 AbstractFunction->setIsSubprogram();

1382 AbstractFunction->setTag(dwarf::DW_TAG_subprogram);

1384 AbstractFunction->setIsInlinedAbstract();

1385 InlinedFunction->setReference(AbstractFunction);

1386

1388

1391 CVFunctionType, InlineSite.Inlinee, AbstractFunction))

1392 return Err;

1394

1395

1396

1398 InlinedFunction->setName(Name);

1399 InlinedFunction->setLinkageName(Name);

1400

1401

1403 AbstractFunction, InlinedFunction, InlineSite))

1404 return Err;

1405 }

1406

1408}

1409

1410

1413 printTypeIndex("Type", Local.Type);

1416 });

1417

1419 Symbol->setName(Local.Name);

1420

1421

1422 Symbol->resetIsVariable();

1423

1424

1425 if (bool(Local.Flags & LocalSymFlags::IsCompilerGenerated) ||

1426 Local.Name == "this") {

1427 Symbol->setIsArtificial();

1428 Symbol->setIsParameter();

1429 } else {

1430 bool(Local.Flags & LocalSymFlags::IsParameter) ? Symbol->setIsParameter()

1431 : Symbol->setIsVariable();

1432 }

1433

1434

1435 if (Symbol->getIsParameter())

1436 Symbol->setTag(dwarf::DW_TAG_formal_parameter);

1437

1439 if (Element && Element->getIsScoped()) {

1440

1441 LVScope *Parent = Symbol->getFunctionParent();

1442

1443

1444

1447 }

1448 Symbol->setType(Element);

1449

1450

1451

1452

1453 LocalSymbol = Symbol;

1454 }

1455

1457}

1458

1459

1464 });

1465

1466 CurrentObjectName = ObjName.Name;

1468}

1469

1470

1472 if (InFunctionScope)

1473 return llvm::make_error("Visiting a ProcSym while inside "

1474 "function scope!");

1475

1476 InFunctionScope = true;

1477

1479 printTypeIndex("FunctionType", Proc.FunctionType);

1484 });

1485

1486

1487

1488

1489

1490

1491

1492

1493

1494

1495

1496

1497

1498

1499

1500

1501

1502

1503

1504

1505

1506

1507

1508

1509

1510

1511

1512

1513

1514

1515

1516

1517

1518

1519

1520

1523 if (ObjDelegate)

1526

1527

1531

1532 if (options().getGeneralCollectRanges()) {

1533

1538 Function->addObject(LowPC, HighPC);

1539

1540

1541 if ((options().getAttributePublics() || options().getPrintAnyLine()) &&

1542 Function->getIsInlinedFunction())

1544 }

1545

1546 if (Function->getIsSystem() && options().getAttributeSystem()) {

1547 Function->resetIncludeInPrint();

1549 }

1550

1552 if (TIFunctionType.isSimple())

1554 else {

1555

1556

1557

1558

1559

1560

1561

1565

1566 std::optional CVFunctionType;

1567 auto GetRecordType = [&]() -> bool {

1568 CVFunctionType = Ids.tryGetType(TIFunctionType);

1569 if (!CVFunctionType)

1570 return false;

1571

1573

1574 if (CVFunctionType->kind() == LF_FUNC_ID)

1575 return true;

1576

1577

1578 return (CVFunctionType->kind() == LF_MFUNC_ID);

1579 };

1580

1581

1582 if (!GetRecordType()) {

1583 CVFunctionType = Types.tryGetType(TIFunctionType);

1584 if (!CVFunctionType)

1585 return llvm::make_error("Invalid type index");

1586 }

1587

1589 *CVFunctionType, TIFunctionType, Function))

1590 return Err;

1591 }

1592

1593 if (Record.kind() == SymbolKind::S_GPROC32 ||

1594 Record.kind() == SymbolKind::S_GPROC32_ID)

1596

1597

1598

1600 if (DemangledSymbol.find("scalar deleting dtor") != std:🧵:npos) {

1601 Function->setIsArtificial();

1602 } else {

1603

1604

1605 if (DemangledSymbol.find("dynamic atexit destructor for") !=

1606 std:🧵:npos)

1607 Function->setIsArtificial();

1608 }

1609 }

1610

1612}

1613

1614

1617 InFunctionScope = false;

1619}

1620

1621

1623 if (InFunctionScope)

1624 return llvm::make_error("Visiting a Thunk32Sym while inside "

1625 "function scope!");

1626

1627 InFunctionScope = true;

1628

1632 });

1633

1636

1638}

1639

1640

1643 printTypeIndex("Type", UDT.Type);

1645 });

1646

1649 if (Type->getParentScope()->removeElement(Type))

1651 }

1652

1653 Type->setName(UDT.Name);

1654

1655

1656

1657

1658

1659

1660

1661

1663 Type->resetIncludeInPrint();

1664 else {

1666 if (UDT.Name == RecordName)

1667 Type->resetIncludeInPrint();

1669 }

1670 }

1671

1673}

1674

1675

1680}

1681

1682

1686 W.printHex("BaseOffset", JumpTable.BaseOffset);

1687 W.printNumber("BaseSegment", JumpTable.BaseSegment);

1688 W.printFlags("SwitchType", static_cast<uint16_t>(JumpTable.SwitchType),

1690 W.printHex("BranchOffset", JumpTable.BranchOffset);

1691 W.printHex("TableOffset", JumpTable.TableOffset);

1692 W.printNumber("BranchSegment", JumpTable.BranchSegment);

1693 W.printNumber("TableSegment", JumpTable.TableSegment);

1694 W.printNumber("EntriesCount", JumpTable.EntriesCount);

1695 });

1697}

1698

1699

1703 switch (Caller.getKind()) {

1704 case SymbolRecordKind::CallerSym:

1705 FieldName = "Callee";

1706 break;

1707 case SymbolRecordKind::CalleeSym:

1708 FieldName = "Caller";

1709 break;

1710 case SymbolRecordKind::InlineesSym:

1711 FieldName = "Inlinee";

1712 break;

1713 default:

1714 return llvm::make_error(

1715 "Unknown CV Record type for a CallerSym object!");

1716 }

1717 for (auto FuncID : Caller.Indices) {

1718 printTypeIndex(FieldName, FuncID);

1719 }

1720 });

1722}

1723

1724#undef DEBUG_TYPE

1725#define DEBUG_TYPE "CodeViewLogicalVisitor"

1726

1727

1728

1729

1732 : Reader(Reader), W(W), Input(Input) {

1733

1734

1735 Shared = std::make_shared(Reader, this);

1736}

1737

1741 StreamIdx == StreamTPI ? types() : ids());

1742}

1743

1754 << Element->getName() << "\n";

1755}

1756

1760}

1761

1773 << Element->getName() << "\n";

1774}

1775

1779}

1780

1785 });

1787}

1788

1789

1801 });

1802

1804 for (uint32_t Index = 0; Index < Size; ++Index) {

1805 TypeIndex ParameterType = Indices[Index];

1807 }

1808

1810}

1811

1812

1822 });

1823

1824 if (Element->getIsFinalized())

1826 Element->setIsFinalized();

1827

1829 if (!Array)

1831

1834

1835 LVType *PrevSubrange = nullptr;

1837

1838

1839

1840

1841 auto AddSubrangeType = [&](ArrayRecord &AR) {

1843 Subrange->setTag(dwarf::DW_TAG_subrange_type);

1845 Subrange->setCount(AR.getSize());

1849 : TIElementType.getIndex());

1850 Array->addElement(Subrange);

1851

1852 if (PrevSubrange)

1853 if (int64_t Count = Subrange->getCount())

1856 };

1857

1858

1859

1860

1862

1863

1864

1865

1868 while (CVEntry.kind() == LF_ARRAY) {

1869

1870

1871

1872

1873

1874

1875

1876

1877

1878

1879 AddSubrangeType(AR);

1880 TIArrayType = TIElementType;

1881

1882

1883

1884

1885 if (!TIElementType.isSimple()) {

1886 CVType CVElementType = Types.getType(TIElementType);

1887 if (CVElementType.kind() == LF_MODIFIER) {

1889 Shared->TypeRecords.find(StreamTPI, TIElementType);

1891 finishVisitation(CVElementType, TIElementType, QualifiedType))

1892 return Err;

1893

1895 }

1896 }

1897

1898 if (TIElementType.isSimple())

1899 break;

1900

1901

1902 CVEntry = Types.getType(TIElementType);

1904 const_cast<CVType &>(CVEntry), AR)) {

1906 break;

1907 }

1909

1911 }

1912

1913 Array->setName(AT.getName());

1914 TIArrayType = Shared->ForwardReferences.remap(TIArrayType);

1916

1917 if (PrevSubrange)

1918

1919

1920

1926

1928}

1929

1930

1939 });

1940

1944}

1945

1946

1956 });

1957

1958

1959

1960 TypeIndex TIName = BI.getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile];

1961 std::string Name = std::string(ids().getTypeName(TIName));

1962

1963

1964 if (Name.empty())

1966

1968}

1969

1970

1981 if (Class.hasUniqueName())

1984 });

1985

1986 if (Element->getIsFinalized())

1988 Element->setIsFinalized();

1989

1991 if (!Scope)

1993

1994 Scope->setName(Class.getName());

1995 if (Class.hasUniqueName())

1996 Scope->setLinkageName(Class.getUniqueName());

1997

1998 if (Class.isNested()) {

1999 Scope->setIsNested();

2000 createParents(Class.getName(), Scope);

2001 }

2002

2003 if (Class.isScoped())

2004 Scope->setIsScoped();

2005

2006

2007

2008 if (!(Class.isNested() || Class.isScoped())) {

2009 if (LVScope *Namespace = Shared->NamespaceDeduction.get(Class.getName()))

2011 else

2013 }

2014

2018 TypeIndex ForwardType = Shared->ForwardReferences.find(Class.getName());

2020 CVType CVReference = Types.getType(ForwardType);

2024 const_cast<CVType &>(CVReference), ReferenceRecord))

2025 return Err;

2026 TIFieldList = ReferenceRecord.getFieldList();

2027 }

2028 }

2029

2031

2032 CVType CVFieldList = Types.getType(TIFieldList);

2034 return Err;

2035 }

2036

2038}

2039

2040

2050 });

2051

2053 if (!Scope)

2055

2056 if (Scope->getIsFinalized())

2058 Scope->setIsFinalized();

2059

2060

2061

2062 Scope->setName(Enum.getName());

2063 if (Enum.hasUniqueName())

2064 Scope->setLinkageName(Enum.getUniqueName());

2065

2067

2068 if (Enum.isNested()) {

2069 Scope->setIsNested();

2070 createParents(Enum.getName(), Scope);

2071 }

2072

2073 if (Enum.isScoped()) {

2074 Scope->setIsScoped();

2075 Scope->setIsEnumClass();

2076 }

2077

2078

2079 if (!(Enum.isNested() || Enum.isScoped())) {

2080 if (LVScope *Namespace = Shared->NamespaceDeduction.get(Enum.getName()))

2082 else

2084 }

2085

2089 CVType CVFieldList = Types.getType(TIFieldList);

2091 return Err;

2092 }

2093

2095}

2096

2097

2104 });

2105

2106 if (Error Err = visitFieldListMemberStream(TI, Element, FieldList.Data))

2107 return Err;

2108

2110}

2111

2112

2115

2122 });

2123

2124

2125

2126 if (LVScope *FunctionDcl = static_cast<LVScope *>(Element)) {

2127

2128

2129

2130

2132 TypeIndex TIParent = Func.getParentScope();

2133 if (FunctionDcl->getIsInlinedAbstract()) {

2134 FunctionDcl->setName(Func.getName());

2137 }

2138

2142 return Err;

2143 }

2144

2145 TypeIndex TIFunctionType = Func.getFunctionType();

2146 CVType CVFunctionType = Types.getType(TIFunctionType);

2148 finishVisitation(CVFunctionType, TIFunctionType, FunctionDcl))

2149 return Err;

2150

2151 FunctionDcl->setIsFinalized();

2152 }

2153

2155}

2156

2157

2163 });

2165}

2166

2167

2170

2177 });

2178

2179 LVScope *FunctionDcl = static_cast<LVScope *>(Element);

2180 if (FunctionDcl->getIsInlinedAbstract()) {

2181

2182

2183

2184

2186 Shared->TypeRecords.find(StreamTPI, Id.getClassType())))

2187 Class->addElement(FunctionDcl);

2188 }

2189

2190 TypeIndex TIFunctionType = Id.getFunctionType();

2191 CVType CVFunction = types().getType(TIFunctionType);

2193 return Err;

2194

2196}

2197

2198

2211 });

2212

2213 if (LVScope *MemberFunction = static_cast<LVScope *>(Element)) {

2215

2216 MemberFunction->setIsFinalized();

2218 MemberFunction->setOffset(TI.getIndex());

2219 MemberFunction->setOffsetFromTypeIndex();

2220

2221 if (ProcessArgumentList) {

2222 ProcessArgumentList = false;

2223

2224 if (!MemberFunction->getIsStatic()) {

2226

2229 createParameter(ThisPointer, StringRef(), MemberFunction);

2230 This->setIsArtificial();

2231 }

2232

2233

2237 MemberFunction))

2238 return Err;

2239 }

2240 }

2241

2243}

2244

2245

2252 });

2253

2256 Record.Kind = LF_METHOD;

2257 Method.Name = OverloadedMethodName;

2259 return Err;

2260 }

2261

2263}

2264

2265

2272 });

2273

2274

2275

2277

2278

2279

2281

2282

2283

2284

2285 LVType *LastLink = static_cast<LVType *>(Element);

2288

2289 bool SeenModifier = false;

2291 if (Mods & uint16_t(ModifierOptions::Const)) {

2292 SeenModifier = true;

2293 LastLink->setTag(dwarf::DW_TAG_const_type);

2294 LastLink->setIsConst();

2295 LastLink->setName("const");

2296 }

2297 if (Mods & uint16_t(ModifierOptions::Volatile)) {

2298 if (SeenModifier) {

2304 }

2305 LastLink->setTag(dwarf::DW_TAG_volatile_type);

2306 LastLink->setIsVolatile();

2307 LastLink->setName("volatile");

2308 }

2309 if (Mods & uint16_t(ModifierOptions::Unaligned)) {

2310 if (SeenModifier) {

2316 }

2318 LastLink->setIsUnaligned();

2319 LastLink->setName("unaligned");

2320 }

2321

2322 LastLink->setType(ModifiedType);

2324}

2325

2326

2337 W.printNumber("IsThisPtr&", Ptr.isLValueReferenceThisPtr());

2338 W.printNumber("IsThisPtr&&", Ptr.isRValueReferenceThisPtr());

2340

2341 if (Ptr.isPointerToMember()) {

2344 }

2346 });

2347

2348

2351

2353 Pointee = Ptr.isPointerToMember()

2354 ? Shared->TypeRecords.find(StreamTPI, Ptr.getReferentType())

2356

2357

2358

2360

2361

2362

2363

2364 bool SeenModifier = false;

2368

2369 if (Ptr.isRestrict()) {

2370 SeenModifier = true;

2372 Restrict->setTag(dwarf::DW_TAG_restrict_type);

2374 Restrict->setName("restrict");

2378 }

2379 if (Mode == PointerMode::LValueReference) {

2380 if (SeenModifier) {

2381 LVType *LReference = Reader->createType();

2382 LReference->setIsModifier();

2383 LastLink->setType(LReference);

2384 LastLink = LReference;

2386 }

2387 LastLink->setTag(dwarf::DW_TAG_reference_type);

2388 LastLink->setIsReference();

2390 }

2391 if (Mode == PointerMode::RValueReference) {

2392 if (SeenModifier) {

2393 LVType *RReference = Reader->createType();

2394 RReference->setIsModifier();

2395 LastLink->setType(RReference);

2396 LastLink = RReference;

2398 }

2399 LastLink->setTag(dwarf::DW_TAG_rvalue_reference_type);

2400 LastLink->setIsRvalueReference();

2401 LastLink->setName("&&");

2402 }

2403

2404

2405 LastLink->setType(Pointee);

2407}

2408

2409

2418 });

2419

2420

2421

2422

2423 if (LVScope *FunctionDcl = static_cast<LVScope *>(Element)) {

2425

2426 if (ProcessArgumentList) {

2427 ProcessArgumentList = false;

2428

2432 FunctionDcl))

2433 return Err;

2434 }

2435 }

2436

2438}

2439

2440

2449 if (Union.hasUniqueName())

2452 });

2453

2455 if (!Scope)

2457

2458 if (Scope->getIsFinalized())

2460 Scope->setIsFinalized();

2461

2462 Scope->setName(Union.getName());

2463 if (Union.hasUniqueName())

2464 Scope->setLinkageName(Union.getUniqueName());

2465

2466 if (Union.isNested()) {

2467 Scope->setIsNested();

2468 createParents(Union.getName(), Scope);

2469 } else {

2470 if (LVScope *Namespace = Shared->NamespaceDeduction.get(Union.getName()))

2472 else

2474 }

2475

2476 if (Union.getFieldList().isNoneType()) {

2478

2481 return Err;

2482 }

2483

2485}

2486

2487

2496 });

2498}

2499

2500

2512 });

2514}

2515

2516

2524 });

2526}

2527

2528

2532

2542 });

2544}

2545

2546

2549

2554 });

2555

2556 if (LVScope *Namespace = Shared->NamespaceDeduction.get(

2557 String.getString(), false)) {

2558

2559

2561 Scope->removeElement(Element);

2563 }

2564

2566}

2567

2568

2572

2578 });

2580}

2581

2582

2586

2595 });

2597}

2598

2599

2609 });

2611}

2612

2613

2621 });

2623}

2624

2629}

2630

2631

2638 W.printHex("BaseOffset", Base.getBaseOffset());

2640 });

2641

2645 Symbol->setName(BaseClass->getName());

2647 Symbol->setAccessibilityCode(Base.getAccess());

2649 }

2650

2652}

2653

2654

2661 W.printHex("FieldOffset", Field.getFieldOffset());

2664 });

2665

2666

2667 createDataMember(Record, static_cast<LVScope *>(Element), Field.getName(),

2668 Field.getType(), Field.getAccess());

2670}

2671

2672

2681 });

2682

2685 Type->setName(Enum.getName());

2687 Enum.getValue().toString(Value, 16, true, true);

2690 }

2691

2693}

2694

2695

2703 });

2705}

2706

2707

2716 });

2717

2721 Typedef->setType(NestedType);

2723 Scope->addElement(Typedef);

2724

2725 if (NestedType && NestedType->getIsNested()) {

2726

2727

2729

2731 if (NestedTypeName.size() && RecordName.size()) {

2733 std::tie(OuterComponent, std::ignore) =

2735

2736

2737 if (OuterComponent.size() && OuterComponent == RecordName) {

2738 if (!NestedType->getIsScopedAlready()) {

2739 Scope->addElement(NestedType);

2740 NestedType->setIsScopedAlready();

2742 }

2743 Typedef->resetIncludeInPrint();

2744 }

2745 }

2746 }

2747 }

2748

2750}

2751

2752

2759

2764 });

2765

2766

2767

2768

2769 ProcessArgumentList = true;

2771 MemberFunction->setIsFinalized();

2773

2774 MemberFunction->setName(Method.getName());

2775 MemberFunction->setAccessibilityCode(Method.getAccess());

2776

2778 if (Kind == MethodKind::Static)

2779 MemberFunction->setIsStatic();

2780 MemberFunction->setVirtualityCode(Kind);

2781

2783 if (MethodOptions::CompilerGenerated ==

2784 (Flags & MethodOptions::CompilerGenerated))

2785 MemberFunction->setIsArtificial();

2786

2791 return Err;

2792 }

2793 ProcessArgumentList = false;

2794

2796}

2797

2798

2808 });

2809

2810

2811

2813 OverloadedMethodName = Method.getName();

2816 return Err;

2817

2819}

2820

2821

2830 });

2831

2832

2833 createDataMember(Record, static_cast<LVScope *>(Element), Field.getName(),

2834 Field.getType(), Field.getAccess());

2836}

2837

2838

2846 });

2848}

2849

2850

2858 W.printHex("VBPtrOffset", Base.getVBPtrOffset());

2859 W.printHex("VBTableIndex", Base.getVTableIndex());

2861 });

2862

2866 Symbol->setName(BaseClass->getName());

2868 Symbol->setAccessibilityCode(Base.getAccess());

2869 Symbol->setVirtualityCode(MethodKind::Virtual);

2871 }

2872

2874}

2875

2880 return Err;

2881

2882 switch (Record.Kind) {

2883 default:

2885 return Err;

2886 break;

2887#define MEMBER_RECORD(EnumName, EnumVal, Name) \

2888 case EnumName: { \

2889 if (Error Err = \

2890 visitKnownMember<Name##Record>(Record, Callbacks, TI, Element)) \

2891 return Err; \

2892 break; \

2893 }

2894#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \

2895 MEMBER_RECORD(EnumVal, EnumVal, AliasName)

2896#define TYPE_RECORD(EnumName, EnumVal, Name)

2897#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)

2898#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"

2899 }

2900

2902 return Err;

2903

2905}

2906

2909 switch (Record.kind()) {

2910 default:

2912 return Err;

2913 break;

2914#define TYPE_RECORD(EnumName, EnumVal, Name) \

2915 case EnumName: { \

2916 if (Error Err = visitKnownRecord<Name##Record>(Record, TI, Element)) \

2917 return Err; \

2918 break; \

2919 }

2920#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \

2921 TYPE_RECORD(EnumVal, EnumVal, AliasName)

2922#define MEMBER_RECORD(EnumName, EnumVal, Name)

2923#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)

2924#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"

2925 }

2926

2928}

2929

2930

2931Error LVLogicalVisitor::visitFieldListMemberStream(

2938

2940 while (!Reader.empty()) {

2941 if (Error Err = Reader.readEnum(Leaf))

2942 return Err;

2943

2947 return Err;

2948 }

2949

2951}

2952

2954

2955

2956

2957

2959 if (!ScopeStack.empty())

2961 InCompileUnitScope = true;

2962 }

2963

2966}

2967

2970}

2971

2974}

2975

2980

2985 if (options().getAttributeBase())

2988 }

2989

2990 switch (Kind) {

2991

2992 case TypeLeafKind::LF_ENUMERATE:

2993 CurrentType = Reader->createTypeEnumerator();

2996 case TypeLeafKind::LF_MODIFIER:

3000 case TypeLeafKind::LF_POINTER:

3006

3007

3008 case TypeLeafKind::LF_BCLASS:

3009 case TypeLeafKind::LF_IVBCLASS:

3010 case TypeLeafKind::LF_VBCLASS:

3015 case TypeLeafKind::LF_MEMBER:

3016 case TypeLeafKind::LF_STMEMBER:

3021

3022

3023 case TypeLeafKind::LF_ARRAY:

3027 case TypeLeafKind::LF_CLASS:

3028 CurrentScope = Reader->createScopeAggregate();

3032 case TypeLeafKind::LF_ENUM:

3033 CurrentScope = Reader->createScopeEnumeration();

3036 case TypeLeafKind::LF_METHOD:

3037 case TypeLeafKind::LF_ONEMETHOD:

3038 case TypeLeafKind::LF_PROCEDURE:

3039 CurrentScope = Reader->createScopeFunction();

3043 case TypeLeafKind::LF_STRUCTURE:

3044 CurrentScope = Reader->createScopeAggregate();

3048 case TypeLeafKind::LF_UNION:

3049 CurrentScope = Reader->createScopeAggregate();

3053 default:

3054

3055

3056 break;

3057 }

3058 return nullptr;

3059}

3060

3065 switch (Kind) {

3066

3067 case SymbolKind::S_UDT:

3068 CurrentType = Reader->createTypeDefinition();

3071

3072

3073 case SymbolKind::S_CONSTANT:

3078

3079 case SymbolKind::S_BPREL32:

3080 case SymbolKind::S_REGREL32:

3081 case SymbolKind::S_GDATA32:

3082 case SymbolKind::S_LDATA32:

3083 case SymbolKind::S_LOCAL:

3084

3085

3086

3091

3092

3093 case SymbolKind::S_BLOCK32:

3098 case SymbolKind::S_COMPILE2:

3099 case SymbolKind::S_COMPILE3:

3100 CurrentScope = Reader->createScopeCompileUnit();

3104 case SymbolKind::S_INLINESITE:

3105 case SymbolKind::S_INLINESITE2:

3106 CurrentScope = Reader->createScopeFunctionInlined();

3110 case SymbolKind::S_LPROC32:

3111 case SymbolKind::S_GPROC32:

3112 case SymbolKind::S_LPROC32_ID:

3113 case SymbolKind::S_GPROC32_ID:

3114 case SymbolKind::S_SEPCODE:

3115 case SymbolKind::S_THUNK32:

3116 CurrentScope = Reader->createScopeFunction();

3120 default:

3121

3122

3123 break;

3124 }

3125 return nullptr;

3126}

3127

3130 if (!Element) {

3131

3132

3135 Element->setIsFinalized();

3138 return Element;

3139 }

3140

3143 Shared->TypeRecords.add(StreamTPI, TI, Kind, Element);

3145 Element->setOffsetFromTypeIndex();

3146 return Element;

3147 }

3148

3149 W.printString("** Not implemented. **");

3152 return nullptr;

3153 }

3154

3156 Element->setOffsetFromTypeIndex();

3157 return Element;

3158}

3159

3166 });

3167

3170 Symbol->setName(Name);

3173 else {

3175 CVType CVMemberType = Types.getType(TI);

3176 if (CVMemberType.kind() == LF_BITFIELD) {

3179 return;

3180 }

3181 } else

3183 }

3186 }

3187}

3188

3191 LVSymbol *Parameter = Reader->createSymbol();

3193 Parameter->setIsParameter();

3194 Parameter->setTag(dwarf::DW_TAG_formal_parameter);

3196 Parameter->setType(Element);

3197 return Parameter;

3198}

3199

3203}

3204

3211 });

3212

3214 return static_cast<LVType *>(Element);

3215

3219 }

3221}

3222

3227 });

3228

3230 return static_cast<LVType *>(Element);

3231

3232 LVType *Pointee = createBaseType(TI, TypeName.drop_back(1));

3233 if (createElement(TI, TypeLeafKind::LF_POINTER)) {

3237 }

3239}

3240

3241void LVLogicalVisitor::createParents(StringRef ScopedName, LVElement *Element) {

3242

3243

3244

3245

3246

3247

3248

3249

3250

3251

3252

3253

3254

3255

3256

3257

3258

3259

3261 if (Components.size() < 2)

3262 return;

3263 Components.pop_back();

3264

3265 LVStringRefs::size_type FirstNamespace;

3266 LVStringRefs::size_type FirstAggregate;

3267 std::tie(FirstNamespace, FirstAggregate) =

3268 Shared->NamespaceDeduction.find(Components);

3269

3271 W.printString("First Namespace", Components[FirstNamespace]);

3272 W.printString("First NonNamespace", Components[FirstAggregate]);

3273 });

3274

3275

3276 if (FirstNamespace < FirstAggregate) {

3277 Shared->NamespaceDeduction.get(

3278 LVStringRefs(Components.begin() + FirstNamespace,

3279 Components.begin() + FirstAggregate));

3280 }

3281

3282

3283

3284

3285 LVScope *Aggregate = nullptr;

3288 LVStringRefs(Components.begin(), Components.begin() + FirstAggregate));

3289

3290

3291 for (LVStringRefs::size_type Index = FirstAggregate;

3292 Index < Components.size(); ++Index) {

3294 Components.begin() + Index + 1),

3295 AggregateName);

3296 TIAggregate = Shared->ForwardReferences.remap(

3297 Shared->TypeRecords.find(StreamTPI, AggregateName));

3298 Aggregate =

3300 ? nullptr

3302 }

3303

3304

3305

3306

3307 if (Aggregate && !Element->getIsScopedAlready()) {

3309 Element->setIsScopedAlready();

3310 }

3311}

3312

3316 TI = Shared->ForwardReferences.remap(TI);

3318

3319 LVElement *Element = Shared->TypeRecords.find(StreamIdx, TI);

3320 if (!Element) {

3323

3324

3325

3326

3327 return (TypeName.back() == '*') ? createPointerType(TI, TypeName)

3328 : createBaseType(TI, TypeName);

3329 }

3330

3332 return nullptr;

3333 }

3334

3335

3336 if (Element->getIsFinalized())

3337 return Element;

3338

3339

3340 if (Parent)

3342

3343

3348 return nullptr;

3349 }

3350 Element->setIsFinalized();

3351 return Element;

3352}

3353

3355

3356

3357 for (const TypeIndex &Entry : Shared->LineRecords) {

3363 else {

3368 });

3369

3370

3371

3372

3373 if (LVElement *Element = Shared->TypeRecords.find(

3377 Shared->StringRecords.findIndex(Line.getSourceFile()));

3378 }

3379 }

3380 }

3381}

3382

3384

3385 Shared->NamespaceDeduction.init();

3386}

3387

3389

3391 if (options().getInternalTag())

3392 return;

3393

3394 unsigned Count = 0;

3396 auto NewLine = [&]() {

3397 if (++Count == 4) {

3398 Count = 0;

3399 OS << "\n";

3400 }

3401 };

3403 NewLine();

3404 };

3405

3406 OS << "\nTypes:\n";

3409 Shared->TypeKinds.clear();

3410

3411 Count = 0;

3412 OS << "\nSymbols:\n";

3415 Shared->SymbolKinds.clear();

3416

3417 OS << "\n";

3418}

3419

3421 LVScope *InlinedFunction,

3423

3424

3429 ParentLowPC = (*Locations->begin())->getLowerAddress();

3430 }

3431

3432

3433

3436 LVInlineeInfo::iterator Iter = InlineeInfo.find(InlineSite.Inlinee);

3437 if (Iter != InlineeInfo.end()) {

3438 LineNumber = Iter->second.first;

3439 Filename = Iter->second.second;

3441

3442

3443

3444 }

3445

3447 dbgs() << "inlineSiteAnnotation\n"

3448 << "Abstract: " << AbstractFunction->getName() << "\n"

3449 << "Inlined: " << InlinedFunction->getName() << "\n"

3450 << "Parent: " << Parent->getName() << "\n"

3451 << "Low PC: " << hexValue(ParentLowPC) << "\n";

3452 });

3453

3454

3455 if (options().getPrintLines())

3457

3458

3459

3460

3462 int32_t LineOffset = LineNumber;

3464

3465 auto UpdateClose = [&]() { LLVM_DEBUG({ dbgs() << ("\n"); }); };

3466 auto UpdateCodeOffset = [&](uint32_t Delta) {

3470 utohexstr(Delta));

3471 });

3472 };

3473 auto UpdateLineOffset = [&](int32_t Delta) {

3474 LineOffset += Delta;

3476 char Sign = Delta > 0 ? '+' : '-';

3477 dbgs() << formatv(" line {0} ({1}{2})", LineOffset, Sign,

3478 std::abs(Delta));

3479 });

3480 };

3481 auto UpdateFileOffset = [&](int32_t Offset) {

3482 FileOffset = Offset;

3484 };

3485

3487 auto CreateLine = [&]() {

3488

3491 Line->setLineNumber(LineOffset);

3492

3493

3494

3496 };

3497

3498 bool SeenLowAddress = false;

3499 bool SeenHighAddress = false;

3502

3503 for (auto &Annot : InlineSite.annotations()) {

3507 });

3508

3509

3510 switch (Annot.OpCode) {

3511 case BinaryAnnotationsOpCode::ChangeCodeOffset:

3512 case BinaryAnnotationsOpCode::CodeOffset:

3513 case BinaryAnnotationsOpCode::ChangeCodeLength:

3514 UpdateCodeOffset(Annot.U1);

3515 UpdateClose();

3516 if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeOffset) {

3517 CreateLine();

3519 SeenLowAddress = true;

3520 break;

3521 }

3522 if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeLength) {

3524 SeenHighAddress = true;

3525 }

3526 break;

3527 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:

3528 UpdateCodeOffset(Annot.U2);

3529 UpdateClose();

3530 break;

3531 case BinaryAnnotationsOpCode::ChangeLineOffset:

3532 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:

3533 UpdateCodeOffset(Annot.U1);

3534 UpdateLineOffset(Annot.S1);

3535 UpdateClose();

3536 if (Annot.OpCode ==

3537 BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset)

3538 CreateLine();

3539 break;

3540 case BinaryAnnotationsOpCode::ChangeFile:

3541 UpdateFileOffset(Annot.U1);

3542 UpdateClose();

3543 break;

3544 default:

3545 break;

3546 }

3547 if (SeenLowAddress && SeenHighAddress) {

3548 SeenLowAddress = false;

3549 SeenHighAddress = false;

3550 InlinedFunction->addObject(LowPC, HighPC);

3551 }

3552 }

3553

3555 UpdateClose();

3556

3558}

for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))

AMDGPU Lower Kernel Arguments

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

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

size_t size() const

size - Get the array size.

An implementation of BinaryStream which holds its entire data set in a single contiguous buffer.

Provides read only access to a subclass of BinaryStream.

This is an important base class in LLVM.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

StringRef getName() const

virtual void printString(StringRef Value)

void indent(int Levels=1)

void unindent(int Levels=1)

void printEnum(StringRef Label, T Value, ArrayRef< EnumEntry< TEnum > > EnumValues)

virtual raw_ostream & getOStream()

virtual raw_ostream & startLine()

virtual void printNumber(StringRef Label, char Value)

void printHex(StringRef Label, T Value)

void printFlags(StringRef Label, T Value, ArrayRef< EnumEntry< TFlag > > Flags, TFlag EnumMask1={}, TFlag EnumMask2={}, TFlag EnumMask3={}, ArrayRef< FlagEntry > ExtraFlags={})

virtual void printBoolean(StringRef Label, bool Value)

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.

StringMapEntry - This is used to represent one value that is inserted into a StringMap.

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

std::string str() const

str - Get the contents as an std::string.

constexpr size_t size() const

size - Get the string size.

Target - Wrapper for Target specific information.

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM Value Representation.

Value(Type *Ty, unsigned scid)

void setName(const Twine &Name)

Change the name of the value.

TypeIndex getElementType() const

TypeIndex getIndexType() const

StringRef getName() const

uint8_t getBitSize() const

TypeIndex getType() const

uint8_t getBitOffset() const

ArrayRef< TypeIndex > getArgs() const

uint8_t getLanguage() const

uint32_t getFlags() const

CompileSym3Flags getFlags() const

SourceLanguage getLanguage() const

Represents a read-only view of a CodeView string table.

DefRangeFramePointerRelHeader Hdr

LocalVariableAddrRange Range

uint32_t getRelocationOffset() const

std::vector< LocalVariableAddrGap > Gaps

DefRangeRegisterRelHeader Hdr

bool hasSpilledUDTMember() const

uint32_t getRelocationOffset() const

uint16_t offsetInParent() const

std::vector< LocalVariableAddrGap > Gaps

LocalVariableAddrRange Range

uint32_t getRelocationOffset() const

std::vector< LocalVariableAddrGap > Gaps

LocalVariableAddrRange Range

DefRangeRegisterHeader Hdr

LocalVariableAddrRange Range

uint32_t getRelocationOffset() const

std::vector< LocalVariableAddrGap > Gaps

DefRangeSubfieldRegisterHeader Hdr

std::vector< LocalVariableAddrGap > Gaps

LocalVariableAddrRange Range

uint32_t getRelocationOffset() const

std::vector< LocalVariableAddrGap > Gaps

uint32_t getRelocationOffset() const

LocalVariableAddrRange Range

uint32_t getSignature() const

RegisterId getLocalFramePtrReg(CPUType CPU) const

Extract the register this frame uses to refer to local variables.

RegisterId getParamFramePtrReg(CPUType CPU) const

Extract the register this frame uses to refer to parameters.

FrameProcedureOptions Flags

Provides amortized O(1) random access to a CodeView type stream.

std::optional< CVType > tryGetType(TypeIndex Index)

CVType getType(TypeIndex Index) override

StringRef getTypeName(TypeIndex Index) override

LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.

TypeIndex getContinuationIndex() const

TypeIndex getReturnType() const

int32_t getThisPointerAdjustment() const

TypeIndex getArgumentList() const

uint16_t getParameterCount() const

TypeIndex getThisType() const

TypeIndex getClassType() const

std::vector< OneMethodRecord > Methods

int32_t getVFTableOffset() const

TypeIndex getType() const

bool isIntroducingVirtual() const

MemberAccess getAccess() const

MethodKind getMethodKind() const

StringRef getName() const

For method overload sets. LF_METHOD.

StringRef getName() const

uint16_t getNumOverloads() const

TypeIndex getMethodList() const

uint32_t getSignature() const

StringRef getPrecompFilePath() const

uint32_t getTypesCount() const

uint32_t getStartTypeIndex() const

uint32_t getRelocationOffset() const

TypeIndex getReturnType() const

TypeIndex getArgumentList() const

uint16_t getParameterCount() const

TypeIndex getFieldList() const

static Error deserializeAs(CVType &CVT, T &Record)

static TypeIndex fromArrayIndex(uint32_t Index)

SimpleTypeKind getSimpleKind() const

void setIndex(uint32_t I)

static const uint32_t FirstNonSimpleIndex

static StringRef simpleTypeName(TypeIndex TI)

uint32_t getIndex() const

StringRef getName() const

const GUID & getGuid() const

void addCallbackToPipeline(TypeVisitorCallbacks &Callbacks)

virtual Error visitUnknownMember(CVMemberRecord &Record)

virtual Error visitMemberEnd(CVMemberRecord &Record)

virtual Error visitMemberBegin(CVMemberRecord &Record)

TypeIndex getSourceFile() const

uint16_t getModule() const

uint32_t getLineNumber() const

uint32_t getLineNumber() const

TypeIndex getSourceFile() const

TypeIndex getType() const

uint32_t getVFPtrOffset() const

TypeIndex getOverriddenVTable() const

ArrayRef< StringRef > getMethodNames() const

StringRef getName() const

TypeIndex getCompleteClass() const

uint32_t getEntryCount() const

Stores all information relating to a compile unit, be it in its original instance in the object file ...

void addInlineeLines(LVScope *Scope, LVLines &Lines)

LVAddress getSymbolTableAddress(StringRef Name)

LVAddress linearAddress(uint16_t Segment, uint32_t Offset, LVAddress Addendum=0)

void addToSymbolTable(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex=0)

void addModule(LVScope *Scope)

void getLinkageName(const llvm::object::coff_section *CoffSection, uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym)

static StringRef getSymbolKindName(SymbolKind Kind)

virtual void setCount(int64_t Value)

virtual void setBitSize(uint32_t Size)

virtual void updateLevel(LVScope *Parent, bool Moved=false)

virtual int64_t getCount() const

void setInlineCode(uint32_t Code)

virtual void setReference(LVElement *Element)

void setName(StringRef ElementName) override

StringRef getName() const override

void setType(LVElement *Element=nullptr)

void setFilenameIndex(size_t Index)

Error visitKnownRecord(CVType &Record, ArgListRecord &Args, TypeIndex TI, LVElement *Element)

void printRecords(raw_ostream &OS) const

void stopProcessArgumentList()

void printTypeEnd(CVType &Record)

Error visitMemberRecord(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks, TypeIndex TI, LVElement *Element)

Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base, TypeIndex TI, LVElement *Element)

void printMemberEnd(CVMemberRecord &Record)

void setCompileUnitName(std::string Name)

LVElement * CurrentElement

Error inlineSiteAnnotation(LVScope *AbstractFunction, LVScope *InlinedFunction, InlineSiteSym &InlineSite)

LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W, llvm::pdb::InputFile &Input)

void printTypeIndex(StringRef FieldName, TypeIndex TI, uint32_t StreamIdx)

Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI)

void pushScope(LVScope *Scope)

Error visitUnknownType(CVType &Record, TypeIndex TI)

void startProcessArgumentList()

void addElement(LVScope *Scope, bool IsCompileUnit)

void printTypeBegin(CVType &Record, TypeIndex TI, LVElement *Element, uint32_t StreamIdx)

LVElement * getElement(uint32_t StreamIdx, TypeIndex TI, LVScope *Parent=nullptr)

LVScope * getReaderScope() const

void printMemberBegin(CVMemberRecord &Record, TypeIndex TI, LVElement *Element, uint32_t StreamIdx)

Error finishVisitation(CVType &Record, TypeIndex TI, LVElement *Element)

LVElement * createElement(TypeLeafKind Kind)

LVScope * getParentScope() const

void setOffset(LVOffset DieOffset)

LVOffset getOffset() const

void setLineNumber(uint32_t Number)

void setTag(dwarf::Tag Tag)

codeview::CPUType getCompileUnitCPUType()

void setCompileUnitCPUType(codeview::CPUType Type)

virtual bool isSystemEntry(LVElement *Element, StringRef Name={}) const

LVScopeCompileUnit * getCompileUnit() const

void setCompileUnit(LVScope *Scope)

void addPublicName(LVScope *Scope, LVAddress LowPC, LVAddress HighPC)

void addElement(LVElement *Element)

void addObject(LVLocation *Location)

const LVLocations * getRanges() const

void getLinkageName(uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym=nullptr)

void printRelocatedField(StringRef Label, uint32_t RelocOffset, uint32_t Offset, StringRef *RelocSym=nullptr)

DebugStringTableSubsectionRef getStringTable() override

StringRef getFileNameForFileOffset(uint32_t FileOffset) override

Error visitSymbolEnd(CVSymbol &Record) override

Error visitKnownRecord(CVSymbol &Record, BlockSym &Block) override

Error visitSymbolBegin(CVSymbol &Record) override

Error visitUnknownSymbol(CVSymbol &Record) override

Action to take on unknown symbols. By default, they are ignored.

Error visitMemberEnd(CVMemberRecord &Record) override

Error visitUnknownMember(CVMemberRecord &Record) override

Error visitTypeBegin(CVType &Record) override

Paired begin/end actions for all types.

Error visitMemberBegin(CVMemberRecord &Record) override

Error visitKnownRecord(CVType &Record, BuildInfoRecord &Args) override

Error visitUnknownType(CVType &Record) override

Action to take on unknown types. By default, they are ignored.

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

constexpr char TypeName[]

Key for Kernel::Arg::Metadata::mTypeName.

PointerMode

Equivalent to CV_ptrmode_e.

MethodKind

Part of member attribute flags. (CV_methodprop_e)

CPUType

These values correspond to the CV_CPU_TYPE_e enumeration, and are documented here: https://msdn....

ArrayRef< EnumEntry< uint16_t > > getJumpTableEntrySizeNames()

bool symbolEndsScope(SymbolKind Kind)

Return true if this ssymbol ends a scope.

MethodOptions

Equivalent to CV_fldattr_t bitfield.

ArrayRef< EnumEntry< SymbolKind > > getSymbolTypeNames()

MemberAccess

Source-level access specifier. (CV_access_e)

bool symbolOpensScope(SymbolKind Kind)

Return true if this symbol opens a scope.

TypeLeafKind

Duplicate copy of the above enum, but using the official CV names.

ArrayRef< EnumEntry< uint16_t > > getLocalFlagNames()

ArrayRef< EnumEntry< uint16_t > > getRegisterNames(CPUType Cpu)

bool isAggregate(CVType CVT)

Given an arbitrary codeview type, determine if it is an LF_STRUCTURE, LF_CLASS, LF_INTERFACE,...

ArrayRef< EnumEntry< uint8_t > > getProcSymFlagNames()

TypeRecordKind

Distinguishes individual records in .debug$T or .debug$P section or PDB type stream.

SymbolKind

Duplicate copy of the above enum, but using the official CV names.

uint64_t getSizeInBytesForTypeRecord(CVType CVT)

Given an arbitrary codeview type, return the type's size in the case of aggregate (LF_STRUCTURE,...

ArrayRef< EnumEntry< unsigned > > getCPUTypeNames()

ArrayRef< EnumEntry< SourceLanguage > > getSourceLanguageNames()

uint64_t getSizeInBytesForTypeIndex(TypeIndex TI)

Given an arbitrary codeview type index, determine its size.

TypeIndex getModifiedType(const CVType &CVT)

Given a CVType which is assumed to be an LF_MODIFIER, return the TypeIndex of the type that the LF_MO...

ArrayRef< EnumEntry< uint32_t > > getCompileSym3FlagNames()

void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI, TypeCollection &Types)

@ DW_INL_declared_inlined

constexpr Tag DW_TAG_unaligned

Scope

Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...

FormattedNumber hexValue(uint64_t N, unsigned Width=HEX_WIDTH, bool Upper=false)

static TypeIndex getTrueType(TypeIndex &TI)

std::vector< StringRef > LVStringRefs

static StringRef getRecordName(LazyRandomTypeCollection &Types, TypeIndex TI)

std::vector< TypeIndex > LVLineRecords

LVStringRefs getAllLexicalComponents(StringRef Name)

std::string transformPath(StringRef Path)

LVLexicalComponent getInnerComponent(StringRef Name)

static const EnumEntry< TypeLeafKind > LeafTypeNames[]

std::set< SymbolKind > LVSymbolKinds

std::set< TypeLeafKind > LVTypeKinds

std::string getScopedName(const LVStringRefs &Components, StringRef BaseName={})

std::tuple< LVStringRefs::size_type, LVStringRefs::size_type > LVLexicalIndex

std::string formatTypeLeafKind(codeview::TypeLeafKind K)

Print(const T &, const DataFlowGraph &) -> Print< T >

This is an optimization pass for GlobalISel generic memory operations.

auto find(R &&Range, const T &Val)

Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.

std::tuple< uint64_t, uint32_t > InlineSite

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

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

These are helper functions used to produce formatted output.

StringRef getTypeName()

We provide a function which tries to compute the (demangled) name of a type statically.

@ Mod

The access may modify the value stored in memory.

support::detail::RepeatAdapter< T > fmt_repeat(T &&Item, size_t Count)

support::detail::AlignAdapter< T > fmt_align(T &&Item, AlignStyle Where, size_t Amount, char Fill=' ')

void erase_if(Container &C, UnaryPredicate P)

Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...

void consumeError(Error Err)

Consume a Error without doing anything.

std::string demangle(std::string_view MangledName)

Attempt to demangle a string using different demangling schemes.

MethodOptions getFlags() const

Get the flags that are not included in access control or method properties.