1//===-- LVLine.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 LVLine class. 10// 11//===----------------------------------------------------------------------===// 12 13#include "llvm/DebugInfo/LogicalView/Core/LVLine.h" 14#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h" 15#include "llvm/DebugInfo/LogicalView/Core/LVReader.h" 16 17using namespace llvm; 18using namespace llvm::logicalview; 19 20#define DEBUG_TYPE "Line" 21 22namespace { 23const char *const KindBasicBlock = "BasicBlock"; 24const char *const KindDiscriminator = "Discriminator"; 25const char *const KindEndSequence = "EndSequence"; 26const char *const KindEpilogueBegin = "EpilogueBegin"; 27const char *const KindLineDebug = "Line"; 28const char *const KindLineSource = "Code"; 29const char *const KindNewStatement = "NewStatement"; 30const char *const KindPrologueEnd = "PrologueEnd"; 31const char *const KindUndefined = "Undefined"; 32const char *const KindAlwaysStepInto = "AlwaysStepInto"; // CodeView 33const char *const KindNeverStepInto = "NeverStepInto"; // CodeView 34} // end anonymous namespace 35 36//===----------------------------------------------------------------------===// 37// Logical line. 38//===----------------------------------------------------------------------===// 39// Return a string representation for the line kind. 40const char *LVLine::kind() const { 41 const char *Kind = KindUndefined; 42 if (getIsLineDebug()) 43 Kind = KindLineDebug; 44 else if (getIsLineAssembler()) 45 Kind = KindLineSource; 46 return Kind; 47} 48 49LVLineDispatch LVLine::Dispatch = { 50 {LVLineKind::IsBasicBlock, &LVLine::getIsBasicBlock}, 51 {LVLineKind::IsDiscriminator, &LVLine::getIsDiscriminator}, 52 {LVLineKind::IsEndSequence, &LVLine::getIsEndSequence}, 53 {LVLineKind::IsLineDebug, &LVLine::getIsLineDebug}, 54 {LVLineKind::IsLineAssembler, &LVLine::getIsLineAssembler}, 55 {LVLineKind::IsNewStatement, &LVLine::getIsNewStatement}, 56 {LVLineKind::IsEpilogueBegin, &LVLine::getIsEpilogueBegin}, 57 {LVLineKind::IsPrologueEnd, &LVLine::getIsPrologueEnd}, 58 {LVLineKind::IsAlwaysStepInto, &LVLine::getIsAlwaysStepInto}, 59 {LVLineKind::IsNeverStepInto, &LVLine::getIsNeverStepInto}}; 60 61// String used as padding for printing elements with no line number. 62std::string LVLine::noLineAsString(bool ShowZero) const { 63 if (options().getInternalNone()) 64 return LVObject::noLineAsString(ShowZero); 65 return (ShowZero || options().getAttributeZero()) ? (" 0 ") 66 : (" - "); 67} 68 69void LVLine::markMissingParents(const LVLines *References, 70 const LVLines *Targets) { 71 if (!(References && Targets)) 72 return; 73 74 LLVM_DEBUG({ 75 dbgs() << "\n[LVLine::markMissingParents]\n"; 76 for (const LVLine *Reference : *References) 77 dbgs() << "References: " 78 << "Kind = " << formattedKind(Reference->kind()) << ", " 79 << "Line = " << Reference->getLineNumber() << "\n"; 80 for (const LVLine *Target : *Targets) 81 dbgs() << "Targets : " 82 << "Kind = " << formattedKind(Target->kind()) << ", " 83 << "Line = " << Target->getLineNumber() << "\n"; 84 }); 85 86 for (LVLine *Reference : *References) { 87 LLVM_DEBUG({ 88 dbgs() << "Search Reference: Line = " << Reference->getLineNumber() 89 << "\n"; 90 }); 91 if (!Reference->findIn(Targets)) 92 Reference->markBranchAsMissing(); 93 } 94} 95 96LVLine *LVLine::findIn(const LVLines *Targets) const { 97 if (!Targets) 98 return nullptr; 99 100 LLVM_DEBUG({ 101 dbgs() << "\n[LVLine::findIn]\n" 102 << "Reference: " 103 << "Level = " << getLevel() << ", " 104 << "Kind = " << formattedKind(kind()) << ", " 105 << "Line = " << getLineNumber() << "\n"; 106 for (const LVLine *Target : *Targets) 107 dbgs() << "Target : " 108 << "Level = " << Target->getLevel() << ", " 109 << "Kind = " << formattedKind(Target->kind()) << ", " 110 << "Line = " << Target->getLineNumber() << "\n"; 111 }); 112 113 for (LVLine *Line : *Targets) 114 if (equals(Line)) 115 return Line; 116 117 return nullptr; 118} 119 120bool LVLine::equals(const LVLine *Line) const { 121 return LVElement::equals(Line); 122} 123 124bool LVLine::equals(const LVLines *References, const LVLines *Targets) { 125 if (!References && !Targets) 126 return true; 127 if (References && Targets && References->size() == Targets->size()) { 128 for (const LVLine *Reference : *References) 129 if (!Reference->findIn(Targets)) 130 return false; 131 return true; 132 } 133 return false; 134} 135 136void LVLine::report(LVComparePass Pass) { 137 getComparator().printItem(this, Pass); 138} 139 140void LVLine::print(raw_ostream &OS, bool Full) const { 141 if (getReader().doPrintLine(this)) { 142 getReaderCompileUnit()->incrementPrintedLines(); 143 LVElement::print(OS, Full); 144 printExtra(OS, Full); 145 } 146} 147 148//===----------------------------------------------------------------------===// 149// DWARF line record. 150//===----------------------------------------------------------------------===// 151std::string LVLineDebug::statesInfo(bool Formatted) const { 152 // Returns the DWARF extra qualifiers. 153 std::string String; 154 raw_string_ostream Stream(String); 155 156 std::string Separator = Formatted ? " " : ""; 157 if (getIsNewStatement()) { 158 Stream << Separator << "{" << KindNewStatement << "}"; 159 Separator = " "; 160 } 161 if (getIsDiscriminator()) { 162 Stream << Separator << "{" << KindDiscriminator << "}"; 163 Separator = " "; 164 } 165 if (getIsBasicBlock()) { 166 Stream << Separator << "{" << KindBasicBlock << "}"; 167 Separator = " "; 168 } 169 if (getIsEndSequence()) { 170 Stream << Separator << "{" << KindEndSequence << "}"; 171 Separator = " "; 172 } 173 if (getIsEpilogueBegin()) { 174 Stream << Separator << "{" << KindEpilogueBegin << "}"; 175 Separator = " "; 176 } 177 if (getIsPrologueEnd()) { 178 Stream << Separator << "{" << KindPrologueEnd << "}"; 179 Separator = " "; 180 } 181 if (getIsAlwaysStepInto()) { 182 Stream << Separator << "{" << KindAlwaysStepInto << "}"; 183 Separator = " "; 184 } 185 if (getIsNeverStepInto()) { 186 Stream << Separator << "{" << KindNeverStepInto << "}"; 187 Separator = " "; 188 } 189 190 return String; 191} 192 193bool LVLineDebug::equals(const LVLine *Line) const { 194 if (!LVLine::equals(Line)) 195 return false; 196 return getFilenameIndex() == Line->getFilenameIndex(); 197} 198 199void LVLineDebug::printExtra(raw_ostream &OS, bool Full) const { 200 OS << formattedKind(kind()); 201 202 if (options().getAttributeQualifier()) { 203 // The qualifier includes the states information and the source filename 204 // that contains the line element. 205 OS << statesInfo(/*Formatted=*/true); 206 OS << " " << formattedName(getPathname()); 207 } 208 OS << "\n"; 209} 210 211//===----------------------------------------------------------------------===// 212// Assembler line extracted from the ELF .text section. 213//===----------------------------------------------------------------------===// 214bool LVLineAssembler::equals(const LVLine *Line) const { 215 return LVLine::equals(Line); 216} 217 218void LVLineAssembler::printExtra(raw_ostream &OS, bool Full) const { 219 OS << formattedKind(kind()); 220 OS << " " << formattedName(getName()); 221 OS << "\n"; 222} 223