1//===-- LVObject.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 LVObject class, which is used to describe a debug
10// information object.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H
15#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H
16
17#include "llvm/BinaryFormat/Dwarf.h"
18#include "llvm/DebugInfo/CodeView/CodeView.h"
19#include "llvm/DebugInfo/CodeView/TypeIndex.h"
20#include "llvm/DebugInfo/LogicalView/Core/LVSupport.h"
21#include <limits>
22#include <list>
23#include <string>
24
25namespace llvm {
26namespace dwarf {
27// Support for CodeView ModifierOptions::Unaligned.
28constexpr Tag DW_TAG_unaligned = Tag(dwarf::DW_TAG_hi_user + 1);
29} // namespace dwarf
30} // namespace llvm
31
32namespace llvm {
33namespace logicalview {
34
35using LVSectionIndex = uint64_t;
36using LVAddress = uint64_t;
37using LVHalf = uint16_t;
38using LVLevel = uint32_t;
39using LVOffset = uint64_t;
40using LVSigned = int64_t;
41using LVUnsigned = uint64_t;
42using LVSmall = uint8_t;
43
44class LVElement;
45class LVLine;
46class LVLocation;
47class LVLocationSymbol;
48class LVObject;
49class LVOperation;
50class LVScope;
51class LVSymbol;
52class LVType;
53
54class LVOptions;
55class LVPatterns;
56
57StringRef typeNone();
58StringRef typeVoid();
59StringRef typeInt();
60StringRef typeUnknown();
61StringRef emptyString();
62
63using LVElementSetFunction = void (LVElement::*)();
64using LVElementGetFunction = bool (LVElement::*)() const;
65using LVLineSetFunction = void (LVLine::*)();
66using LVLineGetFunction = bool (LVLine::*)() const;
67using LVObjectSetFunction = void (LVObject::*)();
68using LVObjectGetFunction = bool (LVObject::*)() const;
69using LVScopeSetFunction = void (LVScope::*)();
70using LVScopeGetFunction = bool (LVScope::*)() const;
71using LVSymbolSetFunction = void (LVSymbol::*)();
72using LVSymbolGetFunction = bool (LVSymbol::*)() const;
73using LVTypeSetFunction = void (LVType::*)();
74using LVTypeGetFunction = bool (LVType::*)() const;
75
76using LVElements = SmallVector<LVElement *, 8>;
77using LVLines = SmallVector<LVLine *, 8>;
78using LVLocations = SmallVector<LVLocation *, 8>;
79using LVOperations = SmallVector<LVOperation *, 8>;
80using LVScopes = SmallVector<LVScope *, 8>;
81using LVSymbols = SmallVector<LVSymbol *, 8>;
82using LVTypes = SmallVector<LVType *, 8>;
83
84using LVOffsets = SmallVector<LVOffset, 8>;
85
86const LVAddress MaxAddress = std::numeric_limits<uint64_t>::max();
87
88enum class LVBinaryType { NONE, ELF, COFF };
89enum class LVComparePass { Missing, Added };
90
91// Validate functions.
92using LVValidLocation = bool (LVLocation::*)();
93
94// Keep counters of objects.
95struct LVCounter {
96  unsigned Lines = 0;
97  unsigned Scopes = 0;
98  unsigned Symbols = 0;
99  unsigned Types = 0;
100  void reset() {
101    Lines = 0;
102    Scopes = 0;
103    Symbols = 0;
104    Types = 0;
105  }
106};
107
108class LVObject {
109  enum class Property {
110    IsLocation,          // Location.
111    IsGlobalReference,   // This object is being referenced from another CU.
112    IsGeneratedName,     // The Object name was generated.
113    IsResolved,          // Object has been resolved.
114    IsResolvedName,      // Object name has been resolved.
115    IsDiscarded,         // Object has been stripped by the linker.
116    IsOptimized,         // Object has been optimized by the compiler.
117    IsAdded,             // Object has been 'added'.
118    IsMatched,           // Object has been matched to a given pattern.
119    IsMissing,           // Object is 'missing'.
120    IsMissingLink,       // Object is indirectly 'missing'.
121    IsInCompare,         // In 'compare' mode.
122    IsFileFromReference, // File ID from specification.
123    IsLineFromReference, // Line No from specification.
124    HasMoved,            // The object was moved from 'target' to 'reference'.
125    HasPattern,          // The object has a pattern.
126    IsFinalized,         // CodeView object is finalized.
127    IsReferenced,        // CodeView object being referenced.
128    HasCodeViewLocation, // CodeView object with debug location.
129    LastEntry
130  };
131  // Typed bitvector with properties for this object.
132  LVProperties<Property> Properties;
133
134  LVOffset Offset = 0;
135  uint32_t LineNumber = 0;
136  LVLevel ScopeLevel = 0;
137  union {
138    dwarf::Tag Tag;
139    dwarf::Attribute Attr;
140    LVSmall Opcode;
141  } TagAttrOpcode = {dwarf::DW_TAG_null};
142
143  // The parent of this object (nullptr if the root scope). For locations,
144  // the parent is a symbol object; otherwise it is a scope object.
145  union {
146    LVElement *Element;
147    LVScope *Scope;
148    LVSymbol *Symbol;
149  } Parent = {nullptr};
150
151  // We do not support any object duplication, as they are created by parsing
152  // the debug information. There is only the case where we need a very basic
153  // object, to manipulate its offset, line number and scope level. Allow the
154  // copy constructor to create that object; it is used to print a reference
155  // to another object and in the case of templates, to print its encoded args.
156  LVObject(const LVObject &Object) {
157#ifndef NDEBUG
158    incID();
159#endif
160    Properties = Object.Properties;
161    Offset = Object.Offset;
162    LineNumber = Object.LineNumber;
163    ScopeLevel = Object.ScopeLevel;
164    TagAttrOpcode = Object.TagAttrOpcode;
165    Parent = Object.Parent;
166  }
167
168#ifndef NDEBUG
169  // This is an internal ID used for debugging logical elements. It is used
170  // for cases where an unique offset within the binary input file is not
171  // available.
172  static uint64_t GID;
173  uint64_t ID = 0;
174
175  void incID() {
176    ++GID;
177    ID = GID;
178  }
179#endif
180
181protected:
182  // Get a string representation for the given number and discriminator.
183  std::string lineAsString(uint32_t LineNumber, LVHalf Discriminator,
184                           bool ShowZero) const;
185
186  // Get a string representation for the given number.
187  std::string referenceAsString(uint32_t LineNumber, bool Spaces) const;
188
189  // Print the Filename or Pathname.
190  // Empty implementation for those objects that do not have any user
191  // source file references, such as debug locations.
192  virtual void printFileIndex(raw_ostream &OS, bool Full = true) const {}
193
194public:
195  LVObject() {
196#ifndef NDEBUG
197    incID();
198#endif
199  };
200  LVObject &operator=(const LVObject &) = delete;
201  virtual ~LVObject() = default;
202
203  PROPERTY(Property, IsLocation);
204  PROPERTY(Property, IsGlobalReference);
205  PROPERTY(Property, IsGeneratedName);
206  PROPERTY(Property, IsResolved);
207  PROPERTY(Property, IsResolvedName);
208  PROPERTY(Property, IsDiscarded);
209  PROPERTY(Property, IsOptimized);
210  PROPERTY(Property, IsAdded);
211  PROPERTY(Property, IsMatched);
212  PROPERTY(Property, IsMissing);
213  PROPERTY(Property, IsMissingLink);
214  PROPERTY(Property, IsInCompare);
215  PROPERTY(Property, IsFileFromReference);
216  PROPERTY(Property, IsLineFromReference);
217  PROPERTY(Property, HasMoved);
218  PROPERTY(Property, HasPattern);
219  PROPERTY(Property, IsFinalized);
220  PROPERTY(Property, IsReferenced);
221  PROPERTY(Property, HasCodeViewLocation);
222
223  // True if the scope has been named or typed or with line number.
224  virtual bool isNamed() const { return false; }
225  virtual bool isTyped() const { return false; }
226  virtual bool isFiled() const { return false; }
227  bool isLined() const { return LineNumber != 0; }
228
229  // DWARF tag, attribute or expression opcode.
230  dwarf::Tag getTag() const { return TagAttrOpcode.Tag; }
231  void setTag(dwarf::Tag Tag) { TagAttrOpcode.Tag = Tag; }
232  dwarf::Attribute getAttr() const { return TagAttrOpcode.Attr; }
233  void setAttr(dwarf::Attribute Attr) { TagAttrOpcode.Attr = Attr; }
234  LVSmall getOpcode() const { return TagAttrOpcode.Opcode; }
235  void setOpcode(LVSmall Opcode) { TagAttrOpcode.Opcode = Opcode; }
236
237  // DIE offset.
238  LVOffset getOffset() const { return Offset; }
239  void setOffset(LVOffset DieOffset) { Offset = DieOffset; }
240
241  // Level where this object is located.
242  LVLevel getLevel() const { return ScopeLevel; }
243  void setLevel(LVLevel Level) { ScopeLevel = Level; }
244
245  virtual StringRef getName() const { return StringRef(); }
246  virtual void setName(StringRef ObjectName) {}
247
248  LVElement *getParent() const {
249    assert((!Parent.Element ||
250            (Parent.Element && static_cast<LVElement *>(Parent.Element))) &&
251           "Invalid element");
252    return Parent.Element;
253  }
254  LVScope *getParentScope() const {
255    assert((!Parent.Scope ||
256            (Parent.Scope && static_cast<LVScope *>(Parent.Scope))) &&
257           "Invalid scope");
258    return Parent.Scope;
259  }
260  LVSymbol *getParentSymbol() const {
261    assert((!Parent.Symbol ||
262            (Parent.Symbol && static_cast<LVSymbol *>(Parent.Symbol))) &&
263           "Invalid symbol");
264    return Parent.Symbol;
265  }
266  void setParent(LVScope *Scope);
267  void setParent(LVSymbol *Symbol);
268  void resetParent() { Parent = {nullptr}; }
269
270  virtual LVAddress getLowerAddress() const { return 0; }
271  virtual void setLowerAddress(LVAddress Address) {}
272  virtual LVAddress getUpperAddress() const { return 0; }
273  virtual void setUpperAddress(LVAddress Address) {}
274
275  uint32_t getLineNumber() const { return LineNumber; }
276  void setLineNumber(uint32_t Number) { LineNumber = Number; }
277
278  virtual const char *kind() const { return nullptr; }
279
280  std::string indentAsString() const;
281  std::string indentAsString(LVLevel Level) const;
282
283  // String used as padding for printing objects with no line number.
284  virtual std::string noLineAsString(bool ShowZero) const;
285
286  // Line number for display; in the case of inlined functions, we use the
287  // DW_AT_call_line attribute; otherwise use DW_AT_decl_line attribute.
288  virtual std::string lineNumberAsString(bool ShowZero = false) const {
289    return lineAsString(getLineNumber(), 0, ShowZero);
290  }
291  std::string lineNumberAsStringStripped(bool ShowZero = false) const;
292
293  // This function prints the logical view to an output stream.
294  // Split: Prints the compilation unit view to a file.
295  // Match: Prints the object only if it satisfies the patterns collected
296  // from the command line. See the '--select' option.
297  // Print: Print the object only if satisfies the conditions specified by
298  // the different '--print' options.
299  // Full: Prints full information for objects representing debug locations,
300  // aggregated scopes, compile unit, functions and namespaces.
301  virtual Error doPrint(bool Split, bool Match, bool Print, raw_ostream &OS,
302                        bool Full = true) const;
303  void printAttributes(raw_ostream &OS, bool Full = true) const;
304  void printAttributes(raw_ostream &OS, bool Full, StringRef Name,
305                       LVObject *Parent, StringRef Value,
306                       bool UseQuotes = false, bool PrintRef = false) const;
307
308  // Mark branch as missing (current element and parents).
309  void markBranchAsMissing();
310
311  // Prints the common information for an object (name, type, etc).
312  virtual void print(raw_ostream &OS, bool Full = true) const;
313  // Prints additional information for an object, depending on its kind
314  // (class attributes, debug ranges, files, directories, etc).
315  virtual void printExtra(raw_ostream &OS, bool Full = true) const {}
316
317#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
318  virtual void dump() const { print(dbgs()); }
319#endif
320
321  uint64_t getID() const {
322    return
323#ifndef NDEBUG
324        ID;
325#else
326        0;
327#endif
328  }
329};
330
331} // end namespace logicalview
332} // end namespace llvm
333
334#endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVOBJECT_H
335