1//===-- LVScope.h -----------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the LVScope class, which is used to describe a debug
10// information scope.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
15#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
16
17#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
18#include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
19#include "llvm/DebugInfo/LogicalView/Core/LVSort.h"
20#include "llvm/Object/ObjectFile.h"
21#include <list>
22#include <map>
23#include <set>
24
25namespace llvm {
26namespace logicalview {
27
28// Name address, Code size.
29using LVNameInfo = std::pair<LVAddress, uint64_t>;
30using LVPublicNames = std::map<LVScope *, LVNameInfo>;
31using LVPublicAddresses = std::map<LVAddress, LVNameInfo>;
32
33class LVRange;
34
35enum class LVScopeKind {
36 IsAggregate,
37 IsArray,
38 IsBlock,
39 IsCallSite,
40 IsCatchBlock,
41 IsClass,
42 IsCompileUnit,
43 IsEntryPoint,
44 IsEnumeration,
45 IsFunction,
46 IsFunctionType,
47 IsInlinedFunction,
48 IsLabel,
49 IsLexicalBlock,
50 IsMember,
51 IsNamespace,
52 IsRoot,
53 IsStructure,
54 IsSubprogram,
55 IsTemplate,
56 IsTemplateAlias,
57 IsTemplatePack,
58 IsTryBlock,
59 IsUnion,
60 LastEntry
61};
62using LVScopeKindSet = std::set<LVScopeKind>;
63using LVScopeDispatch = std::map<LVScopeKind, LVScopeGetFunction>;
64using LVScopeRequest = std::vector<LVScopeGetFunction>;
65
66using LVOffsetElementMap = std::map<LVOffset, LVElement *>;
67using LVOffsetLinesMap = std::map<LVOffset, LVLines>;
68using LVOffsetLocationsMap = std::map<LVOffset, LVLocations>;
69using LVOffsetSymbolMap = std::map<LVOffset, LVSymbol *>;
70using LVTagOffsetsMap = std::map<dwarf::Tag, LVOffsets>;
71
72// Class to represent a DWARF Scope.
73class LVScope : public LVElement {
74 enum class Property {
75 HasDiscriminator,
76 CanHaveRanges,
77 CanHaveLines,
78 HasGlobals,
79 HasLocals,
80 HasLines,
81 HasScopes,
82 HasSymbols,
83 HasTypes,
84 IsComdat,
85 HasComdatScopes, // Compile Unit has comdat functions.
86 HasRanges,
87 AddedMissing, // Added missing referenced symbols.
88 LastEntry
89 };
90
91 // Typed bitvector with kinds and properties for this scope.
92 LVProperties<LVScopeKind> Kinds;
93 LVProperties<Property> Properties;
94 static LVScopeDispatch Dispatch;
95
96 // Coverage factor in units (bytes).
97 unsigned CoverageFactor = 0;
98
99 // Calculate coverage factor.
100 void calculateCoverage() {
101 float CoveragePercentage = 0;
102 LVLocation::calculateCoverage(Locations: Ranges.get(), Factor&: CoverageFactor,
103 Percentage&: CoveragePercentage);
104 }
105
106 // Decide if the scope will be printed, using some conditions given by:
107 // only-globals, only-locals, a-pattern.
108 bool resolvePrinting() const;
109
110 // Find the current scope in the given 'Targets'.
111 LVScope *findIn(const LVScopes *Targets) const;
112
113 // Traverse the scope parent tree, executing the given callback function
114 // on each scope.
115 void traverseParents(LVScopeGetFunction GetFunction,
116 LVScopeSetFunction SetFunction);
117
118protected:
119 // Types, Symbols, Scopes, Lines, Locations in this scope.
120 std::unique_ptr<LVTypes> Types;
121 std::unique_ptr<LVSymbols> Symbols;
122 std::unique_ptr<LVScopes> Scopes;
123 std::unique_ptr<LVLines> Lines;
124 std::unique_ptr<LVLocations> Ranges;
125
126 // Vector of elements (types, scopes and symbols).
127 // It is the union of (*Types, *Symbols and *Scopes) to be used for
128 // the following reasons:
129 // - Preserve the order the logical elements are read in.
130 // - To have a single container with all the logical elements, when
131 // the traversal does not require any specific element kind.
132 std::unique_ptr<LVElements> Children;
133
134 // Resolve the template parameters/arguments relationship.
135 void resolveTemplate();
136 void printEncodedArgs(raw_ostream &OS, bool Full) const;
137
138 void printActiveRanges(raw_ostream &OS, bool Full = true) const;
139 virtual void printSizes(raw_ostream &OS) const {}
140 virtual void printSummary(raw_ostream &OS) const {}
141
142 // Encoded template arguments.
143 virtual StringRef getEncodedArgs() const { return StringRef(); }
144 virtual void setEncodedArgs(StringRef EncodedArgs) {}
145
146public:
147 LVScope() : LVElement(LVSubclassID::LV_SCOPE) {
148 setIsScope();
149 setIncludeInPrint();
150 }
151 LVScope(const LVScope &) = delete;
152 LVScope &operator=(const LVScope &) = delete;
153 virtual ~LVScope() = default;
154
155 static bool classof(const LVElement *Element) {
156 return Element->getSubclassID() == LVSubclassID::LV_SCOPE;
157 }
158
159 KIND(LVScopeKind, IsAggregate);
160 KIND(LVScopeKind, IsArray);
161 KIND_2(LVScopeKind, IsBlock, CanHaveRanges, CanHaveLines);
162 KIND_1(LVScopeKind, IsCallSite, IsFunction);
163 KIND_1(LVScopeKind, IsCatchBlock, IsBlock);
164 KIND_1(LVScopeKind, IsClass, IsAggregate);
165 KIND_3(LVScopeKind, IsCompileUnit, CanHaveRanges, CanHaveLines,
166 TransformName);
167 KIND_1(LVScopeKind, IsEntryPoint, IsFunction);
168 KIND(LVScopeKind, IsEnumeration);
169 KIND_2(LVScopeKind, IsFunction, CanHaveRanges, CanHaveLines);
170 KIND_1(LVScopeKind, IsFunctionType, IsFunction);
171 KIND_2(LVScopeKind, IsInlinedFunction, IsFunction, IsInlined);
172 KIND_1(LVScopeKind, IsLabel, IsFunction);
173 KIND_1(LVScopeKind, IsLexicalBlock, IsBlock);
174 KIND(LVScopeKind, IsMember);
175 KIND(LVScopeKind, IsNamespace);
176 KIND_1(LVScopeKind, IsRoot, TransformName);
177 KIND_1(LVScopeKind, IsStructure, IsAggregate);
178 KIND_1(LVScopeKind, IsSubprogram, IsFunction);
179 KIND(LVScopeKind, IsTemplate);
180 KIND(LVScopeKind, IsTemplateAlias);
181 KIND(LVScopeKind, IsTemplatePack);
182 KIND_1(LVScopeKind, IsTryBlock, IsBlock);
183 KIND_1(LVScopeKind, IsUnion, IsAggregate);
184
185 PROPERTY(Property, HasDiscriminator);
186 PROPERTY(Property, CanHaveRanges);
187 PROPERTY(Property, CanHaveLines);
188 PROPERTY(Property, HasGlobals);
189 PROPERTY(Property, HasLocals);
190 PROPERTY(Property, HasLines);
191 PROPERTY(Property, HasScopes);
192 PROPERTY(Property, HasSymbols);
193 PROPERTY(Property, HasTypes);
194 PROPERTY(Property, IsComdat);
195 PROPERTY(Property, HasComdatScopes);
196 PROPERTY(Property, HasRanges);
197 PROPERTY(Property, AddedMissing);
198
199 bool isCompileUnit() const override { return getIsCompileUnit(); }
200 bool isRoot() const override { return getIsRoot(); }
201
202 const char *kind() const override;
203
204 // Get the specific children.
205 const LVLines *getLines() const { return Lines.get(); }
206 const LVLocations *getRanges() const { return Ranges.get(); }
207 const LVScopes *getScopes() const { return Scopes.get(); }
208 const LVSymbols *getSymbols() const { return Symbols.get(); }
209 const LVTypes *getTypes() const { return Types.get(); }
210 const LVElements *getChildren() const { return Children.get(); }
211
212 void addElement(LVElement *Element);
213 void addElement(LVLine *Line);
214 void addElement(LVScope *Scope);
215 void addElement(LVSymbol *Symbol);
216 void addElement(LVType *Type);
217 void addObject(LVLocation *Location);
218 void addObject(LVAddress LowerAddress, LVAddress UpperAddress);
219 void addToChildren(LVElement *Element);
220
221 // Add the missing elements from the given 'Reference', which is the
222 // scope associated with any DW_AT_specification, DW_AT_abstract_origin.
223 void addMissingElements(LVScope *Reference);
224
225 // Traverse the scope parent tree and the children, executing the given
226 // callback function on each element.
227 void traverseParentsAndChildren(LVObjectGetFunction GetFunction,
228 LVObjectSetFunction SetFunction);
229
230 // Get the size of specific children.
231 size_t lineCount() const { return Lines ? Lines->size() : 0; }
232 size_t rangeCount() const { return Ranges ? Ranges->size() : 0; }
233 size_t scopeCount() const { return Scopes ? Scopes->size() : 0; }
234 size_t symbolCount() const { return Symbols ? Symbols->size() : 0; }
235 size_t typeCount() const { return Types ? Types->size() : 0; }
236
237 // Find containing parent for the given address.
238 LVScope *outermostParent(LVAddress Address);
239
240 // Get all the locations associated with symbols.
241 void getLocations(LVLocations &LocationList, LVValidLocation ValidLocation,
242 bool RecordInvalid = false);
243 void getRanges(LVLocations &LocationList, LVValidLocation ValidLocation,
244 bool RecordInvalid = false);
245 void getRanges(LVRange &RangeList);
246
247 unsigned getCoverageFactor() const { return CoverageFactor; }
248
249 Error doPrint(bool Split, bool Match, bool Print, raw_ostream &OS,
250 bool Full = true) const override;
251 // Sort the logical elements using the criteria specified by the
252 // command line option '--output-sort'.
253 void sort();
254
255 // Get template parameter types.
256 bool getTemplateParameterTypes(LVTypes &Params);
257
258 // DW_AT_specification, DW_AT_abstract_origin, DW_AT_extension.
259 virtual LVScope *getReference() const { return nullptr; }
260
261 LVScope *getCompileUnitParent() const override {
262 return LVElement::getCompileUnitParent();
263 }
264
265 // Follow a chain of references given by DW_AT_abstract_origin and/or
266 // DW_AT_specification and update the scope name.
267 StringRef resolveReferencesChain();
268
269 bool removeElement(LVElement *Element) override;
270 void updateLevel(LVScope *Parent, bool Moved) override;
271
272 void resolve() override;
273 void resolveName() override;
274 void resolveReferences() override;
275
276 // Return the chain of parents as a string.
277 void getQualifiedName(std::string &QualifiedName) const;
278 // Encode the template arguments.
279 void encodeTemplateArguments(std::string &Name) const;
280 void encodeTemplateArguments(std::string &Name, const LVTypes *Types) const;
281
282 void resolveElements();
283
284 // Iterate through the 'References' set and check that all its elements
285 // are present in the 'Targets' set. For a missing element, mark its
286 // parents as missing.
287 static void markMissingParents(const LVScopes *References,
288 const LVScopes *Targets,
289 bool TraverseChildren);
290
291 // Checks if the current scope is contained within the target scope.
292 // Depending on the result, the callback may be performed.
293 virtual void markMissingParents(const LVScope *Target, bool TraverseChildren);
294
295 // Returns true if the current scope and the given 'Scope' have the
296 // same number of children.
297 virtual bool equalNumberOfChildren(const LVScope *Scope) const;
298
299 // Returns true if current scope is logically equal to the given 'Scope'.
300 virtual bool equals(const LVScope *Scope) const;
301
302 // Returns true if the given 'References' are logically equal to the
303 // given 'Targets'.
304 static bool equals(const LVScopes *References, const LVScopes *Targets);
305
306 // For the given 'Scopes' returns a scope that is logically equal
307 // to the current scope; otherwise 'nullptr'.
308 virtual LVScope *findEqualScope(const LVScopes *Scopes) const;
309
310 // Report the current scope as missing or added during comparison.
311 void report(LVComparePass Pass) override;
312
313 static LVScopeDispatch &getDispatch() { return Dispatch; }
314
315 void print(raw_ostream &OS, bool Full = true) const override;
316 void printExtra(raw_ostream &OS, bool Full = true) const override;
317 virtual void printWarnings(raw_ostream &OS, bool Full = true) const {}
318 virtual void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) {}
319
320#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
321 void dump() const override { print(OS&: dbgs()); }
322#endif
323};
324
325// Class to represent a DWARF Union/Structure/Class.
326class LVScopeAggregate final : public LVScope {
327 LVScope *Reference = nullptr; // DW_AT_specification, DW_AT_abstract_origin.
328 size_t EncodedArgsIndex = 0; // Template encoded arguments.
329
330public:
331 LVScopeAggregate() : LVScope() {}
332 LVScopeAggregate(const LVScopeAggregate &) = delete;
333 LVScopeAggregate &operator=(const LVScopeAggregate &) = delete;
334 ~LVScopeAggregate() = default;
335
336 // DW_AT_specification, DW_AT_abstract_origin.
337 LVScope *getReference() const override { return Reference; }
338 void setReference(LVScope *Scope) override {
339 Reference = Scope;
340 setHasReference();
341 }
342 void setReference(LVElement *Element) override {
343 setReference(static_cast<LVScope *>(Element));
344 }
345
346 StringRef getEncodedArgs() const override {
347 return getStringPool().getString(Index: EncodedArgsIndex);
348 }
349 void setEncodedArgs(StringRef EncodedArgs) override {
350 EncodedArgsIndex = getStringPool().getIndex(Key: EncodedArgs);
351 }
352
353 // Returns true if current scope is logically equal to the given 'Scope'.
354 bool equals(const LVScope *Scope) const override;
355
356 // For the given 'Scopes' returns a scope that is logically equal
357 // to the current scope; otherwise 'nullptr'.
358 LVScope *findEqualScope(const LVScopes *Scopes) const override;
359
360 void printExtra(raw_ostream &OS, bool Full = true) const override;
361};
362
363// Class to represent a DWARF Template alias.
364class LVScopeAlias final : public LVScope {
365public:
366 LVScopeAlias() : LVScope() {
367 setIsTemplateAlias();
368 setIsTemplate();
369 }
370 LVScopeAlias(const LVScopeAlias &) = delete;
371 LVScopeAlias &operator=(const LVScopeAlias &) = delete;
372 ~LVScopeAlias() = default;
373
374 // Returns true if current scope is logically equal to the given 'Scope'.
375 bool equals(const LVScope *Scope) const override;
376
377 void printExtra(raw_ostream &OS, bool Full = true) const override;
378};
379
380// Class to represent a DWARF array (DW_TAG_array_type).
381class LVScopeArray final : public LVScope {
382public:
383 LVScopeArray() : LVScope() { setIsArray(); }
384 LVScopeArray(const LVScopeArray &) = delete;
385 LVScopeArray &operator=(const LVScopeArray &) = delete;
386 ~LVScopeArray() = default;
387
388 void resolveExtra() override;
389
390 // Returns true if current scope is logically equal to the given 'Scope'.
391 bool equals(const LVScope *Scope) const override;
392
393 void printExtra(raw_ostream &OS, bool Full = true) const override;
394};
395
396// Class to represent a DWARF Compilation Unit (CU).
397class LVScopeCompileUnit final : public LVScope {
398 // Names (files and directories) used by the Compile Unit.
399 std::vector<size_t> Filenames;
400
401 // As the .debug_pubnames section has been removed in DWARF5, we have a
402 // similar functionality, which is used by the decoded functions. We use
403 // the low-pc and high-pc for those scopes that are marked as public, in
404 // order to support DWARF and CodeView.
405 LVPublicNames PublicNames;
406
407 // Toolchain producer.
408 size_t ProducerIndex = 0;
409
410 // Compilation directory name.
411 size_t CompilationDirectoryIndex = 0;
412
413 // Used by the CodeView Reader.
414 codeview::CPUType CompilationCPUType = codeview::CPUType::X64;
415
416 // Keep record of elements. They are needed at the compilation unit level
417 // to print the summary at the end of the printing.
418 LVCounter Allocated;
419 LVCounter Found;
420 LVCounter Printed;
421
422 // Elements that match a given command line pattern.
423 LVElements MatchedElements;
424 LVScopes MatchedScopes;
425
426 // It records the mapping between logical lines representing a debug line
427 // entry and its address in the text section. It is used to find a line
428 // giving its exact or closest address. To support comdat functions, all
429 // addresses for the same section are recorded in the same map.
430 using LVAddressToLine = std::map<LVAddress, LVLine *>;
431 LVDoubleMap<LVSectionIndex, LVAddress, LVLine *> SectionMappings;
432
433 // DWARF Tags (Tag, Element list).
434 LVTagOffsetsMap DebugTags;
435
436 // Offsets associated with objects being flagged as having invalid data
437 // (ranges, locations, lines zero or coverages).
438 LVOffsetElementMap WarningOffsets;
439
440 // Symbols with invalid locations. (Symbol, Location List).
441 LVOffsetLocationsMap InvalidLocations;
442
443 // Symbols with invalid coverage values.
444 LVOffsetSymbolMap InvalidCoverages;
445
446 // Scopes with invalid ranges (Scope, Range list).
447 LVOffsetLocationsMap InvalidRanges;
448
449 // Scopes with lines zero (Scope, Line list).
450 LVOffsetLinesMap LinesZero;
451
452 // Record scopes contribution in bytes to the debug information.
453 using LVSizesMap = std::map<const LVScope *, LVOffset>;
454 LVSizesMap Sizes;
455 LVOffset CUContributionSize = 0;
456
457 // Helper function to add an invalid location/range.
458 void addInvalidLocationOrRange(LVLocation *Location, LVElement *Element,
459 LVOffsetLocationsMap *Map) {
460 LVOffset Offset = Element->getOffset();
461 addInvalidOffset(Offset, Element);
462 addItem<LVOffsetLocationsMap, LVOffset, LVLocation *>(Map, Key: Offset,
463 Value: Location);
464 }
465
466 // Record scope sizes indexed by lexical level.
467 // Setting an initial size that will cover a very deep nested scopes.
468 const size_t TotalInitialSize = 8;
469 using LVTotalsEntry = std::pair<unsigned, float>;
470 SmallVector<LVTotalsEntry> Totals;
471 // Maximum seen lexical level. It is used to control how many entries
472 // in the 'Totals' vector are valid values.
473 LVLevel MaxSeenLevel = 0;
474
475 // Get the line located at the given address.
476 LVLine *lineLowerBound(LVAddress Address, LVScope *Scope) const;
477 LVLine *lineUpperBound(LVAddress Address, LVScope *Scope) const;
478
479 void printScopeSize(const LVScope *Scope, raw_ostream &OS);
480 void printScopeSize(const LVScope *Scope, raw_ostream &OS) const {
481 (const_cast<LVScopeCompileUnit *>(this))->printScopeSize(Scope, OS);
482 }
483 void printTotals(raw_ostream &OS) const;
484
485protected:
486 void printSizes(raw_ostream &OS) const override;
487 void printSummary(raw_ostream &OS) const override;
488
489public:
490 LVScopeCompileUnit() : LVScope(), Totals(TotalInitialSize, {0, 0.0}) {
491 setIsCompileUnit();
492 }
493 LVScopeCompileUnit(const LVScopeCompileUnit &) = delete;
494 LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete;
495 ~LVScopeCompileUnit() = default;
496
497 LVScope *getCompileUnitParent() const override {
498 return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this));
499 }
500
501 // Add line to address mapping.
502 void addMapping(LVLine *Line, LVSectionIndex SectionIndex);
503 LVLineRange lineRange(LVLocation *Location) const;
504
505 LVNameInfo NameNone = {UINT64_MAX, 0};
506 void addPublicName(LVScope *Scope, LVAddress LowPC, LVAddress HighPC) {
507 PublicNames.emplace(args: std::piecewise_construct, args: std::forward_as_tuple(args&: Scope),
508 args: std::forward_as_tuple(args&: LowPC, args: HighPC - LowPC));
509 }
510 const LVNameInfo &findPublicName(LVScope *Scope) {
511 LVPublicNames::iterator Iter = PublicNames.find(x: Scope);
512 return (Iter != PublicNames.end()) ? Iter->second : NameNone;
513 }
514 const LVPublicNames &getPublicNames() const { return PublicNames; }
515
516 // The base address of the scope for any of the debugging information
517 // entries listed, is given by either the DW_AT_low_pc attribute or the
518 // first address in the first range entry in the list of ranges given by
519 // the DW_AT_ranges attribute.
520 LVAddress getBaseAddress() const {
521 return Ranges ? Ranges->front()->getLowerAddress() : 0;
522 }
523
524 StringRef getCompilationDirectory() const {
525 return getStringPool().getString(Index: CompilationDirectoryIndex);
526 }
527 void setCompilationDirectory(StringRef CompilationDirectory) {
528 CompilationDirectoryIndex = getStringPool().getIndex(Key: CompilationDirectory);
529 }
530
531 StringRef getFilename(size_t Index) const;
532 void addFilename(StringRef Name) {
533 Filenames.push_back(x: getStringPool().getIndex(Key: Name));
534 }
535
536 StringRef getProducer() const override {
537 return getStringPool().getString(Index: ProducerIndex);
538 }
539 void setProducer(StringRef ProducerName) override {
540 ProducerIndex = getStringPool().getIndex(Key: ProducerName);
541 }
542
543 void setCPUType(codeview::CPUType Type) { CompilationCPUType = Type; }
544 codeview::CPUType getCPUType() { return CompilationCPUType; }
545
546 // Record DWARF tags.
547 void addDebugTag(dwarf::Tag Target, LVOffset Offset);
548 // Record elements with invalid offsets.
549 void addInvalidOffset(LVOffset Offset, LVElement *Element);
550 // Record symbols with invalid coverage values.
551 void addInvalidCoverage(LVSymbol *Symbol);
552 // Record symbols with invalid locations.
553 void addInvalidLocation(LVLocation *Location);
554 // Record scopes with invalid ranges.
555 void addInvalidRange(LVLocation *Location);
556 // Record line zero.
557 void addLineZero(LVLine *Line);
558
559 const LVTagOffsetsMap &getDebugTags() const { return DebugTags; }
560 const LVOffsetElementMap &getWarningOffsets() const { return WarningOffsets; }
561 const LVOffsetLocationsMap &getInvalidLocations() const {
562 return InvalidLocations;
563 }
564 const LVOffsetSymbolMap &getInvalidCoverages() const {
565 return InvalidCoverages;
566 }
567 const LVOffsetLocationsMap &getInvalidRanges() const { return InvalidRanges; }
568 const LVOffsetLinesMap &getLinesZero() const { return LinesZero; }
569
570 // Process ranges, locations and calculate coverage.
571 void processRangeLocationCoverage(
572 LVValidLocation ValidLocation = &LVLocation::validateRanges);
573
574 // Add matched element.
575 void addMatched(LVElement *Element) { MatchedElements.push_back(Elt: Element); }
576 void addMatched(LVScope *Scope) { MatchedScopes.push_back(Elt: Scope); }
577 void propagatePatternMatch();
578
579 const LVElements &getMatchedElements() const { return MatchedElements; }
580 const LVScopes &getMatchedScopes() const { return MatchedScopes; }
581
582 void printLocalNames(raw_ostream &OS, bool Full = true) const;
583 void printSummary(raw_ostream &OS, const LVCounter &Counter,
584 const char *Header) const;
585
586 void incrementPrintedLines();
587 void incrementPrintedScopes();
588 void incrementPrintedSymbols();
589 void incrementPrintedTypes();
590
591 // Values are used by '--summary' option (allocated).
592 void increment(LVLine *Line);
593 void increment(LVScope *Scope);
594 void increment(LVSymbol *Symbol);
595 void increment(LVType *Type);
596
597 // A new element has been added to the scopes tree. Take the following steps:
598 // Increase the added element counters, for printing summary.
599 // During comparison notify the Reader of the new element.
600 void addedElement(LVLine *Line);
601 void addedElement(LVScope *Scope);
602 void addedElement(LVSymbol *Symbol);
603 void addedElement(LVType *Type);
604
605 void addSize(LVScope *Scope, LVOffset Lower, LVOffset Upper);
606
607 // Returns true if current scope is logically equal to the given 'Scope'.
608 bool equals(const LVScope *Scope) const override;
609
610 void print(raw_ostream &OS, bool Full = true) const override;
611 void printExtra(raw_ostream &OS, bool Full = true) const override;
612 void printWarnings(raw_ostream &OS, bool Full = true) const override;
613 void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) override;
614};
615
616// Class to represent a DWARF enumerator (DW_TAG_enumeration_type).
617class LVScopeEnumeration final : public LVScope {
618public:
619 LVScopeEnumeration() : LVScope() { setIsEnumeration(); }
620 LVScopeEnumeration(const LVScopeEnumeration &) = delete;
621 LVScopeEnumeration &operator=(const LVScopeEnumeration &) = delete;
622 ~LVScopeEnumeration() = default;
623
624 // Returns true if current scope is logically equal to the given 'Scope'.
625 bool equals(const LVScope *Scope) const override;
626
627 void printExtra(raw_ostream &OS, bool Full = true) const override;
628};
629
630// Class to represent a DWARF formal parameter pack
631// (DW_TAG_GNU_formal_parameter_pack).
632class LVScopeFormalPack final : public LVScope {
633public:
634 LVScopeFormalPack() : LVScope() { setIsTemplatePack(); }
635 LVScopeFormalPack(const LVScopeFormalPack &) = delete;
636 LVScopeFormalPack &operator=(const LVScopeFormalPack &) = delete;
637 ~LVScopeFormalPack() = default;
638
639 // Returns true if current scope is logically equal to the given 'Scope'.
640 bool equals(const LVScope *Scope) const override;
641
642 void printExtra(raw_ostream &OS, bool Full = true) const override;
643};
644
645// Class to represent a DWARF Function.
646class LVScopeFunction : public LVScope {
647 LVScope *Reference = nullptr; // DW_AT_specification, DW_AT_abstract_origin.
648 size_t LinkageNameIndex = 0; // Function DW_AT_linkage_name attribute.
649 size_t EncodedArgsIndex = 0; // Template encoded arguments.
650
651public:
652 LVScopeFunction() : LVScope() {}
653 LVScopeFunction(const LVScopeFunction &) = delete;
654 LVScopeFunction &operator=(const LVScopeFunction &) = delete;
655 virtual ~LVScopeFunction() = default;
656
657 // DW_AT_specification, DW_AT_abstract_origin.
658 LVScope *getReference() const override { return Reference; }
659 void setReference(LVScope *Scope) override {
660 Reference = Scope;
661 setHasReference();
662 }
663 void setReference(LVElement *Element) override {
664 setReference(static_cast<LVScope *>(Element));
665 }
666
667 StringRef getEncodedArgs() const override {
668 return getStringPool().getString(Index: EncodedArgsIndex);
669 }
670 void setEncodedArgs(StringRef EncodedArgs) override {
671 EncodedArgsIndex = getStringPool().getIndex(Key: EncodedArgs);
672 }
673
674 void setLinkageName(StringRef LinkageName) override {
675 LinkageNameIndex = getStringPool().getIndex(Key: LinkageName);
676 }
677 StringRef getLinkageName() const override {
678 return getStringPool().getString(Index: LinkageNameIndex);
679 }
680 size_t getLinkageNameIndex() const override { return LinkageNameIndex; }
681
682 void setName(StringRef ObjectName) override;
683
684 void resolveExtra() override;
685 void resolveReferences() override;
686
687 // Returns true if current scope is logically equal to the given 'Scope'.
688 bool equals(const LVScope *Scope) const override;
689
690 // For the given 'Scopes' returns a scope that is logically equal
691 // to the current scope; otherwise 'nullptr'.
692 LVScope *findEqualScope(const LVScopes *Scopes) const override;
693
694 void printExtra(raw_ostream &OS, bool Full = true) const override;
695};
696
697// Class to represent a DWARF inlined function.
698class LVScopeFunctionInlined final : public LVScopeFunction {
699 size_t CallFilenameIndex = 0;
700 uint32_t CallLineNumber = 0;
701 uint32_t Discriminator = 0;
702
703public:
704 LVScopeFunctionInlined() : LVScopeFunction() { setIsInlinedFunction(); }
705 LVScopeFunctionInlined(const LVScopeFunctionInlined &) = delete;
706 LVScopeFunctionInlined &operator=(const LVScopeFunctionInlined &) = delete;
707 ~LVScopeFunctionInlined() = default;
708
709 uint32_t getDiscriminator() const override { return Discriminator; }
710 void setDiscriminator(uint32_t Value) override {
711 Discriminator = Value;
712 setHasDiscriminator();
713 }
714
715 uint32_t getCallLineNumber() const override { return CallLineNumber; }
716 void setCallLineNumber(uint32_t Number) override { CallLineNumber = Number; }
717 size_t getCallFilenameIndex() const override { return CallFilenameIndex; }
718 void setCallFilenameIndex(size_t Index) override {
719 CallFilenameIndex = Index;
720 }
721
722 // Line number for display; in the case of Inlined Functions, we use the
723 // DW_AT_call_line attribute; otherwise use DW_AT_decl_line attribute.
724 std::string lineNumberAsString(bool ShowZero = false) const override {
725 return lineAsString(LineNumber: getCallLineNumber(), Discriminator: getDiscriminator(), ShowZero);
726 }
727
728 void resolveExtra() override;
729
730 // Returns true if current scope is logically equal to the given 'Scope'.
731 bool equals(const LVScope *Scope) const override;
732
733 // For the given 'Scopes' returns a scope that is logically equal
734 // to the current scope; otherwise 'nullptr'.
735 LVScope *findEqualScope(const LVScopes *Scopes) const override;
736
737 void printExtra(raw_ostream &OS, bool Full = true) const override;
738};
739
740// Class to represent a DWARF subroutine type.
741class LVScopeFunctionType final : public LVScopeFunction {
742public:
743 LVScopeFunctionType() : LVScopeFunction() { setIsFunctionType(); }
744 LVScopeFunctionType(const LVScopeFunctionType &) = delete;
745 LVScopeFunctionType &operator=(const LVScopeFunctionType &) = delete;
746 ~LVScopeFunctionType() = default;
747
748 void resolveExtra() override;
749};
750
751// Class to represent a DWARF Namespace.
752class LVScopeNamespace final : public LVScope {
753 LVScope *Reference = nullptr; // Reference to DW_AT_extension attribute.
754
755public:
756 LVScopeNamespace() : LVScope() { setIsNamespace(); }
757 LVScopeNamespace(const LVScopeNamespace &) = delete;
758 LVScopeNamespace &operator=(const LVScopeNamespace &) = delete;
759 ~LVScopeNamespace() = default;
760
761 // Access DW_AT_extension reference.
762 LVScope *getReference() const override { return Reference; }
763 void setReference(LVScope *Scope) override {
764 Reference = Scope;
765 setHasReference();
766 }
767 void setReference(LVElement *Element) override {
768 setReference(static_cast<LVScope *>(Element));
769 }
770
771 // Returns true if current scope is logically equal to the given 'Scope'.
772 bool equals(const LVScope *Scope) const override;
773
774 // For the given 'Scopes' returns a scope that is logically equal
775 // to the current scope; otherwise 'nullptr'.
776 LVScope *findEqualScope(const LVScopes *Scopes) const override;
777
778 void printExtra(raw_ostream &OS, bool Full = true) const override;
779};
780
781// Class to represent the binary file being analyzed.
782class LVScopeRoot final : public LVScope {
783 size_t FileFormatNameIndex = 0;
784
785public:
786 LVScopeRoot() : LVScope() { setIsRoot(); }
787 LVScopeRoot(const LVScopeRoot &) = delete;
788 LVScopeRoot &operator=(const LVScopeRoot &) = delete;
789 ~LVScopeRoot() = default;
790
791 StringRef getFileFormatName() const {
792 return getStringPool().getString(Index: FileFormatNameIndex);
793 }
794 void setFileFormatName(StringRef FileFormatName) {
795 FileFormatNameIndex = getStringPool().getIndex(Key: FileFormatName);
796 }
797
798 // The CodeView Reader uses scoped names. Recursively transform the
799 // element name to use just the most inner component.
800 void transformScopedName();
801
802 // Process the collected location, ranges and calculate coverage.
803 void processRangeInformation();
804
805 // Returns true if current scope is logically equal to the given 'Scope'.
806 bool equals(const LVScope *Scope) const override;
807
808 void print(raw_ostream &OS, bool Full = true) const override;
809 void printExtra(raw_ostream &OS, bool Full = true) const override;
810 Error doPrintMatches(bool Split, raw_ostream &OS,
811 bool UseMatchedElements) const;
812};
813
814// Class to represent a DWARF template parameter pack
815// (DW_TAG_GNU_template_parameter_pack).
816class LVScopeTemplatePack final : public LVScope {
817public:
818 LVScopeTemplatePack() : LVScope() { setIsTemplatePack(); }
819 LVScopeTemplatePack(const LVScopeTemplatePack &) = delete;
820 LVScopeTemplatePack &operator=(const LVScopeTemplatePack &) = delete;
821 ~LVScopeTemplatePack() = default;
822
823 // Returns true if current scope is logically equal to the given 'Scope'.
824 bool equals(const LVScope *Scope) const override;
825
826 void printExtra(raw_ostream &OS, bool Full = true) const override;
827};
828
829} // end namespace logicalview
830} // end namespace llvm
831
832#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
833

source code of llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h