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