1 | //===-- LVObject.cpp ------------------------------------------------------===// |
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 implements the LVObject class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/DebugInfo/LogicalView/Core/LVObject.h" |
14 | #include "llvm/DebugInfo/LogicalView/Core/LVReader.h" |
15 | #include "llvm/DebugInfo/LogicalView/Core/LVScope.h" |
16 | #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h" |
17 | #include <iomanip> |
18 | |
19 | using namespace llvm; |
20 | using namespace llvm::logicalview; |
21 | |
22 | #define DEBUG_TYPE "Object" |
23 | |
24 | uint32_t LVObject::GID = 0; |
25 | |
26 | StringRef llvm::logicalview::typeNone() { return StringRef(); } |
27 | StringRef llvm::logicalview::typeVoid() { return "void" ; } |
28 | StringRef llvm::logicalview::typeInt() { return "int" ; } |
29 | StringRef llvm::logicalview::typeUnknown() { return "?" ; } |
30 | StringRef llvm::logicalview::emptyString() { return StringRef(); } |
31 | |
32 | // Get a string representing the indentation level. |
33 | std::string LVObject::indentAsString(LVLevel Level) const { |
34 | return std::string(Level * 2, ' '); |
35 | } |
36 | |
37 | // Get a string representing the indentation level. |
38 | std::string LVObject::indentAsString() const { |
39 | return (options().getPrintFormatting() || options().getPrintOffset()) |
40 | ? indentAsString(Level: ScopeLevel) |
41 | : "" ; |
42 | } |
43 | |
44 | // String used as padding for printing objects with no line number. |
45 | std::string LVObject::noLineAsString(bool ShowZero) const { |
46 | return std::string(8, ' '); |
47 | } |
48 | |
49 | // Get a string representation for the given number and discriminator. |
50 | std::string LVObject::lineAsString(uint32_t LineNumber, LVHalf Discriminator, |
51 | bool ShowZero) const { |
52 | // The representation is formatted as: |
53 | // a) line number (xxxxx) and discriminator (yy): 'xxxxx,yy' |
54 | // b) Only line number (xxxxx): 'xxxxx ' |
55 | // c) No line number: ' ' |
56 | std::stringstream Stream; |
57 | if (LineNumber) { |
58 | if (Discriminator && options().getAttributeDiscriminator()) |
59 | Stream << std::setw(5) << LineNumber << "," << std::left << std::setw(2) |
60 | << Discriminator; |
61 | else |
62 | Stream << std::setw(5) << LineNumber << " " ; |
63 | } else |
64 | Stream << noLineAsString(ShowZero); |
65 | |
66 | if (options().getInternalNone()) |
67 | Stream.str(s: noLineAsString(ShowZero)); |
68 | |
69 | return Stream.str(); |
70 | } |
71 | |
72 | // Same as 'LineString' but with stripped whitespaces. |
73 | std::string LVObject::lineNumberAsStringStripped(bool ShowZero) const { |
74 | return std::string(StringRef(lineNumberAsString(ShowZero)).trim()); |
75 | } |
76 | |
77 | std::string LVObject::referenceAsString(uint32_t LineNumber, |
78 | bool Spaces) const { |
79 | std::string String; |
80 | raw_string_ostream Stream(String); |
81 | if (LineNumber) |
82 | Stream << "@" << LineNumber << (Spaces ? " " : "" ); |
83 | |
84 | return String; |
85 | } |
86 | |
87 | void LVObject::setParent(LVScope *Scope) { |
88 | Parent.Scope = Scope; |
89 | setLevel(Scope->getLevel() + 1); |
90 | } |
91 | void LVObject::setParent(LVSymbol *Symbol) { |
92 | Parent.Symbol = Symbol; |
93 | setLevel(Symbol->getLevel() + 1); |
94 | } |
95 | |
96 | void LVObject::markBranchAsMissing() { |
97 | // Mark the current object as 'missing'; then traverse the parents chain |
98 | // marking them as 'special missing' to indicate a missing branch. They |
99 | // can not be marked as missing, because will generate incorrect reports. |
100 | LVObject *Parent = this; |
101 | Parent->setIsMissing(); |
102 | while (Parent) { |
103 | Parent->setIsMissingLink(); |
104 | Parent = Parent->getParent(); |
105 | } |
106 | } |
107 | |
108 | Error LVObject::doPrint(bool Split, bool Match, bool Print, raw_ostream &OS, |
109 | bool Full) const { |
110 | print(OS, Full); |
111 | return Error::success(); |
112 | } |
113 | |
114 | void LVObject::printAttributes(raw_ostream &OS, bool Full, StringRef Name, |
115 | LVObject *Parent, StringRef Value, |
116 | bool UseQuotes, bool PrintRef) const { |
117 | // The current object will be the enclosing scope, use its offset and level. |
118 | LVObject Object(*Parent); |
119 | Object.setLevel(Parent->getLevel() + 1); |
120 | Object.setLineNumber(0); |
121 | Object.printAttributes(OS, Full); |
122 | |
123 | // Print the line. |
124 | std::string TheLineNumber(Object.lineNumberAsString()); |
125 | std::string TheIndentation(Object.indentAsString()); |
126 | OS << format(Fmt: " %5s %s " , Vals: TheLineNumber.c_str(), Vals: TheIndentation.c_str()); |
127 | |
128 | OS << Name; |
129 | if (PrintRef && options().getAttributeOffset()) |
130 | OS << hexSquareString(Value: getOffset()); |
131 | if (UseQuotes) |
132 | OS << formattedName(Name: Value) << "\n" ; |
133 | else |
134 | OS << Value << "\n" ; |
135 | } |
136 | |
137 | void LVObject::printAttributes(raw_ostream &OS, bool Full) const { |
138 | if (options().getInternalID()) |
139 | OS << hexSquareString(Value: getID()); |
140 | if (options().getCompareExecute() && |
141 | (options().getAttributeAdded() || options().getAttributeMissing())) |
142 | OS << (getIsAdded() ? '+' : getIsMissing() ? '-' : ' '); |
143 | if (options().getAttributeOffset()) |
144 | OS << hexSquareString(Value: getOffset()); |
145 | if (options().getAttributeLevel()) { |
146 | std::stringstream Stream; |
147 | Stream.str(s: std::string()); |
148 | Stream << "[" << std::setfill('0') << std::setw(3) << getLevel() << "]" ; |
149 | std::string TheLevel(Stream.str()); |
150 | OS << TheLevel; |
151 | } |
152 | if (options().getAttributeGlobal()) |
153 | OS << (getIsGlobalReference() ? 'X' : ' '); |
154 | } |
155 | |
156 | void LVObject::print(raw_ostream &OS, bool Full) const { |
157 | printFileIndex(OS, Full); |
158 | printAttributes(OS, Full); |
159 | |
160 | // Print the line and any discriminator. |
161 | std::stringstream Stream; |
162 | Stream << " " << std::setw(5) << lineNumberAsString() << " " |
163 | << indentAsString() << " " ; |
164 | OS << Stream.str(); |
165 | } |
166 | |