| 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 | |