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