diff options
Diffstat (limited to 'llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp b/llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp new file mode 100644 index 000000000000..c3810d282abc --- /dev/null +++ b/llvm/lib/DebugInfo/LogicalView/Core/LVLine.cpp @@ -0,0 +1,222 @@ +//===-- LVLine.cpp --------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This implements the LVLine class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/LogicalView/Core/LVLine.h" +#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h" +#include "llvm/DebugInfo/LogicalView/Core/LVReader.h" + +using namespace llvm; +using namespace llvm::logicalview; + +#define DEBUG_TYPE "Line" + +namespace { +const char *const KindBasicBlock = "BasicBlock"; +const char *const KindDiscriminator = "Discriminator"; +const char *const KindEndSequence = "EndSequence"; +const char *const KindEpilogueBegin = "EpilogueBegin"; +const char *const KindLineDebug = "Line"; +const char *const KindLineSource = "Code"; +const char *const KindNewStatement = "NewStatement"; +const char *const KindPrologueEnd = "PrologueEnd"; +const char *const KindUndefined = "Undefined"; +const char *const KindAlwaysStepInto = "AlwaysStepInto"; // CodeView +const char *const KindNeverStepInto = "NeverStepInto"; // CodeView +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Logical line. +//===----------------------------------------------------------------------===// +// Return a string representation for the line kind. +const char *LVLine::kind() const { + const char *Kind = KindUndefined; + if (getIsLineDebug()) + Kind = KindLineDebug; + else if (getIsLineAssembler()) + Kind = KindLineSource; + return Kind; +} + +LVLineDispatch LVLine::Dispatch = { + {LVLineKind::IsBasicBlock, &LVLine::getIsBasicBlock}, + {LVLineKind::IsDiscriminator, &LVLine::getIsDiscriminator}, + {LVLineKind::IsEndSequence, &LVLine::getIsEndSequence}, + {LVLineKind::IsLineDebug, &LVLine::getIsLineDebug}, + {LVLineKind::IsLineAssembler, &LVLine::getIsLineAssembler}, + {LVLineKind::IsNewStatement, &LVLine::getIsNewStatement}, + {LVLineKind::IsEpilogueBegin, &LVLine::getIsEpilogueBegin}, + {LVLineKind::IsPrologueEnd, &LVLine::getIsPrologueEnd}, + {LVLineKind::IsAlwaysStepInto, &LVLine::getIsAlwaysStepInto}, + {LVLineKind::IsNeverStepInto, &LVLine::getIsNeverStepInto}}; + +// String used as padding for printing elements with no line number. +std::string LVLine::noLineAsString(bool ShowZero) const { + if (options().getInternalNone()) + return LVObject::noLineAsString(ShowZero); + return (ShowZero || options().getAttributeZero()) ? (" 0 ") + : (" - "); +} + +void LVLine::markMissingParents(const LVLines *References, + const LVLines *Targets) { + if (!(References && Targets)) + return; + + LLVM_DEBUG({ + dbgs() << "\n[LVLine::markMissingParents]\n"; + for (const LVLine *Reference : *References) + dbgs() << "References: " + << "Kind = " << formattedKind(Reference->kind()) << ", " + << "Line = " << Reference->getLineNumber() << "\n"; + for (const LVLine *Target : *Targets) + dbgs() << "Targets : " + << "Kind = " << formattedKind(Target->kind()) << ", " + << "Line = " << Target->getLineNumber() << "\n"; + }); + + for (LVLine *Reference : *References) { + LLVM_DEBUG({ + dbgs() << "Search Reference: Line = " << Reference->getLineNumber() + << "\n"; + }); + if (!Reference->findIn(Targets)) + Reference->markBranchAsMissing(); + } +} + +LVLine *LVLine::findIn(const LVLines *Targets) const { + if (!Targets) + return nullptr; + + LLVM_DEBUG({ + dbgs() << "\n[LVLine::findIn]\n" + << "Reference: " + << "Level = " << getLevel() << ", " + << "Kind = " << formattedKind(kind()) << ", " + << "Line = " << getLineNumber() << "\n"; + for (const LVLine *Target : *Targets) + dbgs() << "Target : " + << "Level = " << Target->getLevel() << ", " + << "Kind = " << formattedKind(Target->kind()) << ", " + << "Line = " << Target->getLineNumber() << "\n"; + }); + + for (LVLine *Line : *Targets) + if (equals(Line)) + return Line; + + return nullptr; +} + +bool LVLine::equals(const LVLine *Line) const { + return LVElement::equals(Line); +} + +bool LVLine::equals(const LVLines *References, const LVLines *Targets) { + if (!References && !Targets) + return true; + if (References && Targets && References->size() == Targets->size()) { + for (const LVLine *Reference : *References) + if (!Reference->findIn(Targets)) + return false; + return true; + } + return false; +} + +void LVLine::report(LVComparePass Pass) { + getComparator().printItem(this, Pass); +} + +void LVLine::print(raw_ostream &OS, bool Full) const { + if (getReader().doPrintLine(this)) { + getReaderCompileUnit()->incrementPrintedLines(); + LVElement::print(OS, Full); + printExtra(OS, Full); + } +} + +//===----------------------------------------------------------------------===// +// DWARF line record. +//===----------------------------------------------------------------------===// +std::string LVLineDebug::statesInfo(bool Formatted) const { + // Returns the DWARF extra qualifiers. + std::string String; + raw_string_ostream Stream(String); + + std::string Separator = Formatted ? " " : ""; + if (getIsNewStatement()) { + Stream << Separator << "{" << KindNewStatement << "}"; + Separator = " "; + } + if (getIsDiscriminator()) { + Stream << Separator << "{" << KindDiscriminator << "}"; + Separator = " "; + } + if (getIsBasicBlock()) { + Stream << Separator << "{" << KindBasicBlock << "}"; + Separator = " "; + } + if (getIsEndSequence()) { + Stream << Separator << "{" << KindEndSequence << "}"; + Separator = " "; + } + if (getIsEpilogueBegin()) { + Stream << Separator << "{" << KindEpilogueBegin << "}"; + Separator = " "; + } + if (getIsPrologueEnd()) { + Stream << Separator << "{" << KindPrologueEnd << "}"; + Separator = " "; + } + if (getIsAlwaysStepInto()) { + Stream << Separator << "{" << KindAlwaysStepInto << "}"; + Separator = " "; + } + if (getIsNeverStepInto()) { + Stream << Separator << "{" << KindNeverStepInto << "}"; + Separator = " "; + } + + return String; +} + +bool LVLineDebug::equals(const LVLine *Line) const { + if (!LVLine::equals(Line)) + return false; + return getFilenameIndex() == Line->getFilenameIndex(); +} + +void LVLineDebug::printExtra(raw_ostream &OS, bool Full) const { + OS << formattedKind(kind()); + + if (options().getAttributeQualifier()) { + // The qualifier includes the states information and the source filename + // that contains the line element. + OS << statesInfo(/*Formatted=*/true); + OS << " " << formattedName(getPathname()); + } + OS << "\n"; +} + +//===----------------------------------------------------------------------===// +// Assembler line extracted from the ELF .text section. +//===----------------------------------------------------------------------===// +bool LVLineAssembler::equals(const LVLine *Line) const { + return LVLine::equals(Line); +} + +void LVLineAssembler::printExtra(raw_ostream &OS, bool Full) const { + OS << formattedKind(kind()); + OS << " " << formattedName(getName()); + OS << "\n"; +} |