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
19using namespace llvm;
20using namespace llvm::logicalview;
21
22#define DEBUG_TYPE "Object"
23
24uint32_t LVObject::GID = 0;
25
26StringRef llvm::logicalview::typeNone() { return StringRef(); }
27StringRef llvm::logicalview::typeVoid() { return "void"; }
28StringRef llvm::logicalview::typeInt() { return "int"; }
29StringRef llvm::logicalview::typeUnknown() { return "?"; }
30StringRef llvm::logicalview::emptyString() { return StringRef(); }
31
32// Get a string representing the indentation level.
33std::string LVObject::indentAsString(LVLevel Level) const {
34 return std::string(Level * 2, ' ');
35}
36
37// Get a string representing the indentation level.
38std::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.
45std::string LVObject::noLineAsString(bool ShowZero) const {
46 return std::string(8, ' ');
47}
48
49// Get a string representation for the given number and discriminator.
50std::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.
73std::string LVObject::lineNumberAsStringStripped(bool ShowZero) const {
74 return std::string(StringRef(lineNumberAsString(ShowZero)).trim());
75}
76
77std::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
87void LVObject::setParent(LVScope *Scope) {
88 Parent.Scope = Scope;
89 setLevel(Scope->getLevel() + 1);
90}
91void LVObject::setParent(LVSymbol *Symbol) {
92 Parent.Symbol = Symbol;
93 setLevel(Symbol->getLevel() + 1);
94}
95
96void 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
108Error 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
114void 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
137void 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
156void 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