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 ->getIsInlinedFunction())
1544 }
1545
1546 if (Function->getIsSystem() && ().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
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 (.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 (.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 (().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 (().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.