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 | |
17 | using namespace llvm; |
18 | using namespace llvm::logicalview; |
19 | |
20 | #define DEBUG_TYPE "Line" |
21 | |
22 | namespace { |
23 | const char *const KindBasicBlock = "BasicBlock" ; |
24 | const char *const KindDiscriminator = "Discriminator" ; |
25 | const char *const KindEndSequence = "EndSequence" ; |
26 | const char *const KindEpilogueBegin = "EpilogueBegin" ; |
27 | const char *const KindLineDebug = "Line" ; |
28 | const char *const KindLineSource = "Code" ; |
29 | const char *const KindNewStatement = "NewStatement" ; |
30 | const char *const KindPrologueEnd = "PrologueEnd" ; |
31 | const char *const KindUndefined = "Undefined" ; |
32 | const char *const KindAlwaysStepInto = "AlwaysStepInto" ; // CodeView |
33 | const char *const KindNeverStepInto = "NeverStepInto" ; // CodeView |
34 | } // end anonymous namespace |
35 | |
36 | //===----------------------------------------------------------------------===// |
37 | // Logical line. |
38 | //===----------------------------------------------------------------------===// |
39 | // Return a string representation for the line kind. |
40 | const 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 | |
49 | LVLineDispatch 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. |
62 | std::string LVLine::noLineAsString(bool ShowZero) const { |
63 | if (options().getInternalNone()) |
64 | return LVObject::noLineAsString(ShowZero); |
65 | return (ShowZero || options().getAttributeZero()) ? (" 0 " ) |
66 | : (" - " ); |
67 | } |
68 | |
69 | void 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 | |
96 | LVLine *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 | |
120 | bool LVLine::equals(const LVLine *Line) const { |
121 | return LVElement::equals(Element: Line); |
122 | } |
123 | |
124 | bool 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 | |
136 | void LVLine::report(LVComparePass Pass) { |
137 | getComparator().printItem(Element: this, Pass); |
138 | } |
139 | |
140 | void LVLine::print(raw_ostream &OS, bool Full) const { |
141 | if (getReader().doPrintLine(Line: this)) { |
142 | getReaderCompileUnit()->incrementPrintedLines(); |
143 | LVElement::print(OS, Full); |
144 | printExtra(OS, Full); |
145 | } |
146 | } |
147 | |
148 | //===----------------------------------------------------------------------===// |
149 | // DWARF line record. |
150 | //===----------------------------------------------------------------------===// |
151 | std::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 | |
193 | bool LVLineDebug::equals(const LVLine *Line) const { |
194 | if (!LVLine::equals(Line)) |
195 | return false; |
196 | return getFilenameIndex() == Line->getFilenameIndex(); |
197 | } |
198 | |
199 | void LVLineDebug::(raw_ostream &OS, bool Full) const { |
200 | OS << formattedKind(Kind: 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(Name: getPathname()); |
207 | } |
208 | OS << "\n" ; |
209 | } |
210 | |
211 | //===----------------------------------------------------------------------===// |
212 | // Assembler line extracted from the ELF .text section. |
213 | //===----------------------------------------------------------------------===// |
214 | bool LVLineAssembler::equals(const LVLine *Line) const { |
215 | return LVLine::equals(Line); |
216 | } |
217 | |
218 | void LVLineAssembler::(raw_ostream &OS, bool Full) const { |
219 | OS << formattedKind(Kind: kind()); |
220 | OS << " " << formattedName(Name: getName()); |
221 | OS << "\n" ; |
222 | } |
223 | |