223 lines
7.2 KiB
C++
223 lines
7.2 KiB
C++
//===-- 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";
|
|
}
|