223 lines · cpp
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-exception6//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"; // CodeView33const char *const KindNeverStepInto = "NeverStepInto"; // CodeView34} // end anonymous namespace35 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 filename204 // 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