1bdd1243dSDimitry Andric //===-- LVScope.cpp -------------------------------------------------------===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric //
9bdd1243dSDimitry Andric // This implements the LVScope class.
10bdd1243dSDimitry Andric //
11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
12bdd1243dSDimitry Andric
13bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
14bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
15bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
16bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
17bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVRange.h"
18bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
19bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
20bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
21bdd1243dSDimitry Andric
22bdd1243dSDimitry Andric using namespace llvm;
23bdd1243dSDimitry Andric using namespace llvm::logicalview;
24bdd1243dSDimitry Andric
25bdd1243dSDimitry Andric #define DEBUG_TYPE "Scope"
26bdd1243dSDimitry Andric
27bdd1243dSDimitry Andric namespace {
28bdd1243dSDimitry Andric const char *const KindArray = "Array";
29bdd1243dSDimitry Andric const char *const KindBlock = "Block";
30bdd1243dSDimitry Andric const char *const KindCallSite = "CallSite";
31bdd1243dSDimitry Andric const char *const KindClass = "Class";
32bdd1243dSDimitry Andric const char *const KindCompileUnit = "CompileUnit";
33bdd1243dSDimitry Andric const char *const KindEnumeration = "Enumeration";
34bdd1243dSDimitry Andric const char *const KindFile = "File";
35bdd1243dSDimitry Andric const char *const KindFunction = "Function";
36bdd1243dSDimitry Andric const char *const KindInlinedFunction = "InlinedFunction";
37bdd1243dSDimitry Andric const char *const KindNamespace = "Namespace";
38bdd1243dSDimitry Andric const char *const KindStruct = "Struct";
39bdd1243dSDimitry Andric const char *const KindTemplateAlias = "TemplateAlias";
40bdd1243dSDimitry Andric const char *const KindTemplatePack = "TemplatePack";
41bdd1243dSDimitry Andric const char *const KindUndefined = "Undefined";
42bdd1243dSDimitry Andric const char *const KindUnion = "Union";
43bdd1243dSDimitry Andric } // end anonymous namespace
44bdd1243dSDimitry Andric
45bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
46bdd1243dSDimitry Andric // DWARF lexical block, such as: namespace, function, compile unit, module, etc.
47bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
48bdd1243dSDimitry Andric // Return a string representation for the scope kind.
kind() const49bdd1243dSDimitry Andric const char *LVScope::kind() const {
50bdd1243dSDimitry Andric const char *Kind = KindUndefined;
51bdd1243dSDimitry Andric if (getIsArray())
52bdd1243dSDimitry Andric Kind = KindArray;
53bdd1243dSDimitry Andric else if (getIsBlock())
54bdd1243dSDimitry Andric Kind = KindBlock;
55bdd1243dSDimitry Andric else if (getIsCallSite())
56bdd1243dSDimitry Andric Kind = KindCallSite;
57bdd1243dSDimitry Andric else if (getIsCompileUnit())
58bdd1243dSDimitry Andric Kind = KindCompileUnit;
59bdd1243dSDimitry Andric else if (getIsEnumeration())
60bdd1243dSDimitry Andric Kind = KindEnumeration;
61bdd1243dSDimitry Andric else if (getIsInlinedFunction())
62bdd1243dSDimitry Andric Kind = KindInlinedFunction;
63bdd1243dSDimitry Andric else if (getIsNamespace())
64bdd1243dSDimitry Andric Kind = KindNamespace;
65bdd1243dSDimitry Andric else if (getIsTemplatePack())
66bdd1243dSDimitry Andric Kind = KindTemplatePack;
67bdd1243dSDimitry Andric else if (getIsRoot())
68bdd1243dSDimitry Andric Kind = KindFile;
69bdd1243dSDimitry Andric else if (getIsTemplateAlias())
70bdd1243dSDimitry Andric Kind = KindTemplateAlias;
71bdd1243dSDimitry Andric else if (getIsClass())
72bdd1243dSDimitry Andric Kind = KindClass;
73bdd1243dSDimitry Andric else if (getIsFunction())
74bdd1243dSDimitry Andric Kind = KindFunction;
75bdd1243dSDimitry Andric else if (getIsStructure())
76bdd1243dSDimitry Andric Kind = KindStruct;
77bdd1243dSDimitry Andric else if (getIsUnion())
78bdd1243dSDimitry Andric Kind = KindUnion;
79bdd1243dSDimitry Andric return Kind;
80bdd1243dSDimitry Andric }
81bdd1243dSDimitry Andric
82bdd1243dSDimitry Andric LVScopeDispatch LVScope::Dispatch = {
83bdd1243dSDimitry Andric {LVScopeKind::IsAggregate, &LVScope::getIsAggregate},
84bdd1243dSDimitry Andric {LVScopeKind::IsArray, &LVScope::getIsArray},
85bdd1243dSDimitry Andric {LVScopeKind::IsBlock, &LVScope::getIsBlock},
86bdd1243dSDimitry Andric {LVScopeKind::IsCallSite, &LVScope::getIsCallSite},
87bdd1243dSDimitry Andric {LVScopeKind::IsCatchBlock, &LVScope::getIsCatchBlock},
88bdd1243dSDimitry Andric {LVScopeKind::IsClass, &LVScope::getIsClass},
89bdd1243dSDimitry Andric {LVScopeKind::IsCompileUnit, &LVScope::getIsCompileUnit},
90bdd1243dSDimitry Andric {LVScopeKind::IsEntryPoint, &LVScope::getIsEntryPoint},
91bdd1243dSDimitry Andric {LVScopeKind::IsEnumeration, &LVScope::getIsEnumeration},
92bdd1243dSDimitry Andric {LVScopeKind::IsFunction, &LVScope::getIsFunction},
93bdd1243dSDimitry Andric {LVScopeKind::IsFunctionType, &LVScope::getIsFunctionType},
94bdd1243dSDimitry Andric {LVScopeKind::IsInlinedFunction, &LVScope::getIsInlinedFunction},
95bdd1243dSDimitry Andric {LVScopeKind::IsLabel, &LVScope::getIsLabel},
96bdd1243dSDimitry Andric {LVScopeKind::IsLexicalBlock, &LVScope::getIsLexicalBlock},
97bdd1243dSDimitry Andric {LVScopeKind::IsNamespace, &LVScope::getIsNamespace},
98bdd1243dSDimitry Andric {LVScopeKind::IsRoot, &LVScope::getIsRoot},
99bdd1243dSDimitry Andric {LVScopeKind::IsStructure, &LVScope::getIsStructure},
100bdd1243dSDimitry Andric {LVScopeKind::IsTemplate, &LVScope::getIsTemplate},
101bdd1243dSDimitry Andric {LVScopeKind::IsTemplateAlias, &LVScope::getIsTemplateAlias},
102bdd1243dSDimitry Andric {LVScopeKind::IsTemplatePack, &LVScope::getIsTemplatePack},
103bdd1243dSDimitry Andric {LVScopeKind::IsTryBlock, &LVScope::getIsTryBlock},
104bdd1243dSDimitry Andric {LVScopeKind::IsUnion, &LVScope::getIsUnion}};
105bdd1243dSDimitry Andric
addToChildren(LVElement * Element)106bdd1243dSDimitry Andric void LVScope::addToChildren(LVElement *Element) {
107bdd1243dSDimitry Andric if (!Children)
10806c3fb27SDimitry Andric Children = std::make_unique<LVElements>();
109bdd1243dSDimitry Andric Children->push_back(Element);
110bdd1243dSDimitry Andric }
111bdd1243dSDimitry Andric
addElement(LVElement * Element)112bdd1243dSDimitry Andric void LVScope::addElement(LVElement *Element) {
113bdd1243dSDimitry Andric assert(Element && "Invalid element.");
114bdd1243dSDimitry Andric if (Element->getIsType())
115bdd1243dSDimitry Andric addElement(static_cast<LVType *>(Element));
116bdd1243dSDimitry Andric else if (Element->getIsScope())
117bdd1243dSDimitry Andric addElement(static_cast<LVScope *>(Element));
118bdd1243dSDimitry Andric else if (Element->getIsSymbol())
119bdd1243dSDimitry Andric addElement(static_cast<LVSymbol *>(Element));
120bdd1243dSDimitry Andric else if (Element->getIsLine())
121bdd1243dSDimitry Andric addElement(static_cast<LVLine *>(Element));
122bdd1243dSDimitry Andric else
123bdd1243dSDimitry Andric llvm_unreachable("Invalid Element.");
124bdd1243dSDimitry Andric }
125bdd1243dSDimitry Andric
126bdd1243dSDimitry Andric // Adds the line info item to the ones stored in the scope.
addElement(LVLine * Line)127bdd1243dSDimitry Andric void LVScope::addElement(LVLine *Line) {
128bdd1243dSDimitry Andric assert(Line && "Invalid line.");
129bdd1243dSDimitry Andric assert(!Line->getParent() && "Line already inserted");
130bdd1243dSDimitry Andric if (!Lines)
13106c3fb27SDimitry Andric Lines = std::make_unique<LVLines>();
132bdd1243dSDimitry Andric
133bdd1243dSDimitry Andric // Add it to parent.
134bdd1243dSDimitry Andric Lines->push_back(Line);
135bdd1243dSDimitry Andric Line->setParent(this);
136bdd1243dSDimitry Andric
137bdd1243dSDimitry Andric // Notify the reader about the new element being added.
138bdd1243dSDimitry Andric getReaderCompileUnit()->addedElement(Line);
139bdd1243dSDimitry Andric
140bdd1243dSDimitry Andric // All logical elements added to the children, are sorted by any of the
141bdd1243dSDimitry Andric // following criterias: offset, name, line number, kind.
142bdd1243dSDimitry Andric // Do not add the line records to the children, as they represent the
143bdd1243dSDimitry Andric // logical view for the text section and any sorting will not preserve
144bdd1243dSDimitry Andric // the original sequence.
145bdd1243dSDimitry Andric
146bdd1243dSDimitry Andric // Indicate that this tree branch has lines.
147bdd1243dSDimitry Andric traverseParents(&LVScope::getHasLines, &LVScope::setHasLines);
148bdd1243dSDimitry Andric }
149bdd1243dSDimitry Andric
150bdd1243dSDimitry Andric // Add a location.
addObject(LVLocation * Location)151bdd1243dSDimitry Andric void LVScope::addObject(LVLocation *Location) {
152bdd1243dSDimitry Andric assert(Location && "Invalid location.");
153bdd1243dSDimitry Andric assert(!Location->getParent() && "Location already inserted");
154bdd1243dSDimitry Andric if (!Ranges)
15506c3fb27SDimitry Andric Ranges = std::make_unique<LVLocations>();
156bdd1243dSDimitry Andric
157bdd1243dSDimitry Andric // Add it to parent.
158bdd1243dSDimitry Andric Location->setParent(this);
159bdd1243dSDimitry Andric Location->setOffset(getOffset());
160bdd1243dSDimitry Andric
161bdd1243dSDimitry Andric Ranges->push_back(Location);
162bdd1243dSDimitry Andric setHasRanges();
163bdd1243dSDimitry Andric }
164bdd1243dSDimitry Andric
165bdd1243dSDimitry Andric // Adds the scope to the child scopes and sets the parent in the child.
addElement(LVScope * Scope)166bdd1243dSDimitry Andric void LVScope::addElement(LVScope *Scope) {
167bdd1243dSDimitry Andric assert(Scope && "Invalid scope.");
168bdd1243dSDimitry Andric assert(!Scope->getParent() && "Scope already inserted");
169bdd1243dSDimitry Andric if (!Scopes)
17006c3fb27SDimitry Andric Scopes = std::make_unique<LVScopes>();
171bdd1243dSDimitry Andric
172bdd1243dSDimitry Andric // Add it to parent.
173bdd1243dSDimitry Andric Scopes->push_back(Scope);
174bdd1243dSDimitry Andric addToChildren(Scope);
175bdd1243dSDimitry Andric Scope->setParent(this);
176bdd1243dSDimitry Andric
177bdd1243dSDimitry Andric // Notify the reader about the new element being added.
178bdd1243dSDimitry Andric getReaderCompileUnit()->addedElement(Scope);
179bdd1243dSDimitry Andric
180bdd1243dSDimitry Andric // If the element is a global reference, mark its parent as having global
181bdd1243dSDimitry Andric // references; that information is used, to print only those branches
182bdd1243dSDimitry Andric // with global references.
183bdd1243dSDimitry Andric if (Scope->getIsGlobalReference())
184bdd1243dSDimitry Andric traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);
185bdd1243dSDimitry Andric else
186bdd1243dSDimitry Andric traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);
187bdd1243dSDimitry Andric
188bdd1243dSDimitry Andric // Indicate that this tree branch has scopes.
189bdd1243dSDimitry Andric traverseParents(&LVScope::getHasScopes, &LVScope::setHasScopes);
190bdd1243dSDimitry Andric }
191bdd1243dSDimitry Andric
192bdd1243dSDimitry Andric // Adds a symbol to the ones stored in the scope.
addElement(LVSymbol * Symbol)193bdd1243dSDimitry Andric void LVScope::addElement(LVSymbol *Symbol) {
194bdd1243dSDimitry Andric assert(Symbol && "Invalid symbol.");
195bdd1243dSDimitry Andric assert(!Symbol->getParent() && "Symbol already inserted");
196bdd1243dSDimitry Andric if (!Symbols)
19706c3fb27SDimitry Andric Symbols = std::make_unique<LVSymbols>();
198bdd1243dSDimitry Andric
199bdd1243dSDimitry Andric // Add it to parent.
200bdd1243dSDimitry Andric Symbols->push_back(Symbol);
201bdd1243dSDimitry Andric addToChildren(Symbol);
202bdd1243dSDimitry Andric Symbol->setParent(this);
203bdd1243dSDimitry Andric
204bdd1243dSDimitry Andric // Notify the reader about the new element being added.
205bdd1243dSDimitry Andric getReaderCompileUnit()->addedElement(Symbol);
206bdd1243dSDimitry Andric
207bdd1243dSDimitry Andric // If the element is a global reference, mark its parent as having global
208bdd1243dSDimitry Andric // references; that information is used, to print only those branches
209bdd1243dSDimitry Andric // with global references.
210bdd1243dSDimitry Andric if (Symbol->getIsGlobalReference())
211bdd1243dSDimitry Andric traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);
212bdd1243dSDimitry Andric else
213bdd1243dSDimitry Andric traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);
214bdd1243dSDimitry Andric
215bdd1243dSDimitry Andric // Indicate that this tree branch has symbols.
216bdd1243dSDimitry Andric traverseParents(&LVScope::getHasSymbols, &LVScope::setHasSymbols);
217bdd1243dSDimitry Andric }
218bdd1243dSDimitry Andric
219bdd1243dSDimitry Andric // Adds a type to the ones stored in the scope.
addElement(LVType * Type)220bdd1243dSDimitry Andric void LVScope::addElement(LVType *Type) {
221bdd1243dSDimitry Andric assert(Type && "Invalid type.");
222bdd1243dSDimitry Andric assert(!Type->getParent() && "Type already inserted");
223bdd1243dSDimitry Andric if (!Types)
22406c3fb27SDimitry Andric Types = std::make_unique<LVTypes>();
225bdd1243dSDimitry Andric
226bdd1243dSDimitry Andric // Add it to parent.
227bdd1243dSDimitry Andric Types->push_back(Type);
228bdd1243dSDimitry Andric addToChildren(Type);
229bdd1243dSDimitry Andric Type->setParent(this);
230bdd1243dSDimitry Andric
231bdd1243dSDimitry Andric // Notify the reader about the new element being added.
232bdd1243dSDimitry Andric getReaderCompileUnit()->addedElement(Type);
233bdd1243dSDimitry Andric
234bdd1243dSDimitry Andric // If the element is a global reference, mark its parent as having global
235bdd1243dSDimitry Andric // references; that information is used, to print only those branches
236bdd1243dSDimitry Andric // with global references.
237bdd1243dSDimitry Andric if (Type->getIsGlobalReference())
238bdd1243dSDimitry Andric traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);
239bdd1243dSDimitry Andric else
240bdd1243dSDimitry Andric traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);
241bdd1243dSDimitry Andric
242bdd1243dSDimitry Andric // Indicate that this tree branch has types.
243bdd1243dSDimitry Andric traverseParents(&LVScope::getHasTypes, &LVScope::setHasTypes);
244bdd1243dSDimitry Andric }
245bdd1243dSDimitry Andric
246bdd1243dSDimitry Andric // Add a pair of ranges.
addObject(LVAddress LowerAddress,LVAddress UpperAddress)247bdd1243dSDimitry Andric void LVScope::addObject(LVAddress LowerAddress, LVAddress UpperAddress) {
248bdd1243dSDimitry Andric // Pack the ranges into a Location object.
24906c3fb27SDimitry Andric LVLocation *Location = getReader().createLocation();
250bdd1243dSDimitry Andric Location->setLowerAddress(LowerAddress);
251bdd1243dSDimitry Andric Location->setUpperAddress(UpperAddress);
252bdd1243dSDimitry Andric Location->setIsAddressRange();
253bdd1243dSDimitry Andric
254bdd1243dSDimitry Andric addObject(Location);
255bdd1243dSDimitry Andric }
256bdd1243dSDimitry Andric
removeElement(LVElement * Element)257bdd1243dSDimitry Andric bool LVScope::removeElement(LVElement *Element) {
258bdd1243dSDimitry Andric auto Predicate = [Element](LVElement *Item) -> bool {
259bdd1243dSDimitry Andric return Item == Element;
260bdd1243dSDimitry Andric };
261bdd1243dSDimitry Andric auto RemoveElement = [Element, Predicate](auto &Container) -> bool {
262bdd1243dSDimitry Andric auto Iter = std::remove_if(Container->begin(), Container->end(), Predicate);
263bdd1243dSDimitry Andric if (Iter != Container->end()) {
264bdd1243dSDimitry Andric Container->erase(Iter, Container->end());
265bdd1243dSDimitry Andric Element->resetParent();
266bdd1243dSDimitry Andric return true;
267bdd1243dSDimitry Andric }
268bdd1243dSDimitry Andric return false;
269bdd1243dSDimitry Andric };
270bdd1243dSDimitry Andric
271bdd1243dSDimitry Andric // As 'children' contains only (scopes, symbols and types), check if the
272bdd1243dSDimitry Andric // element we are deleting is a line.
273bdd1243dSDimitry Andric if (Element->getIsLine())
274bdd1243dSDimitry Andric return RemoveElement(Lines);
275bdd1243dSDimitry Andric
276bdd1243dSDimitry Andric if (RemoveElement(Children)) {
277bdd1243dSDimitry Andric if (Element->getIsSymbol())
278bdd1243dSDimitry Andric return RemoveElement(Symbols);
279bdd1243dSDimitry Andric if (Element->getIsType())
280bdd1243dSDimitry Andric return RemoveElement(Types);
281bdd1243dSDimitry Andric if (Element->getIsScope())
282bdd1243dSDimitry Andric return RemoveElement(Scopes);
283bdd1243dSDimitry Andric llvm_unreachable("Invalid element.");
284bdd1243dSDimitry Andric }
285bdd1243dSDimitry Andric
286bdd1243dSDimitry Andric return false;
287bdd1243dSDimitry Andric }
288bdd1243dSDimitry Andric
addMissingElements(LVScope * Reference)289bdd1243dSDimitry Andric void LVScope::addMissingElements(LVScope *Reference) {
290bdd1243dSDimitry Andric setAddedMissing();
291bdd1243dSDimitry Andric if (!Reference)
292bdd1243dSDimitry Andric return;
293bdd1243dSDimitry Andric
294bdd1243dSDimitry Andric // Get abstract symbols for the given scope reference.
295bdd1243dSDimitry Andric const LVSymbols *ReferenceSymbols = Reference->getSymbols();
296bdd1243dSDimitry Andric if (!ReferenceSymbols)
297bdd1243dSDimitry Andric return;
298bdd1243dSDimitry Andric
299bdd1243dSDimitry Andric LVSymbols References;
300bdd1243dSDimitry Andric References.append(ReferenceSymbols->begin(), ReferenceSymbols->end());
301bdd1243dSDimitry Andric
302bdd1243dSDimitry Andric // Erase abstract symbols already in this scope from the collection of
303bdd1243dSDimitry Andric // symbols in the referenced scope.
304bdd1243dSDimitry Andric if (getSymbols())
305bdd1243dSDimitry Andric for (const LVSymbol *Symbol : *getSymbols())
306bdd1243dSDimitry Andric if (Symbol->getHasReferenceAbstract())
307*5f757f3fSDimitry Andric llvm::erase(References, Symbol->getReference());
308bdd1243dSDimitry Andric
309bdd1243dSDimitry Andric // If we have elements left in 'References', those are the elements that
310bdd1243dSDimitry Andric // need to be inserted in the current scope.
311bdd1243dSDimitry Andric if (References.size()) {
312bdd1243dSDimitry Andric LLVM_DEBUG({
313bdd1243dSDimitry Andric dbgs() << "Insert Missing Inlined Elements\n"
314bdd1243dSDimitry Andric << "Offset = " << hexSquareString(getOffset()) << " "
315bdd1243dSDimitry Andric << "Abstract = " << hexSquareString(Reference->getOffset())
316bdd1243dSDimitry Andric << "\n";
317bdd1243dSDimitry Andric });
318bdd1243dSDimitry Andric for (LVSymbol *Reference : References) {
319bdd1243dSDimitry Andric LLVM_DEBUG({
320bdd1243dSDimitry Andric dbgs() << "Missing Offset = " << hexSquareString(Reference->getOffset())
321bdd1243dSDimitry Andric << "\n";
322bdd1243dSDimitry Andric });
323bdd1243dSDimitry Andric // We can't clone the abstract origin reference, as it contain extra
324bdd1243dSDimitry Andric // information that is incorrect for the element to be inserted.
325bdd1243dSDimitry Andric // As the symbol being added does not exist in the debug section,
326bdd1243dSDimitry Andric // use its parent scope offset, to indicate its DIE location.
32706c3fb27SDimitry Andric LVSymbol *Symbol = getReader().createSymbol();
328bdd1243dSDimitry Andric addElement(Symbol);
329bdd1243dSDimitry Andric Symbol->setOffset(getOffset());
330bdd1243dSDimitry Andric Symbol->setIsOptimized();
331bdd1243dSDimitry Andric Symbol->setReference(Reference);
332bdd1243dSDimitry Andric
333bdd1243dSDimitry Andric // The symbol can be a constant, parameter or variable.
334bdd1243dSDimitry Andric if (Reference->getIsConstant())
335bdd1243dSDimitry Andric Symbol->setIsConstant();
336bdd1243dSDimitry Andric else if (Reference->getIsParameter())
337bdd1243dSDimitry Andric Symbol->setIsParameter();
338bdd1243dSDimitry Andric else if (Reference->getIsVariable())
339bdd1243dSDimitry Andric Symbol->setIsVariable();
340bdd1243dSDimitry Andric else
341bdd1243dSDimitry Andric llvm_unreachable("Invalid symbol kind.");
342bdd1243dSDimitry Andric }
343bdd1243dSDimitry Andric }
344bdd1243dSDimitry Andric }
345bdd1243dSDimitry Andric
updateLevel(LVScope * Parent,bool Moved)346bdd1243dSDimitry Andric void LVScope::updateLevel(LVScope *Parent, bool Moved) {
347bdd1243dSDimitry Andric // Update the level for the element itself and all its children, using the
348bdd1243dSDimitry Andric // given scope parent as reference.
349bdd1243dSDimitry Andric setLevel(Parent->getLevel() + 1);
350bdd1243dSDimitry Andric
351bdd1243dSDimitry Andric // Update the children.
352bdd1243dSDimitry Andric if (Children)
353bdd1243dSDimitry Andric for (LVElement *Element : *Children)
354bdd1243dSDimitry Andric Element->updateLevel(this, Moved);
355bdd1243dSDimitry Andric
356bdd1243dSDimitry Andric // Update any lines.
357bdd1243dSDimitry Andric if (Lines)
358bdd1243dSDimitry Andric for (LVLine *Line : *Lines)
359bdd1243dSDimitry Andric Line->updateLevel(this, Moved);
360bdd1243dSDimitry Andric }
361bdd1243dSDimitry Andric
resolve()362bdd1243dSDimitry Andric void LVScope::resolve() {
363bdd1243dSDimitry Andric if (getIsResolved())
364bdd1243dSDimitry Andric return;
365bdd1243dSDimitry Andric
366bdd1243dSDimitry Andric // Resolve the element itself.
367bdd1243dSDimitry Andric LVElement::resolve();
368bdd1243dSDimitry Andric
369bdd1243dSDimitry Andric // Resolve the children.
370bdd1243dSDimitry Andric if (Children)
371bdd1243dSDimitry Andric for (LVElement *Element : *Children) {
372bdd1243dSDimitry Andric if (getIsGlobalReference())
373bdd1243dSDimitry Andric // If the scope is a global reference, mark all its children as well.
374bdd1243dSDimitry Andric Element->setIsGlobalReference();
375bdd1243dSDimitry Andric Element->resolve();
376bdd1243dSDimitry Andric }
377bdd1243dSDimitry Andric }
378bdd1243dSDimitry Andric
resolveName()379bdd1243dSDimitry Andric void LVScope::resolveName() {
380bdd1243dSDimitry Andric if (getIsResolvedName())
381bdd1243dSDimitry Andric return;
382bdd1243dSDimitry Andric setIsResolvedName();
383bdd1243dSDimitry Andric
384bdd1243dSDimitry Andric // If the scope is a template, resolve the template parameters and get
385bdd1243dSDimitry Andric // the name for the template with the encoded arguments.
386bdd1243dSDimitry Andric if (getIsTemplate())
387bdd1243dSDimitry Andric resolveTemplate();
388bdd1243dSDimitry Andric else {
389bdd1243dSDimitry Andric if (LVElement *BaseType = getType()) {
390bdd1243dSDimitry Andric BaseType->resolveName();
391bdd1243dSDimitry Andric resolveFullname(BaseType);
392bdd1243dSDimitry Andric }
393bdd1243dSDimitry Andric }
394bdd1243dSDimitry Andric
395bdd1243dSDimitry Andric // In the case of unnamed scopes, try to generate a name for it, using
396bdd1243dSDimitry Andric // the parents name and the line information. In the case of compiler
397bdd1243dSDimitry Andric // generated functions, use its linkage name if is available.
398bdd1243dSDimitry Andric if (!isNamed()) {
399bdd1243dSDimitry Andric if (getIsArtificial())
400bdd1243dSDimitry Andric setName(getLinkageName());
401bdd1243dSDimitry Andric else
402bdd1243dSDimitry Andric generateName();
403bdd1243dSDimitry Andric }
404bdd1243dSDimitry Andric
405bdd1243dSDimitry Andric LVElement::resolveName();
406bdd1243dSDimitry Andric
407bdd1243dSDimitry Andric // Resolve any given pattern.
408bdd1243dSDimitry Andric patterns().resolvePatternMatch(this);
409bdd1243dSDimitry Andric }
410bdd1243dSDimitry Andric
resolveReferences()411bdd1243dSDimitry Andric void LVScope::resolveReferences() {
412bdd1243dSDimitry Andric // The scopes can have the following references to other elements:
413bdd1243dSDimitry Andric // A type:
414bdd1243dSDimitry Andric // DW_AT_type -> Type or Scope
415bdd1243dSDimitry Andric // DW_AT_import -> Type
416bdd1243dSDimitry Andric // A Reference:
417bdd1243dSDimitry Andric // DW_AT_specification -> Scope
418bdd1243dSDimitry Andric // DW_AT_abstract_origin -> Scope
419bdd1243dSDimitry Andric // DW_AT_extension -> Scope
420bdd1243dSDimitry Andric
421bdd1243dSDimitry Andric // Resolve any referenced scope.
422bdd1243dSDimitry Andric LVScope *Reference = getReference();
423bdd1243dSDimitry Andric if (Reference) {
424bdd1243dSDimitry Andric Reference->resolve();
425bdd1243dSDimitry Andric // Recursively resolve the scope names.
426bdd1243dSDimitry Andric resolveReferencesChain();
427bdd1243dSDimitry Andric }
428bdd1243dSDimitry Andric
429bdd1243dSDimitry Andric // Set the file/line information using the Debug Information entry.
430bdd1243dSDimitry Andric setFile(Reference);
431bdd1243dSDimitry Andric
432bdd1243dSDimitry Andric // Resolve any referenced type or scope.
433bdd1243dSDimitry Andric if (LVElement *Element = getType())
434bdd1243dSDimitry Andric Element->resolve();
435bdd1243dSDimitry Andric }
436bdd1243dSDimitry Andric
resolveElements()437bdd1243dSDimitry Andric void LVScope::resolveElements() {
438bdd1243dSDimitry Andric // The current element represents the Root. Traverse each Compile Unit.
439bdd1243dSDimitry Andric if (!Scopes)
440bdd1243dSDimitry Andric return;
441bdd1243dSDimitry Andric
442bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes) {
443bdd1243dSDimitry Andric LVScopeCompileUnit *CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
444bdd1243dSDimitry Andric getReader().setCompileUnit(CompileUnit);
445bdd1243dSDimitry Andric CompileUnit->resolve();
446bdd1243dSDimitry Andric // Propagate any matching information into the scopes tree.
447bdd1243dSDimitry Andric CompileUnit->propagatePatternMatch();
448bdd1243dSDimitry Andric }
449bdd1243dSDimitry Andric }
450bdd1243dSDimitry Andric
resolveReferencesChain()451bdd1243dSDimitry Andric StringRef LVScope::resolveReferencesChain() {
452bdd1243dSDimitry Andric // If the scope has a DW_AT_specification or DW_AT_abstract_origin,
453bdd1243dSDimitry Andric // follow the chain to resolve the name from those references.
454bdd1243dSDimitry Andric if (getHasReference() && !isNamed())
455bdd1243dSDimitry Andric setName(getReference()->resolveReferencesChain());
456bdd1243dSDimitry Andric
457bdd1243dSDimitry Andric return getName();
458bdd1243dSDimitry Andric }
459bdd1243dSDimitry Andric
460bdd1243dSDimitry Andric // Get template parameter types.
getTemplateParameterTypes(LVTypes & Params)461bdd1243dSDimitry Andric bool LVScope::getTemplateParameterTypes(LVTypes &Params) {
462bdd1243dSDimitry Andric // Traverse the scope types and populate the given container with those
463bdd1243dSDimitry Andric // types that are template parameters; that container will be used by
464bdd1243dSDimitry Andric // 'encodeTemplateArguments' to resolve them.
465bdd1243dSDimitry Andric if (const LVTypes *Types = getTypes())
466bdd1243dSDimitry Andric for (LVType *Type : *Types)
467bdd1243dSDimitry Andric if (Type->getIsTemplateParam()) {
468bdd1243dSDimitry Andric Type->resolve();
469bdd1243dSDimitry Andric Params.push_back(Type);
470bdd1243dSDimitry Andric }
471bdd1243dSDimitry Andric
472bdd1243dSDimitry Andric return !Params.empty();
473bdd1243dSDimitry Andric }
474bdd1243dSDimitry Andric
475bdd1243dSDimitry Andric // Resolve the template parameters/arguments relationship.
resolveTemplate()476bdd1243dSDimitry Andric void LVScope::resolveTemplate() {
477bdd1243dSDimitry Andric if (getIsTemplateResolved())
478bdd1243dSDimitry Andric return;
479bdd1243dSDimitry Andric setIsTemplateResolved();
480bdd1243dSDimitry Andric
481bdd1243dSDimitry Andric // Check if we need to encode the template arguments.
482bdd1243dSDimitry Andric if (options().getAttributeEncoded()) {
483bdd1243dSDimitry Andric LVTypes Params;
484bdd1243dSDimitry Andric if (getTemplateParameterTypes(Params)) {
485bdd1243dSDimitry Andric std::string EncodedArgs;
486bdd1243dSDimitry Andric // Encode the arguments as part of the template name and update the
487bdd1243dSDimitry Andric // template name, to reflect the encoded parameters.
488bdd1243dSDimitry Andric encodeTemplateArguments(EncodedArgs, &Params);
489bdd1243dSDimitry Andric setEncodedArgs(EncodedArgs);
490bdd1243dSDimitry Andric }
491bdd1243dSDimitry Andric }
492bdd1243dSDimitry Andric }
493bdd1243dSDimitry Andric
494bdd1243dSDimitry Andric // Get the qualified name for the template.
getQualifiedName(std::string & QualifiedName) const495bdd1243dSDimitry Andric void LVScope::getQualifiedName(std::string &QualifiedName) const {
496bdd1243dSDimitry Andric if (getIsRoot() || getIsCompileUnit())
497bdd1243dSDimitry Andric return;
498bdd1243dSDimitry Andric
499bdd1243dSDimitry Andric if (LVScope *Parent = getParentScope())
500bdd1243dSDimitry Andric Parent->getQualifiedName(QualifiedName);
501bdd1243dSDimitry Andric if (!QualifiedName.empty())
502bdd1243dSDimitry Andric QualifiedName.append("::");
503bdd1243dSDimitry Andric QualifiedName.append(std::string(getName()));
504bdd1243dSDimitry Andric }
505bdd1243dSDimitry Andric
506bdd1243dSDimitry Andric // Encode the template arguments as part of the template name.
encodeTemplateArguments(std::string & Name) const507bdd1243dSDimitry Andric void LVScope::encodeTemplateArguments(std::string &Name) const {
508bdd1243dSDimitry Andric // Qualify only when we are expanding parameters that are template
509bdd1243dSDimitry Andric // instances; the debugger will assume the current scope symbol as
510bdd1243dSDimitry Andric // the qualifying tag for the symbol being generated, which gives:
511bdd1243dSDimitry Andric // namespace std {
512bdd1243dSDimitry Andric // ...
513bdd1243dSDimitry Andric // set<float,std::less<float>,std::allocator<float>>
514bdd1243dSDimitry Andric // ...
515bdd1243dSDimitry Andric // }
516bdd1243dSDimitry Andric // The 'set' symbol is assumed to have the qualified tag 'std'.
517bdd1243dSDimitry Andric
518bdd1243dSDimitry Andric // We are resolving a template parameter which is another template. If
519bdd1243dSDimitry Andric // it is already resolved, just get the qualified name and return.
520bdd1243dSDimitry Andric std::string BaseName;
521bdd1243dSDimitry Andric getQualifiedName(BaseName);
522bdd1243dSDimitry Andric if (getIsTemplateResolved())
523bdd1243dSDimitry Andric Name.append(BaseName);
524bdd1243dSDimitry Andric }
525bdd1243dSDimitry Andric
encodeTemplateArguments(std::string & Name,const LVTypes * Types) const526bdd1243dSDimitry Andric void LVScope::encodeTemplateArguments(std::string &Name,
527bdd1243dSDimitry Andric const LVTypes *Types) const {
528bdd1243dSDimitry Andric // The encoded string will start with the scope name.
529bdd1243dSDimitry Andric Name.append("<");
530bdd1243dSDimitry Andric
531bdd1243dSDimitry Andric // The list of types are the template parameters.
532bdd1243dSDimitry Andric if (Types) {
533bdd1243dSDimitry Andric bool AddComma = false;
534bdd1243dSDimitry Andric for (const LVType *Type : *Types) {
535bdd1243dSDimitry Andric if (AddComma)
536bdd1243dSDimitry Andric Name.append(", ");
537bdd1243dSDimitry Andric Type->encodeTemplateArgument(Name);
538bdd1243dSDimitry Andric AddComma = true;
539bdd1243dSDimitry Andric }
540bdd1243dSDimitry Andric }
541bdd1243dSDimitry Andric
542bdd1243dSDimitry Andric Name.append(">");
543bdd1243dSDimitry Andric }
544bdd1243dSDimitry Andric
resolvePrinting() const545bdd1243dSDimitry Andric bool LVScope::resolvePrinting() const {
546bdd1243dSDimitry Andric // The warnings collected during the scope creation as per compile unit.
547bdd1243dSDimitry Andric // If there is a request for printing warnings, always print its associate
548bdd1243dSDimitry Andric // Compile Unit.
549bdd1243dSDimitry Andric if (options().getPrintWarnings() && (getIsRoot() || getIsCompileUnit()))
550bdd1243dSDimitry Andric return true;
551bdd1243dSDimitry Andric
552bdd1243dSDimitry Andric // In selection mode, always print the root scope regardless of the
553bdd1243dSDimitry Andric // number of matched elements. If no matches, the root by itself will
554bdd1243dSDimitry Andric // indicate no matches.
555bdd1243dSDimitry Andric if (options().getSelectExecute()) {
556bdd1243dSDimitry Andric return getIsRoot() || getIsCompileUnit() || getHasPattern();
557bdd1243dSDimitry Andric }
558bdd1243dSDimitry Andric
559bdd1243dSDimitry Andric bool Globals = options().getAttributeGlobal();
560bdd1243dSDimitry Andric bool Locals = options().getAttributeLocal();
561bdd1243dSDimitry Andric if ((Globals && Locals) || (!Globals && !Locals)) {
562bdd1243dSDimitry Andric // Print both Global and Local.
563bdd1243dSDimitry Andric } else {
564bdd1243dSDimitry Andric // Check for Global or Local Objects.
565bdd1243dSDimitry Andric if ((Globals && !(getHasGlobals() || getIsGlobalReference())) ||
566bdd1243dSDimitry Andric (Locals && !(getHasLocals() || !getIsGlobalReference())))
567bdd1243dSDimitry Andric return false;
568bdd1243dSDimitry Andric }
569bdd1243dSDimitry Andric
570bdd1243dSDimitry Andric // For the case of functions, skip it if is compiler generated.
571bdd1243dSDimitry Andric if (getIsFunction() && getIsArtificial() &&
572bdd1243dSDimitry Andric !options().getAttributeGenerated())
573bdd1243dSDimitry Andric return false;
574bdd1243dSDimitry Andric
575bdd1243dSDimitry Andric return true;
576bdd1243dSDimitry Andric }
577bdd1243dSDimitry Andric
doPrint(bool Split,bool Match,bool Print,raw_ostream & OS,bool Full) const578bdd1243dSDimitry Andric Error LVScope::doPrint(bool Split, bool Match, bool Print, raw_ostream &OS,
579bdd1243dSDimitry Andric bool Full) const {
580bdd1243dSDimitry Andric // During a view output splitting, use the output stream created by the
581bdd1243dSDimitry Andric // split context, then switch to the reader output stream.
582bdd1243dSDimitry Andric raw_ostream *StreamSplit = &OS;
583bdd1243dSDimitry Andric
58406c3fb27SDimitry Andric // Ignore the CU generated by the VS toolchain, when compiling to PDB.
58506c3fb27SDimitry Andric if (getIsSystem() && !options().getAttributeSystem())
58606c3fb27SDimitry Andric return Error::success();
58706c3fb27SDimitry Andric
588bdd1243dSDimitry Andric // If 'Split', we use the scope name (CU name) as the ouput file; the
589bdd1243dSDimitry Andric // delimiters in the pathname, must be replaced by a normal character.
590bdd1243dSDimitry Andric if (getIsCompileUnit()) {
591bdd1243dSDimitry Andric getReader().setCompileUnit(const_cast<LVScope *>(this));
592bdd1243dSDimitry Andric if (Split) {
593bdd1243dSDimitry Andric std::string ScopeName(getName());
594bdd1243dSDimitry Andric if (std::error_code EC =
595bdd1243dSDimitry Andric getReaderSplitContext().open(ScopeName, ".txt", OS))
596bdd1243dSDimitry Andric return createStringError(EC, "Unable to create split output file %s",
597bdd1243dSDimitry Andric ScopeName.c_str());
598bdd1243dSDimitry Andric StreamSplit = static_cast<raw_ostream *>(&getReaderSplitContext().os());
599bdd1243dSDimitry Andric }
600bdd1243dSDimitry Andric }
601bdd1243dSDimitry Andric
602bdd1243dSDimitry Andric // Ignore discarded or stripped scopes (functions).
603bdd1243dSDimitry Andric bool DoPrint = (options().getAttributeDiscarded()) ? true : !getIsDiscarded();
604bdd1243dSDimitry Andric
605bdd1243dSDimitry Andric // If we are in compare mode, the only conditions are related to the
606bdd1243dSDimitry Andric // element being missing. In the case of elements comparison, we print the
607bdd1243dSDimitry Andric // augmented view, that includes added elements.
608bdd1243dSDimitry Andric // In print mode, we check other conditions, such as local, global, etc.
609bdd1243dSDimitry Andric if (DoPrint) {
610bdd1243dSDimitry Andric DoPrint =
611bdd1243dSDimitry Andric getIsInCompare() ? options().getReportExecute() : resolvePrinting();
612bdd1243dSDimitry Andric }
613bdd1243dSDimitry Andric
614bdd1243dSDimitry Andric // At this point we have checked for very specific options, to decide if the
615bdd1243dSDimitry Andric // element will be printed. Include the caller's test for element general
616bdd1243dSDimitry Andric // print.
617bdd1243dSDimitry Andric DoPrint = DoPrint && (Print || options().getOutputSplit());
618bdd1243dSDimitry Andric
619bdd1243dSDimitry Andric if (DoPrint) {
620bdd1243dSDimitry Andric // Print the element itself.
621bdd1243dSDimitry Andric print(*StreamSplit, Full);
622bdd1243dSDimitry Andric
623bdd1243dSDimitry Andric // Check if we have reached the requested lexical level specified in the
624bdd1243dSDimitry Andric // command line options. Input file is level zero and the CU is level 1.
625bdd1243dSDimitry Andric if ((getIsRoot() || options().getPrintAnyElement()) &&
626bdd1243dSDimitry Andric options().getPrintFormatting() &&
627bdd1243dSDimitry Andric getLevel() < options().getOutputLevel()) {
628bdd1243dSDimitry Andric // Print the children.
629bdd1243dSDimitry Andric if (Children)
630bdd1243dSDimitry Andric for (const LVElement *Element : *Children) {
631bdd1243dSDimitry Andric if (Match && !Element->getHasPattern())
632bdd1243dSDimitry Andric continue;
633bdd1243dSDimitry Andric if (Error Err =
634bdd1243dSDimitry Andric Element->doPrint(Split, Match, Print, *StreamSplit, Full))
635bdd1243dSDimitry Andric return Err;
636bdd1243dSDimitry Andric }
637bdd1243dSDimitry Andric
638bdd1243dSDimitry Andric // Print the line records.
639bdd1243dSDimitry Andric if (Lines)
640bdd1243dSDimitry Andric for (const LVLine *Line : *Lines) {
641bdd1243dSDimitry Andric if (Match && !Line->getHasPattern())
642bdd1243dSDimitry Andric continue;
643bdd1243dSDimitry Andric if (Error Err =
644bdd1243dSDimitry Andric Line->doPrint(Split, Match, Print, *StreamSplit, Full))
645bdd1243dSDimitry Andric return Err;
646bdd1243dSDimitry Andric }
647bdd1243dSDimitry Andric
648bdd1243dSDimitry Andric // Print the warnings.
649bdd1243dSDimitry Andric if (options().getPrintWarnings())
650bdd1243dSDimitry Andric printWarnings(*StreamSplit, Full);
651bdd1243dSDimitry Andric }
652bdd1243dSDimitry Andric }
653bdd1243dSDimitry Andric
654bdd1243dSDimitry Andric // Done printing the compile unit. Print any requested summary and
655bdd1243dSDimitry Andric // restore the original output context.
656bdd1243dSDimitry Andric if (getIsCompileUnit()) {
657bdd1243dSDimitry Andric if (options().getPrintSummary())
658bdd1243dSDimitry Andric printSummary(*StreamSplit);
659bdd1243dSDimitry Andric if (options().getPrintSizes())
660bdd1243dSDimitry Andric printSizes(*StreamSplit);
661bdd1243dSDimitry Andric if (Split) {
662bdd1243dSDimitry Andric getReaderSplitContext().close();
663bdd1243dSDimitry Andric StreamSplit = &getReader().outputStream();
664bdd1243dSDimitry Andric }
665bdd1243dSDimitry Andric }
666bdd1243dSDimitry Andric
667bdd1243dSDimitry Andric if (getIsRoot() && options().getPrintWarnings()) {
668bdd1243dSDimitry Andric getReader().printRecords(*StreamSplit);
669bdd1243dSDimitry Andric }
670bdd1243dSDimitry Andric
671bdd1243dSDimitry Andric return Error::success();
672bdd1243dSDimitry Andric }
673bdd1243dSDimitry Andric
sort()674bdd1243dSDimitry Andric void LVScope::sort() {
675bdd1243dSDimitry Andric // Preserve the lines order as they are associated with user code.
676bdd1243dSDimitry Andric LVSortFunction SortFunction = getSortFunction();
677bdd1243dSDimitry Andric if (SortFunction) {
678bdd1243dSDimitry Andric std::function<void(LVScope * Parent, LVSortFunction SortFunction)> Sort =
679bdd1243dSDimitry Andric [&](LVScope *Parent, LVSortFunction SortFunction) {
68006c3fb27SDimitry Andric auto Traverse = [&](auto &Set, LVSortFunction SortFunction) {
681bdd1243dSDimitry Andric if (Set)
682bdd1243dSDimitry Andric std::stable_sort(Set->begin(), Set->end(), SortFunction);
683bdd1243dSDimitry Andric };
684bdd1243dSDimitry Andric Traverse(Parent->Types, SortFunction);
685bdd1243dSDimitry Andric Traverse(Parent->Symbols, SortFunction);
686bdd1243dSDimitry Andric Traverse(Parent->Scopes, SortFunction);
687bdd1243dSDimitry Andric Traverse(Parent->Ranges, compareRange);
688bdd1243dSDimitry Andric Traverse(Parent->Children, SortFunction);
689bdd1243dSDimitry Andric
690bdd1243dSDimitry Andric if (Parent->Scopes)
691bdd1243dSDimitry Andric for (LVScope *Scope : *Parent->Scopes)
692bdd1243dSDimitry Andric Sort(Scope, SortFunction);
693bdd1243dSDimitry Andric };
694bdd1243dSDimitry Andric
695bdd1243dSDimitry Andric // Start traversing the scopes root and transform the element name.
696bdd1243dSDimitry Andric Sort(this, SortFunction);
697bdd1243dSDimitry Andric }
698bdd1243dSDimitry Andric }
699bdd1243dSDimitry Andric
traverseParents(LVScopeGetFunction GetFunction,LVScopeSetFunction SetFunction)700bdd1243dSDimitry Andric void LVScope::traverseParents(LVScopeGetFunction GetFunction,
701bdd1243dSDimitry Andric LVScopeSetFunction SetFunction) {
702bdd1243dSDimitry Andric // Traverse the parent tree.
703bdd1243dSDimitry Andric LVScope *Parent = this;
704bdd1243dSDimitry Andric while (Parent) {
705bdd1243dSDimitry Andric // Terminates if the 'SetFunction' has been already executed.
706bdd1243dSDimitry Andric if ((Parent->*GetFunction)())
707bdd1243dSDimitry Andric break;
708bdd1243dSDimitry Andric (Parent->*SetFunction)();
709bdd1243dSDimitry Andric Parent = Parent->getParentScope();
710bdd1243dSDimitry Andric }
711bdd1243dSDimitry Andric }
712bdd1243dSDimitry Andric
traverseParentsAndChildren(LVObjectGetFunction GetFunction,LVObjectSetFunction SetFunction)713bdd1243dSDimitry Andric void LVScope::traverseParentsAndChildren(LVObjectGetFunction GetFunction,
714bdd1243dSDimitry Andric LVObjectSetFunction SetFunction) {
715bdd1243dSDimitry Andric if (options().getReportParents()) {
716bdd1243dSDimitry Andric // First traverse the parent tree.
717bdd1243dSDimitry Andric LVScope *Parent = this;
718bdd1243dSDimitry Andric while (Parent) {
719bdd1243dSDimitry Andric // Terminates if the 'SetFunction' has been already executed.
720bdd1243dSDimitry Andric if ((Parent->*GetFunction)())
721bdd1243dSDimitry Andric break;
722bdd1243dSDimitry Andric (Parent->*SetFunction)();
723bdd1243dSDimitry Andric Parent = Parent->getParentScope();
724bdd1243dSDimitry Andric }
725bdd1243dSDimitry Andric }
726bdd1243dSDimitry Andric
727bdd1243dSDimitry Andric std::function<void(LVScope * Scope)> TraverseChildren = [&](LVScope *Scope) {
728bdd1243dSDimitry Andric auto Traverse = [&](const auto *Set) {
729bdd1243dSDimitry Andric if (Set)
730bdd1243dSDimitry Andric for (const auto &Entry : *Set)
731bdd1243dSDimitry Andric (Entry->*SetFunction)();
732bdd1243dSDimitry Andric };
733bdd1243dSDimitry Andric
734bdd1243dSDimitry Andric (Scope->*SetFunction)();
735bdd1243dSDimitry Andric
736bdd1243dSDimitry Andric Traverse(Scope->getTypes());
737bdd1243dSDimitry Andric Traverse(Scope->getSymbols());
738bdd1243dSDimitry Andric Traverse(Scope->getLines());
739bdd1243dSDimitry Andric
740bdd1243dSDimitry Andric if (const LVScopes *Scopes = Scope->getScopes())
741bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes)
742bdd1243dSDimitry Andric TraverseChildren(Scope);
743bdd1243dSDimitry Andric };
744bdd1243dSDimitry Andric
745bdd1243dSDimitry Andric if (options().getReportChildren())
746bdd1243dSDimitry Andric TraverseChildren(this);
747bdd1243dSDimitry Andric }
748bdd1243dSDimitry Andric
749bdd1243dSDimitry Andric // Traverse the symbol location ranges and for each range:
750bdd1243dSDimitry Andric // - Apply the 'ValidLocation' validation criteria.
751bdd1243dSDimitry Andric // - Add any failed range to the 'LocationList'.
752bdd1243dSDimitry Andric // - Calculate location coverage.
getLocations(LVLocations & LocationList,LVValidLocation ValidLocation,bool RecordInvalid)753bdd1243dSDimitry Andric void LVScope::getLocations(LVLocations &LocationList,
754bdd1243dSDimitry Andric LVValidLocation ValidLocation, bool RecordInvalid) {
755bdd1243dSDimitry Andric // Traverse scopes and symbols.
756bdd1243dSDimitry Andric if (Symbols)
757bdd1243dSDimitry Andric for (LVSymbol *Symbol : *Symbols)
758bdd1243dSDimitry Andric Symbol->getLocations(LocationList, ValidLocation, RecordInvalid);
759bdd1243dSDimitry Andric if (Scopes)
760bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes)
761bdd1243dSDimitry Andric Scope->getLocations(LocationList, ValidLocation, RecordInvalid);
762bdd1243dSDimitry Andric }
763bdd1243dSDimitry Andric
764bdd1243dSDimitry Andric // Traverse the scope ranges and for each range:
765bdd1243dSDimitry Andric // - Apply the 'ValidLocation' validation criteria.
766bdd1243dSDimitry Andric // - Add any failed range to the 'LocationList'.
767bdd1243dSDimitry Andric // - Calculate location coverage.
getRanges(LVLocations & LocationList,LVValidLocation ValidLocation,bool RecordInvalid)768bdd1243dSDimitry Andric void LVScope::getRanges(LVLocations &LocationList,
769bdd1243dSDimitry Andric LVValidLocation ValidLocation, bool RecordInvalid) {
770bdd1243dSDimitry Andric // Ignore discarded or stripped scopes (functions).
771bdd1243dSDimitry Andric if (getIsDiscarded())
772bdd1243dSDimitry Andric return;
773bdd1243dSDimitry Andric
774bdd1243dSDimitry Andric // Process the ranges for current scope.
775bdd1243dSDimitry Andric if (Ranges) {
776bdd1243dSDimitry Andric for (LVLocation *Location : *Ranges) {
777bdd1243dSDimitry Andric // Add the invalid location object.
778bdd1243dSDimitry Andric if (!(Location->*ValidLocation)() && RecordInvalid)
779bdd1243dSDimitry Andric LocationList.push_back(Location);
780bdd1243dSDimitry Andric }
781bdd1243dSDimitry Andric
782bdd1243dSDimitry Andric // Calculate coverage factor.
783bdd1243dSDimitry Andric calculateCoverage();
784bdd1243dSDimitry Andric }
785bdd1243dSDimitry Andric
786bdd1243dSDimitry Andric // Traverse the scopes.
787bdd1243dSDimitry Andric if (Scopes)
788bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes)
789bdd1243dSDimitry Andric Scope->getRanges(LocationList, ValidLocation, RecordInvalid);
790bdd1243dSDimitry Andric }
791bdd1243dSDimitry Andric
792bdd1243dSDimitry Andric // Get all the ranges associated with scopes.
getRanges(LVRange & RangeList)793bdd1243dSDimitry Andric void LVScope::getRanges(LVRange &RangeList) {
794bdd1243dSDimitry Andric // Ignore discarded or stripped scopes (functions).
795bdd1243dSDimitry Andric if (getIsDiscarded())
796bdd1243dSDimitry Andric return;
797bdd1243dSDimitry Andric
798bdd1243dSDimitry Andric if (Ranges)
799bdd1243dSDimitry Andric RangeList.addEntry(this);
800bdd1243dSDimitry Andric if (Scopes)
801bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes)
802bdd1243dSDimitry Andric Scope->getRanges(RangeList);
803bdd1243dSDimitry Andric }
804bdd1243dSDimitry Andric
outermostParent(LVAddress Address)805bdd1243dSDimitry Andric LVScope *LVScope::outermostParent(LVAddress Address) {
806bdd1243dSDimitry Andric LVScope *Parent = this;
807bdd1243dSDimitry Andric while (Parent) {
808bdd1243dSDimitry Andric const LVLocations *ParentRanges = Parent->getRanges();
809bdd1243dSDimitry Andric if (ParentRanges)
810bdd1243dSDimitry Andric for (const LVLocation *Location : *ParentRanges)
811bdd1243dSDimitry Andric if (Location->getLowerAddress() <= Address)
812bdd1243dSDimitry Andric return Parent;
813bdd1243dSDimitry Andric Parent = Parent->getParentScope();
814bdd1243dSDimitry Andric }
815bdd1243dSDimitry Andric return Parent;
816bdd1243dSDimitry Andric }
817bdd1243dSDimitry Andric
findIn(const LVScopes * Targets) const818bdd1243dSDimitry Andric LVScope *LVScope::findIn(const LVScopes *Targets) const {
819bdd1243dSDimitry Andric if (!Targets)
820bdd1243dSDimitry Andric return nullptr;
821bdd1243dSDimitry Andric
822bdd1243dSDimitry Andric // In the case of overloaded functions, sometimes the DWARF used to
823bdd1243dSDimitry Andric // describe them, does not give suficient information. Try to find a
824bdd1243dSDimitry Andric // perfect match or mark them as possible conflicts.
825bdd1243dSDimitry Andric LVScopes Candidates;
826bdd1243dSDimitry Andric for (LVScope *Target : *Targets)
827bdd1243dSDimitry Andric if (LVScope::equals(Target))
828bdd1243dSDimitry Andric Candidates.push_back(Target);
829bdd1243dSDimitry Andric
830bdd1243dSDimitry Andric LLVM_DEBUG({
831bdd1243dSDimitry Andric if (!Candidates.empty()) {
832bdd1243dSDimitry Andric dbgs() << "\n[LVScope::findIn]\n"
833bdd1243dSDimitry Andric << "Reference: "
834bdd1243dSDimitry Andric << "Offset = " << hexSquareString(getOffset()) << ", "
835bdd1243dSDimitry Andric << "Level = " << getLevel() << ", "
836bdd1243dSDimitry Andric << "Kind = " << formattedKind(kind()) << ", "
837bdd1243dSDimitry Andric << "Name = " << formattedName(getName()) << "\n";
838bdd1243dSDimitry Andric for (const LVScope *Candidate : Candidates)
839bdd1243dSDimitry Andric dbgs() << "Candidate: "
840bdd1243dSDimitry Andric << "Offset = " << hexSquareString(Candidate->getOffset()) << ", "
841bdd1243dSDimitry Andric << "Level = " << Candidate->getLevel() << ", "
842bdd1243dSDimitry Andric << "Kind = " << formattedKind(Candidate->kind()) << ", "
843bdd1243dSDimitry Andric << "Name = " << formattedName(Candidate->getName()) << "\n";
844bdd1243dSDimitry Andric }
845bdd1243dSDimitry Andric });
846bdd1243dSDimitry Andric
847bdd1243dSDimitry Andric if (!Candidates.empty())
848bdd1243dSDimitry Andric return (Candidates.size() == 1)
849bdd1243dSDimitry Andric ? (equals(Candidates[0]) ? Candidates[0] : nullptr)
850bdd1243dSDimitry Andric : findEqualScope(&Candidates);
851bdd1243dSDimitry Andric
852bdd1243dSDimitry Andric return nullptr;
853bdd1243dSDimitry Andric }
854bdd1243dSDimitry Andric
equalNumberOfChildren(const LVScope * Scope) const855bdd1243dSDimitry Andric bool LVScope::equalNumberOfChildren(const LVScope *Scope) const {
856bdd1243dSDimitry Andric // Same number of children. Take into account which elements are requested
857bdd1243dSDimitry Andric // to be included in the comparison.
858bdd1243dSDimitry Andric return !(
859bdd1243dSDimitry Andric (options().getCompareScopes() && scopeCount() != Scope->scopeCount()) ||
860bdd1243dSDimitry Andric (options().getCompareSymbols() &&
861bdd1243dSDimitry Andric symbolCount() != Scope->symbolCount()) ||
862bdd1243dSDimitry Andric (options().getCompareTypes() && typeCount() != Scope->typeCount()) ||
863bdd1243dSDimitry Andric (options().getCompareLines() && lineCount() != Scope->lineCount()));
864bdd1243dSDimitry Andric }
865bdd1243dSDimitry Andric
markMissingParents(const LVScope * Target,bool TraverseChildren)866bdd1243dSDimitry Andric void LVScope::markMissingParents(const LVScope *Target, bool TraverseChildren) {
86706c3fb27SDimitry Andric auto SetCompareState = [&](auto &Container) {
868bdd1243dSDimitry Andric if (Container)
869bdd1243dSDimitry Andric for (auto *Entry : *Container)
870bdd1243dSDimitry Andric Entry->setIsInCompare();
871bdd1243dSDimitry Andric };
872bdd1243dSDimitry Andric SetCompareState(Types);
873bdd1243dSDimitry Andric SetCompareState(Symbols);
874bdd1243dSDimitry Andric SetCompareState(Lines);
875bdd1243dSDimitry Andric SetCompareState(Scopes);
876bdd1243dSDimitry Andric
877bdd1243dSDimitry Andric // At this point, we are ready to start comparing the current scope, once
878bdd1243dSDimitry Andric // the compare bits have been set.
879bdd1243dSDimitry Andric if (options().getCompareTypes() && getTypes() && Target->getTypes())
880bdd1243dSDimitry Andric LVType::markMissingParents(getTypes(), Target->getTypes());
881bdd1243dSDimitry Andric if (options().getCompareSymbols() && getSymbols() && Target->getSymbols())
882bdd1243dSDimitry Andric LVSymbol::markMissingParents(getSymbols(), Target->getSymbols());
883bdd1243dSDimitry Andric if (options().getCompareLines() && getLines() && Target->getLines())
884bdd1243dSDimitry Andric LVLine::markMissingParents(getLines(), Target->getLines());
885bdd1243dSDimitry Andric if (getScopes() && Target->getScopes())
886bdd1243dSDimitry Andric LVScope::markMissingParents(getScopes(), Target->getScopes(),
887bdd1243dSDimitry Andric TraverseChildren);
888bdd1243dSDimitry Andric }
889bdd1243dSDimitry Andric
markMissingParents(const LVScopes * References,const LVScopes * Targets,bool TraverseChildren)890bdd1243dSDimitry Andric void LVScope::markMissingParents(const LVScopes *References,
891bdd1243dSDimitry Andric const LVScopes *Targets,
892bdd1243dSDimitry Andric bool TraverseChildren) {
893bdd1243dSDimitry Andric if (!(References && Targets))
894bdd1243dSDimitry Andric return;
895bdd1243dSDimitry Andric
896bdd1243dSDimitry Andric LLVM_DEBUG({
897bdd1243dSDimitry Andric dbgs() << "\n[LVScope::markMissingParents]\n";
898bdd1243dSDimitry Andric for (const LVScope *Reference : *References)
899bdd1243dSDimitry Andric dbgs() << "References: "
900bdd1243dSDimitry Andric << "Offset = " << hexSquareString(Reference->getOffset()) << ", "
901bdd1243dSDimitry Andric << "Level = " << Reference->getLevel() << ", "
902bdd1243dSDimitry Andric << "Kind = " << formattedKind(Reference->kind()) << ", "
903bdd1243dSDimitry Andric << "Name = " << formattedName(Reference->getName()) << "\n";
904bdd1243dSDimitry Andric for (const LVScope *Target : *Targets)
905bdd1243dSDimitry Andric dbgs() << "Targets : "
906bdd1243dSDimitry Andric << "Offset = " << hexSquareString(Target->getOffset()) << ", "
907bdd1243dSDimitry Andric << "Level = " << Target->getLevel() << ", "
908bdd1243dSDimitry Andric << "Kind = " << formattedKind(Target->kind()) << ", "
909bdd1243dSDimitry Andric << "Name = " << formattedName(Target->getName()) << "\n";
910bdd1243dSDimitry Andric });
911bdd1243dSDimitry Andric
912bdd1243dSDimitry Andric for (LVScope *Reference : *References) {
913bdd1243dSDimitry Andric // Don't process 'Block' scopes, as we can't identify them.
914bdd1243dSDimitry Andric if (Reference->getIsBlock() || Reference->getIsGeneratedName())
915bdd1243dSDimitry Andric continue;
916bdd1243dSDimitry Andric
917bdd1243dSDimitry Andric LLVM_DEBUG({
918bdd1243dSDimitry Andric dbgs() << "\nSearch Reference: "
919bdd1243dSDimitry Andric << "Offset = " << hexSquareString(Reference->getOffset()) << " "
920bdd1243dSDimitry Andric << "Name = " << formattedName(Reference->getName()) << "\n";
921bdd1243dSDimitry Andric });
922bdd1243dSDimitry Andric LVScope *Target = Reference->findIn(Targets);
923bdd1243dSDimitry Andric if (Target) {
924bdd1243dSDimitry Andric LLVM_DEBUG({
925bdd1243dSDimitry Andric dbgs() << "\nFound Target: "
926bdd1243dSDimitry Andric << "Offset = " << hexSquareString(Target->getOffset()) << " "
927bdd1243dSDimitry Andric << "Name = " << formattedName(Target->getName()) << "\n";
928bdd1243dSDimitry Andric });
929bdd1243dSDimitry Andric if (TraverseChildren)
930bdd1243dSDimitry Andric Reference->markMissingParents(Target, TraverseChildren);
931bdd1243dSDimitry Andric } else {
932bdd1243dSDimitry Andric LLVM_DEBUG({
933bdd1243dSDimitry Andric dbgs() << "Missing Reference: "
934bdd1243dSDimitry Andric << "Offset = " << hexSquareString(Reference->getOffset()) << " "
935bdd1243dSDimitry Andric << "Name = " << formattedName(Reference->getName()) << "\n";
936bdd1243dSDimitry Andric });
937bdd1243dSDimitry Andric Reference->markBranchAsMissing();
938bdd1243dSDimitry Andric }
939bdd1243dSDimitry Andric }
940bdd1243dSDimitry Andric }
941bdd1243dSDimitry Andric
equals(const LVScope * Scope) const942bdd1243dSDimitry Andric bool LVScope::equals(const LVScope *Scope) const {
943bdd1243dSDimitry Andric if (!LVElement::equals(Scope))
944bdd1243dSDimitry Andric return false;
945bdd1243dSDimitry Andric // For lexical scopes, check if their parents are the same.
946bdd1243dSDimitry Andric if (getIsLexicalBlock() && Scope->getIsLexicalBlock())
947bdd1243dSDimitry Andric return getParentScope()->equals(Scope->getParentScope());
948bdd1243dSDimitry Andric return true;
949bdd1243dSDimitry Andric }
950bdd1243dSDimitry Andric
findEqualScope(const LVScopes * Scopes) const951bdd1243dSDimitry Andric LVScope *LVScope::findEqualScope(const LVScopes *Scopes) const {
952bdd1243dSDimitry Andric assert(Scopes && "Scopes must not be nullptr");
953bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes)
954bdd1243dSDimitry Andric if (equals(Scope))
955bdd1243dSDimitry Andric return Scope;
956bdd1243dSDimitry Andric return nullptr;
957bdd1243dSDimitry Andric }
958bdd1243dSDimitry Andric
equals(const LVScopes * References,const LVScopes * Targets)959bdd1243dSDimitry Andric bool LVScope::equals(const LVScopes *References, const LVScopes *Targets) {
960bdd1243dSDimitry Andric if (!References && !Targets)
961bdd1243dSDimitry Andric return true;
962bdd1243dSDimitry Andric if (References && Targets && References->size() == Targets->size()) {
963bdd1243dSDimitry Andric for (const LVScope *Reference : *References)
964bdd1243dSDimitry Andric if (!Reference->findIn(Targets))
965bdd1243dSDimitry Andric return false;
966bdd1243dSDimitry Andric return true;
967bdd1243dSDimitry Andric }
968bdd1243dSDimitry Andric return false;
969bdd1243dSDimitry Andric }
970bdd1243dSDimitry Andric
report(LVComparePass Pass)971bdd1243dSDimitry Andric void LVScope::report(LVComparePass Pass) {
972bdd1243dSDimitry Andric getComparator().printItem(this, Pass);
973bdd1243dSDimitry Andric getComparator().push(this);
974bdd1243dSDimitry Andric if (Children)
975bdd1243dSDimitry Andric for (LVElement *Element : *Children)
976bdd1243dSDimitry Andric Element->report(Pass);
977bdd1243dSDimitry Andric
978bdd1243dSDimitry Andric if (Lines)
979bdd1243dSDimitry Andric for (LVLine *Line : *Lines)
980bdd1243dSDimitry Andric Line->report(Pass);
981bdd1243dSDimitry Andric getComparator().pop();
982bdd1243dSDimitry Andric }
983bdd1243dSDimitry Andric
printActiveRanges(raw_ostream & OS,bool Full) const984bdd1243dSDimitry Andric void LVScope::printActiveRanges(raw_ostream &OS, bool Full) const {
985bdd1243dSDimitry Andric if (options().getPrintFormatting() && options().getAttributeRange() &&
986bdd1243dSDimitry Andric Ranges) {
987bdd1243dSDimitry Andric for (const LVLocation *Location : *Ranges)
988bdd1243dSDimitry Andric Location->print(OS, Full);
989bdd1243dSDimitry Andric }
990bdd1243dSDimitry Andric }
991bdd1243dSDimitry Andric
printEncodedArgs(raw_ostream & OS,bool Full) const992bdd1243dSDimitry Andric void LVScope::printEncodedArgs(raw_ostream &OS, bool Full) const {
993bdd1243dSDimitry Andric if (options().getPrintFormatting() && options().getAttributeEncoded())
994bdd1243dSDimitry Andric printAttributes(OS, Full, "{Encoded} ", const_cast<LVScope *>(this),
995bdd1243dSDimitry Andric getEncodedArgs(), /*UseQuotes=*/false, /*PrintRef=*/false);
996bdd1243dSDimitry Andric }
997bdd1243dSDimitry Andric
print(raw_ostream & OS,bool Full) const998bdd1243dSDimitry Andric void LVScope::print(raw_ostream &OS, bool Full) const {
999bdd1243dSDimitry Andric if (getIncludeInPrint() && getReader().doPrintScope(this)) {
1000bdd1243dSDimitry Andric // For a summary (printed elements), do not count the scope root.
1001bdd1243dSDimitry Andric // For a summary (selected elements) do not count a compile unit.
1002bdd1243dSDimitry Andric if (!(getIsRoot() || (getIsCompileUnit() && options().getSelectExecute())))
1003bdd1243dSDimitry Andric getReaderCompileUnit()->incrementPrintedScopes();
1004bdd1243dSDimitry Andric LVElement::print(OS, Full);
1005bdd1243dSDimitry Andric printExtra(OS, Full);
1006bdd1243dSDimitry Andric }
1007bdd1243dSDimitry Andric }
1008bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1009bdd1243dSDimitry Andric void LVScope::printExtra(raw_ostream &OS, bool Full) const {
1010bdd1243dSDimitry Andric OS << formattedKind(kind());
1011bdd1243dSDimitry Andric // Do not print any type or name for a lexical block.
1012bdd1243dSDimitry Andric if (!getIsBlock()) {
1013bdd1243dSDimitry Andric OS << " " << formattedName(getName());
1014bdd1243dSDimitry Andric if (!getIsAggregate())
1015bdd1243dSDimitry Andric OS << " -> " << typeOffsetAsString()
1016bdd1243dSDimitry Andric << formattedNames(getTypeQualifiedName(), typeAsString());
1017bdd1243dSDimitry Andric }
1018bdd1243dSDimitry Andric OS << "\n";
1019bdd1243dSDimitry Andric
1020bdd1243dSDimitry Andric // Print any active ranges.
1021bdd1243dSDimitry Andric if (Full && getIsBlock())
1022bdd1243dSDimitry Andric printActiveRanges(OS, Full);
1023bdd1243dSDimitry Andric }
1024bdd1243dSDimitry Andric
1025bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1026bdd1243dSDimitry Andric // DWARF Union/Structure/Class.
1027bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1028bdd1243dSDimitry Andric bool LVScopeAggregate::equals(const LVScope *Scope) const {
1029bdd1243dSDimitry Andric if (!LVScope::equals(Scope))
1030bdd1243dSDimitry Andric return false;
1031bdd1243dSDimitry Andric
1032bdd1243dSDimitry Andric if (!equalNumberOfChildren(Scope))
1033bdd1243dSDimitry Andric return false;
1034bdd1243dSDimitry Andric
1035bdd1243dSDimitry Andric // Check if the parameters match in the case of templates.
1036bdd1243dSDimitry Andric if (!LVType::parametersMatch(getTypes(), Scope->getTypes()))
1037bdd1243dSDimitry Andric return false;
1038bdd1243dSDimitry Andric
1039bdd1243dSDimitry Andric if (!isNamed() && !Scope->isNamed())
1040bdd1243dSDimitry Andric // In the case of unnamed union/structure/class compare the file name.
1041bdd1243dSDimitry Andric if (getFilenameIndex() != Scope->getFilenameIndex())
1042bdd1243dSDimitry Andric return false;
1043bdd1243dSDimitry Andric
1044bdd1243dSDimitry Andric return true;
1045bdd1243dSDimitry Andric }
1046bdd1243dSDimitry Andric
findEqualScope(const LVScopes * Scopes) const1047bdd1243dSDimitry Andric LVScope *LVScopeAggregate::findEqualScope(const LVScopes *Scopes) const {
1048bdd1243dSDimitry Andric assert(Scopes && "Scopes must not be nullptr");
1049bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes)
1050bdd1243dSDimitry Andric if (equals(Scope))
1051bdd1243dSDimitry Andric return Scope;
1052bdd1243dSDimitry Andric return nullptr;
1053bdd1243dSDimitry Andric }
1054bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1055bdd1243dSDimitry Andric void LVScopeAggregate::printExtra(raw_ostream &OS, bool Full) const {
1056bdd1243dSDimitry Andric LVScope::printExtra(OS, Full);
1057bdd1243dSDimitry Andric if (Full) {
1058bdd1243dSDimitry Andric if (getIsTemplateResolved())
1059bdd1243dSDimitry Andric printEncodedArgs(OS, Full);
1060bdd1243dSDimitry Andric LVScope *Reference = getReference();
1061bdd1243dSDimitry Andric if (Reference)
1062bdd1243dSDimitry Andric Reference->printReference(OS, Full, const_cast<LVScopeAggregate *>(this));
1063bdd1243dSDimitry Andric }
1064bdd1243dSDimitry Andric }
1065bdd1243dSDimitry Andric
1066bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1067bdd1243dSDimitry Andric // DWARF Template alias.
1068bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1069bdd1243dSDimitry Andric bool LVScopeAlias::equals(const LVScope *Scope) const {
1070bdd1243dSDimitry Andric if (!LVScope::equals(Scope))
1071bdd1243dSDimitry Andric return false;
1072bdd1243dSDimitry Andric return equalNumberOfChildren(Scope);
1073bdd1243dSDimitry Andric }
1074bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1075bdd1243dSDimitry Andric void LVScopeAlias::printExtra(raw_ostream &OS, bool Full) const {
1076bdd1243dSDimitry Andric OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "
1077bdd1243dSDimitry Andric << typeOffsetAsString()
1078bdd1243dSDimitry Andric << formattedNames(getTypeQualifiedName(), typeAsString()) << "\n";
1079bdd1243dSDimitry Andric }
1080bdd1243dSDimitry Andric
1081bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1082bdd1243dSDimitry Andric // DWARF array (DW_TAG_array_type).
1083bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
resolveExtra()1084bdd1243dSDimitry Andric void LVScopeArray::resolveExtra() {
1085bdd1243dSDimitry Andric // If the scope is an array, resolve the subrange entries and get those
1086bdd1243dSDimitry Andric // values encoded and assigned to the scope type.
1087bdd1243dSDimitry Andric // Encode the array subrange entries as part of the name.
1088bdd1243dSDimitry Andric if (getIsArrayResolved())
1089bdd1243dSDimitry Andric return;
1090bdd1243dSDimitry Andric setIsArrayResolved();
1091bdd1243dSDimitry Andric
1092bdd1243dSDimitry Andric // There are 2 cases to represent the bounds information for an array:
1093bdd1243dSDimitry Andric // 1) DW_TAG_array_type
1094bdd1243dSDimitry Andric // DW_AT_type --> ref_type
1095bdd1243dSDimitry Andric // DW_TAG_subrange_type
1096bdd1243dSDimitry Andric // DW_AT_type --> ref_type (type of object)
1097bdd1243dSDimitry Andric // DW_AT_count --> value (number of elements in subrange)
1098bdd1243dSDimitry Andric
1099bdd1243dSDimitry Andric // 2) DW_TAG_array_type
1100bdd1243dSDimitry Andric // DW_AT_type --> ref_type
1101bdd1243dSDimitry Andric // DW_TAG_subrange_type
1102bdd1243dSDimitry Andric // DW_AT_lower_bound --> value
1103bdd1243dSDimitry Andric // DW_AT_upper_bound --> value
1104bdd1243dSDimitry Andric
1105bdd1243dSDimitry Andric // The idea is to represent the bounds as a string, depending on the format:
1106bdd1243dSDimitry Andric // 1) [count]
1107bdd1243dSDimitry Andric // 2) [lower][upper]
1108bdd1243dSDimitry Andric
1109bdd1243dSDimitry Andric // Traverse scope types, looking for those types that are subranges.
1110bdd1243dSDimitry Andric LVTypes Subranges;
1111bdd1243dSDimitry Andric if (const LVTypes *Types = getTypes())
1112bdd1243dSDimitry Andric for (LVType *Type : *Types)
1113bdd1243dSDimitry Andric if (Type->getIsSubrange()) {
1114bdd1243dSDimitry Andric Type->resolve();
1115bdd1243dSDimitry Andric Subranges.push_back(Type);
1116bdd1243dSDimitry Andric }
1117bdd1243dSDimitry Andric
1118bdd1243dSDimitry Andric // Use the subrange types to generate the high level name for the array.
1119bdd1243dSDimitry Andric // Check the type has been fully resolved.
1120bdd1243dSDimitry Andric if (LVElement *BaseType = getType()) {
1121bdd1243dSDimitry Andric BaseType->resolveName();
1122bdd1243dSDimitry Andric resolveFullname(BaseType);
1123bdd1243dSDimitry Andric }
1124bdd1243dSDimitry Andric
1125bdd1243dSDimitry Andric // In 'resolveFullname' a check is done for double spaces in the type name.
1126bdd1243dSDimitry Andric std::stringstream ArrayInfo;
1127bdd1243dSDimitry Andric if (ElementType)
1128bdd1243dSDimitry Andric ArrayInfo << getTypeName().str() << " ";
1129bdd1243dSDimitry Andric
1130bdd1243dSDimitry Andric for (const LVType *Type : Subranges) {
1131bdd1243dSDimitry Andric if (Type->getIsSubrangeCount())
1132bdd1243dSDimitry Andric // Check if we have DW_AT_count subrange style.
1133bdd1243dSDimitry Andric ArrayInfo << "[" << Type->getCount() << "]";
1134bdd1243dSDimitry Andric else {
1135bdd1243dSDimitry Andric // Get lower and upper subrange values.
1136bdd1243dSDimitry Andric unsigned LowerBound;
1137bdd1243dSDimitry Andric unsigned UpperBound;
1138bdd1243dSDimitry Andric std::tie(LowerBound, UpperBound) = Type->getBounds();
1139bdd1243dSDimitry Andric
1140bdd1243dSDimitry Andric // The representation depends on the bound values. If the lower value
1141bdd1243dSDimitry Andric // is zero, treat the pair as the elements count. Otherwise, just use
1142bdd1243dSDimitry Andric // the pair, as they are representing arrays in languages other than
1143bdd1243dSDimitry Andric // C/C++ and the lower limit is not zero.
1144bdd1243dSDimitry Andric if (LowerBound)
1145bdd1243dSDimitry Andric ArrayInfo << "[" << LowerBound << ".." << UpperBound << "]";
1146bdd1243dSDimitry Andric else
1147bdd1243dSDimitry Andric ArrayInfo << "[" << UpperBound + 1 << "]";
1148bdd1243dSDimitry Andric }
1149bdd1243dSDimitry Andric }
1150bdd1243dSDimitry Andric
1151bdd1243dSDimitry Andric // Update the scope name, to reflect the encoded subranges.
1152bdd1243dSDimitry Andric setName(ArrayInfo.str());
1153bdd1243dSDimitry Andric }
1154bdd1243dSDimitry Andric
equals(const LVScope * Scope) const1155bdd1243dSDimitry Andric bool LVScopeArray::equals(const LVScope *Scope) const {
1156bdd1243dSDimitry Andric if (!LVScope::equals(Scope))
1157bdd1243dSDimitry Andric return false;
1158bdd1243dSDimitry Andric
1159bdd1243dSDimitry Andric if (!equalNumberOfChildren(Scope))
1160bdd1243dSDimitry Andric return false;
1161bdd1243dSDimitry Andric
1162bdd1243dSDimitry Andric // Despite the arrays are encoded, to reflect the dimensions, we have to
1163bdd1243dSDimitry Andric // check the subranges, in order to determine if they are the same.
1164bdd1243dSDimitry Andric if (!LVType::equals(getTypes(), Scope->getTypes()))
1165bdd1243dSDimitry Andric return false;
1166bdd1243dSDimitry Andric
1167bdd1243dSDimitry Andric return true;
1168bdd1243dSDimitry Andric }
1169bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1170bdd1243dSDimitry Andric void LVScopeArray::printExtra(raw_ostream &OS, bool Full) const {
1171bdd1243dSDimitry Andric OS << formattedKind(kind()) << " " << typeOffsetAsString()
1172bdd1243dSDimitry Andric << formattedName(getName()) << "\n";
1173bdd1243dSDimitry Andric }
1174bdd1243dSDimitry Andric
1175bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1176bdd1243dSDimitry Andric // An object file (single or multiple CUs).
1177bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
addSize(LVScope * Scope,LVOffset Lower,LVOffset Upper)1178bdd1243dSDimitry Andric void LVScopeCompileUnit::addSize(LVScope *Scope, LVOffset Lower,
1179bdd1243dSDimitry Andric LVOffset Upper) {
1180bdd1243dSDimitry Andric LLVM_DEBUG({
1181bdd1243dSDimitry Andric dbgs() << format(
1182bdd1243dSDimitry Andric "CU [0x%08" PRIx64 "], Scope [0x%08" PRIx64 "], Range [0x%08" PRIx64
1183bdd1243dSDimitry Andric ":0x%08" PRIx64 "], Size = %" PRId64 "\n",
1184bdd1243dSDimitry Andric getOffset(), Scope->getOffset(), Lower, Upper, Upper - Lower);
1185bdd1243dSDimitry Andric });
1186bdd1243dSDimitry Andric
1187bdd1243dSDimitry Andric // There is no need to check for a previous entry, as we are traversing the
1188bdd1243dSDimitry Andric // debug information in sequential order.
1189bdd1243dSDimitry Andric LVOffset Size = Upper - Lower;
1190bdd1243dSDimitry Andric Sizes[Scope] = Size;
1191bdd1243dSDimitry Andric if (this == Scope)
1192bdd1243dSDimitry Andric // Record contribution size for the compilation unit.
1193bdd1243dSDimitry Andric CUContributionSize = Size;
1194bdd1243dSDimitry Andric }
1195bdd1243dSDimitry Andric
1196bdd1243dSDimitry Andric // Update parents and children with pattern information.
propagatePatternMatch()1197bdd1243dSDimitry Andric void LVScopeCompileUnit::propagatePatternMatch() {
1198bdd1243dSDimitry Andric // At this stage, we have finished creating the Scopes tree and we have
1199bdd1243dSDimitry Andric // a list of elements that match the pattern specified in the command line.
1200bdd1243dSDimitry Andric // The pattern corresponds to a scope or element; mark parents and/or
1201bdd1243dSDimitry Andric // children as having that pattern, before any printing is done.
1202bdd1243dSDimitry Andric if (!options().getSelectExecute())
1203bdd1243dSDimitry Andric return;
1204bdd1243dSDimitry Andric
1205bdd1243dSDimitry Andric if (MatchedScopes.size()) {
1206bdd1243dSDimitry Andric for (LVScope *Scope : MatchedScopes)
1207bdd1243dSDimitry Andric Scope->traverseParentsAndChildren(&LVScope::getHasPattern,
1208bdd1243dSDimitry Andric &LVScope::setHasPattern);
1209bdd1243dSDimitry Andric } else {
1210bdd1243dSDimitry Andric // Mark the compile unit as having a pattern to enable any requests to
1211bdd1243dSDimitry Andric // print sizes and summary as that information is recorded at that level.
1212bdd1243dSDimitry Andric setHasPattern();
1213bdd1243dSDimitry Andric }
1214bdd1243dSDimitry Andric }
1215bdd1243dSDimitry Andric
processRangeLocationCoverage(LVValidLocation ValidLocation)1216bdd1243dSDimitry Andric void LVScopeCompileUnit::processRangeLocationCoverage(
1217bdd1243dSDimitry Andric LVValidLocation ValidLocation) {
1218bdd1243dSDimitry Andric if (options().getAttributeRange()) {
1219bdd1243dSDimitry Andric // Traverse the scopes to get scopes that have invalid ranges.
1220bdd1243dSDimitry Andric LVLocations Locations;
1221bdd1243dSDimitry Andric bool RecordInvalid = options().getWarningRanges();
1222bdd1243dSDimitry Andric getRanges(Locations, ValidLocation, RecordInvalid);
1223bdd1243dSDimitry Andric
1224bdd1243dSDimitry Andric // Validate ranges associated with scopes.
1225bdd1243dSDimitry Andric if (RecordInvalid)
1226bdd1243dSDimitry Andric for (LVLocation *Location : Locations)
1227bdd1243dSDimitry Andric addInvalidRange(Location);
1228bdd1243dSDimitry Andric }
1229bdd1243dSDimitry Andric
1230bdd1243dSDimitry Andric if (options().getAttributeLocation()) {
1231bdd1243dSDimitry Andric // Traverse the scopes to get locations that have invalid ranges.
1232bdd1243dSDimitry Andric LVLocations Locations;
1233bdd1243dSDimitry Andric bool RecordInvalid = options().getWarningLocations();
1234bdd1243dSDimitry Andric getLocations(Locations, ValidLocation, RecordInvalid);
1235bdd1243dSDimitry Andric
1236bdd1243dSDimitry Andric // Validate ranges associated with locations.
1237bdd1243dSDimitry Andric if (RecordInvalid)
1238bdd1243dSDimitry Andric for (LVLocation *Location : Locations)
1239bdd1243dSDimitry Andric addInvalidLocation(Location);
1240bdd1243dSDimitry Andric }
1241bdd1243dSDimitry Andric }
1242bdd1243dSDimitry Andric
addMapping(LVLine * Line,LVSectionIndex SectionIndex)1243bdd1243dSDimitry Andric void LVScopeCompileUnit::addMapping(LVLine *Line, LVSectionIndex SectionIndex) {
1244bdd1243dSDimitry Andric LVAddress Address = Line->getOffset();
1245bdd1243dSDimitry Andric SectionMappings.add(SectionIndex, Address, Line);
1246bdd1243dSDimitry Andric }
1247bdd1243dSDimitry Andric
lineLowerBound(LVAddress Address,LVScope * Scope) const1248bdd1243dSDimitry Andric LVLine *LVScopeCompileUnit::lineLowerBound(LVAddress Address,
1249bdd1243dSDimitry Andric LVScope *Scope) const {
1250bdd1243dSDimitry Andric LVSectionIndex SectionIndex = getReader().getSectionIndex(Scope);
1251bdd1243dSDimitry Andric LVAddressToLine *Map = SectionMappings.findMap(SectionIndex);
1252bdd1243dSDimitry Andric if (!Map || Map->empty())
1253bdd1243dSDimitry Andric return nullptr;
1254bdd1243dSDimitry Andric LVAddressToLine::const_iterator Iter = Map->lower_bound(Address);
1255bdd1243dSDimitry Andric return (Iter != Map->end()) ? Iter->second : nullptr;
1256bdd1243dSDimitry Andric }
1257bdd1243dSDimitry Andric
lineUpperBound(LVAddress Address,LVScope * Scope) const1258bdd1243dSDimitry Andric LVLine *LVScopeCompileUnit::lineUpperBound(LVAddress Address,
1259bdd1243dSDimitry Andric LVScope *Scope) const {
1260bdd1243dSDimitry Andric LVSectionIndex SectionIndex = getReader().getSectionIndex(Scope);
1261bdd1243dSDimitry Andric LVAddressToLine *Map = SectionMappings.findMap(SectionIndex);
1262bdd1243dSDimitry Andric if (!Map || Map->empty())
1263bdd1243dSDimitry Andric return nullptr;
1264bdd1243dSDimitry Andric LVAddressToLine::const_iterator Iter = Map->upper_bound(Address);
1265bdd1243dSDimitry Andric if (Iter != Map->begin())
1266bdd1243dSDimitry Andric Iter = std::prev(Iter);
1267bdd1243dSDimitry Andric return Iter->second;
1268bdd1243dSDimitry Andric }
1269bdd1243dSDimitry Andric
lineRange(LVLocation * Location) const1270bdd1243dSDimitry Andric LVLineRange LVScopeCompileUnit::lineRange(LVLocation *Location) const {
1271bdd1243dSDimitry Andric // The parent of a location can be a symbol or a scope.
1272bdd1243dSDimitry Andric LVElement *Element = Location->getParent();
1273bdd1243dSDimitry Andric LVScope *Parent = Element->getIsScope() ? static_cast<LVScope *>(Element)
1274bdd1243dSDimitry Andric : Element->getParentScope();
1275bdd1243dSDimitry Andric LVLine *LowLine = lineLowerBound(Location->getLowerAddress(), Parent);
1276bdd1243dSDimitry Andric LVLine *HighLine = lineUpperBound(Location->getUpperAddress(), Parent);
1277bdd1243dSDimitry Andric return LVLineRange(LowLine, HighLine);
1278bdd1243dSDimitry Andric }
1279bdd1243dSDimitry Andric
getFilename(size_t Index) const1280bdd1243dSDimitry Andric StringRef LVScopeCompileUnit::getFilename(size_t Index) const {
1281bdd1243dSDimitry Andric if (Index <= 0 || Index > Filenames.size())
1282bdd1243dSDimitry Andric return StringRef();
1283bdd1243dSDimitry Andric return getStringPool().getString(Filenames[Index - 1]);
1284bdd1243dSDimitry Andric }
1285bdd1243dSDimitry Andric
equals(const LVScope * Scope) const1286bdd1243dSDimitry Andric bool LVScopeCompileUnit::equals(const LVScope *Scope) const {
1287bdd1243dSDimitry Andric if (!LVScope::equals(Scope))
1288bdd1243dSDimitry Andric return false;
1289bdd1243dSDimitry Andric
1290bdd1243dSDimitry Andric return getNameIndex() == Scope->getNameIndex();
1291bdd1243dSDimitry Andric }
1292bdd1243dSDimitry Andric
incrementPrintedLines()1293bdd1243dSDimitry Andric void LVScopeCompileUnit::incrementPrintedLines() {
1294bdd1243dSDimitry Andric options().getSelectExecute() ? ++Found.Lines : ++Printed.Lines;
1295bdd1243dSDimitry Andric }
incrementPrintedScopes()1296bdd1243dSDimitry Andric void LVScopeCompileUnit::incrementPrintedScopes() {
1297bdd1243dSDimitry Andric options().getSelectExecute() ? ++Found.Scopes : ++Printed.Scopes;
1298bdd1243dSDimitry Andric }
incrementPrintedSymbols()1299bdd1243dSDimitry Andric void LVScopeCompileUnit::incrementPrintedSymbols() {
1300bdd1243dSDimitry Andric options().getSelectExecute() ? ++Found.Symbols : ++Printed.Symbols;
1301bdd1243dSDimitry Andric }
incrementPrintedTypes()1302bdd1243dSDimitry Andric void LVScopeCompileUnit::incrementPrintedTypes() {
1303bdd1243dSDimitry Andric options().getSelectExecute() ? ++Found.Types : ++Printed.Types;
1304bdd1243dSDimitry Andric }
1305bdd1243dSDimitry Andric
1306bdd1243dSDimitry Andric // Values are used by '--summary' option (allocated).
increment(LVLine * Line)1307bdd1243dSDimitry Andric void LVScopeCompileUnit::increment(LVLine *Line) {
1308bdd1243dSDimitry Andric if (Line->getIncludeInPrint())
1309bdd1243dSDimitry Andric ++Allocated.Lines;
1310bdd1243dSDimitry Andric }
increment(LVScope * Scope)1311bdd1243dSDimitry Andric void LVScopeCompileUnit::increment(LVScope *Scope) {
1312bdd1243dSDimitry Andric if (Scope->getIncludeInPrint())
1313bdd1243dSDimitry Andric ++Allocated.Scopes;
1314bdd1243dSDimitry Andric }
increment(LVSymbol * Symbol)1315bdd1243dSDimitry Andric void LVScopeCompileUnit::increment(LVSymbol *Symbol) {
1316bdd1243dSDimitry Andric if (Symbol->getIncludeInPrint())
1317bdd1243dSDimitry Andric ++Allocated.Symbols;
1318bdd1243dSDimitry Andric }
increment(LVType * Type)1319bdd1243dSDimitry Andric void LVScopeCompileUnit::increment(LVType *Type) {
1320bdd1243dSDimitry Andric if (Type->getIncludeInPrint())
1321bdd1243dSDimitry Andric ++Allocated.Types;
1322bdd1243dSDimitry Andric }
1323bdd1243dSDimitry Andric
1324bdd1243dSDimitry Andric // A new element has been added to the scopes tree. Take the following steps:
1325bdd1243dSDimitry Andric // Increase the added element counters, for printing summary.
1326bdd1243dSDimitry Andric // During comparison notify the Reader of the new element.
addedElement(LVLine * Line)1327bdd1243dSDimitry Andric void LVScopeCompileUnit::addedElement(LVLine *Line) {
1328bdd1243dSDimitry Andric increment(Line);
1329bdd1243dSDimitry Andric getReader().notifyAddedElement(Line);
1330bdd1243dSDimitry Andric }
addedElement(LVScope * Scope)1331bdd1243dSDimitry Andric void LVScopeCompileUnit::addedElement(LVScope *Scope) {
1332bdd1243dSDimitry Andric increment(Scope);
1333bdd1243dSDimitry Andric getReader().notifyAddedElement(Scope);
1334bdd1243dSDimitry Andric }
addedElement(LVSymbol * Symbol)1335bdd1243dSDimitry Andric void LVScopeCompileUnit::addedElement(LVSymbol *Symbol) {
1336bdd1243dSDimitry Andric increment(Symbol);
1337bdd1243dSDimitry Andric getReader().notifyAddedElement(Symbol);
1338bdd1243dSDimitry Andric }
addedElement(LVType * Type)1339bdd1243dSDimitry Andric void LVScopeCompileUnit::addedElement(LVType *Type) {
1340bdd1243dSDimitry Andric increment(Type);
1341bdd1243dSDimitry Andric getReader().notifyAddedElement(Type);
1342bdd1243dSDimitry Andric }
1343bdd1243dSDimitry Andric
1344bdd1243dSDimitry Andric // Record unsuported DWARF tags.
addDebugTag(dwarf::Tag Target,LVOffset Offset)1345bdd1243dSDimitry Andric void LVScopeCompileUnit::addDebugTag(dwarf::Tag Target, LVOffset Offset) {
134606c3fb27SDimitry Andric addItem<LVTagOffsetsMap, dwarf::Tag, LVOffset>(&DebugTags, Target, Offset);
1347bdd1243dSDimitry Andric }
1348bdd1243dSDimitry Andric
1349bdd1243dSDimitry Andric // Record elements with invalid offsets.
addInvalidOffset(LVOffset Offset,LVElement * Element)1350bdd1243dSDimitry Andric void LVScopeCompileUnit::addInvalidOffset(LVOffset Offset, LVElement *Element) {
1351bdd1243dSDimitry Andric if (WarningOffsets.find(Offset) == WarningOffsets.end())
1352bdd1243dSDimitry Andric WarningOffsets.emplace(Offset, Element);
1353bdd1243dSDimitry Andric }
1354bdd1243dSDimitry Andric
1355bdd1243dSDimitry Andric // Record symbols with invalid coverage values.
addInvalidCoverage(LVSymbol * Symbol)1356bdd1243dSDimitry Andric void LVScopeCompileUnit::addInvalidCoverage(LVSymbol *Symbol) {
1357bdd1243dSDimitry Andric LVOffset Offset = Symbol->getOffset();
1358bdd1243dSDimitry Andric if (InvalidCoverages.find(Offset) == InvalidCoverages.end())
1359bdd1243dSDimitry Andric InvalidCoverages.emplace(Offset, Symbol);
1360bdd1243dSDimitry Andric }
1361bdd1243dSDimitry Andric
1362bdd1243dSDimitry Andric // Record symbols with invalid locations.
addInvalidLocation(LVLocation * Location)1363bdd1243dSDimitry Andric void LVScopeCompileUnit::addInvalidLocation(LVLocation *Location) {
1364bdd1243dSDimitry Andric addInvalidLocationOrRange(Location, Location->getParentSymbol(),
1365bdd1243dSDimitry Andric &InvalidLocations);
1366bdd1243dSDimitry Andric }
1367bdd1243dSDimitry Andric
1368bdd1243dSDimitry Andric // Record scopes with invalid ranges.
addInvalidRange(LVLocation * Location)1369bdd1243dSDimitry Andric void LVScopeCompileUnit::addInvalidRange(LVLocation *Location) {
1370bdd1243dSDimitry Andric addInvalidLocationOrRange(Location, Location->getParentScope(),
1371bdd1243dSDimitry Andric &InvalidRanges);
1372bdd1243dSDimitry Andric }
1373bdd1243dSDimitry Andric
1374bdd1243dSDimitry Andric // Record line zero.
addLineZero(LVLine * Line)1375bdd1243dSDimitry Andric void LVScopeCompileUnit::addLineZero(LVLine *Line) {
1376bdd1243dSDimitry Andric LVScope *Scope = Line->getParentScope();
1377bdd1243dSDimitry Andric LVOffset Offset = Scope->getOffset();
1378bdd1243dSDimitry Andric addInvalidOffset(Offset, Scope);
137906c3fb27SDimitry Andric addItem<LVOffsetLinesMap, LVOffset, LVLine *>(&LinesZero, Offset, Line);
1380bdd1243dSDimitry Andric }
1381bdd1243dSDimitry Andric
printLocalNames(raw_ostream & OS,bool Full) const1382bdd1243dSDimitry Andric void LVScopeCompileUnit::printLocalNames(raw_ostream &OS, bool Full) const {
1383bdd1243dSDimitry Andric if (!options().getPrintFormatting())
1384bdd1243dSDimitry Andric return;
1385bdd1243dSDimitry Andric
1386bdd1243dSDimitry Andric // Calculate an indentation value, to preserve a nice layout.
1387bdd1243dSDimitry Andric size_t Indentation = options().indentationSize() +
1388bdd1243dSDimitry Andric lineNumberAsString().length() +
1389bdd1243dSDimitry Andric indentAsString(getLevel() + 1).length() + 3;
1390bdd1243dSDimitry Andric
1391bdd1243dSDimitry Andric enum class Option { Directory, File };
1392bdd1243dSDimitry Andric auto PrintNames = [&](Option Action) {
1393bdd1243dSDimitry Andric StringRef Kind = Action == Option::Directory ? "Directory" : "File";
1394bdd1243dSDimitry Andric std::set<std::string> UniqueNames;
1395bdd1243dSDimitry Andric for (size_t Index : Filenames) {
1396bdd1243dSDimitry Andric // In the case of missing directory name in the .debug_line table,
1397bdd1243dSDimitry Andric // the returned string has a leading '/'.
1398bdd1243dSDimitry Andric StringRef Name = getStringPool().getString(Index);
1399bdd1243dSDimitry Andric size_t Pos = Name.rfind('/');
1400bdd1243dSDimitry Andric if (Pos != std::string::npos)
1401bdd1243dSDimitry Andric Name = (Action == Option::File) ? Name.substr(Pos + 1)
1402bdd1243dSDimitry Andric : Name.substr(0, Pos);
1403bdd1243dSDimitry Andric // Collect only unique names.
1404bdd1243dSDimitry Andric UniqueNames.insert(std::string(Name));
1405bdd1243dSDimitry Andric }
1406bdd1243dSDimitry Andric for (const std::string &Name : UniqueNames)
1407bdd1243dSDimitry Andric OS << std::string(Indentation, ' ') << formattedKind(Kind) << " "
1408bdd1243dSDimitry Andric << formattedName(Name) << "\n";
1409bdd1243dSDimitry Andric };
1410bdd1243dSDimitry Andric
1411bdd1243dSDimitry Andric if (options().getAttributeDirectories())
1412bdd1243dSDimitry Andric PrintNames(Option::Directory);
1413bdd1243dSDimitry Andric if (options().getAttributeFiles())
1414bdd1243dSDimitry Andric PrintNames(Option::File);
1415bdd1243dSDimitry Andric if (options().getAttributePublics()) {
1416bdd1243dSDimitry Andric StringRef Kind = "Public";
1417bdd1243dSDimitry Andric // The public names are indexed by 'LVScope *'. We want to print
1418bdd1243dSDimitry Andric // them by logical element address, to show the scopes layout.
1419bdd1243dSDimitry Andric using OffsetSorted = std::map<LVAddress, LVPublicNames::const_iterator>;
1420bdd1243dSDimitry Andric OffsetSorted SortedNames;
1421bdd1243dSDimitry Andric for (LVPublicNames::const_iterator Iter = PublicNames.begin();
1422bdd1243dSDimitry Andric Iter != PublicNames.end(); ++Iter)
1423bdd1243dSDimitry Andric SortedNames.emplace(Iter->first->getOffset(), Iter);
1424bdd1243dSDimitry Andric
1425bdd1243dSDimitry Andric LVPublicNames::const_iterator Iter;
1426bdd1243dSDimitry Andric for (OffsetSorted::reference Entry : SortedNames) {
1427bdd1243dSDimitry Andric Iter = Entry.second;
1428bdd1243dSDimitry Andric OS << std::string(Indentation, ' ') << formattedKind(Kind) << " "
1429bdd1243dSDimitry Andric << formattedName((*Iter).first->getName());
1430bdd1243dSDimitry Andric if (options().getAttributeOffset()) {
1431bdd1243dSDimitry Andric LVAddress Address = (*Iter).second.first;
1432bdd1243dSDimitry Andric size_t Size = (*Iter).second.second;
1433bdd1243dSDimitry Andric OS << " [" << hexString(Address) << ":" << hexString(Address + Size)
1434bdd1243dSDimitry Andric << "]";
1435bdd1243dSDimitry Andric }
1436bdd1243dSDimitry Andric OS << "\n";
1437bdd1243dSDimitry Andric }
1438bdd1243dSDimitry Andric }
1439bdd1243dSDimitry Andric }
1440bdd1243dSDimitry Andric
printWarnings(raw_ostream & OS,bool Full) const1441bdd1243dSDimitry Andric void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const {
1442bdd1243dSDimitry Andric auto PrintHeader = [&](const char *Header) { OS << "\n" << Header << ":\n"; };
1443bdd1243dSDimitry Andric auto PrintFooter = [&](auto &Set) {
1444bdd1243dSDimitry Andric if (Set.empty())
1445bdd1243dSDimitry Andric OS << "None\n";
1446bdd1243dSDimitry Andric };
1447bdd1243dSDimitry Andric auto PrintOffset = [&](unsigned &Count, LVOffset Offset) {
1448bdd1243dSDimitry Andric if (Count == 5) {
1449bdd1243dSDimitry Andric Count = 0;
1450bdd1243dSDimitry Andric OS << "\n";
1451bdd1243dSDimitry Andric }
1452bdd1243dSDimitry Andric ++Count;
1453bdd1243dSDimitry Andric OS << hexSquareString(Offset) << " ";
1454bdd1243dSDimitry Andric };
1455bdd1243dSDimitry Andric auto PrintElement = [&](const LVOffsetElementMap &Map, LVOffset Offset) {
1456bdd1243dSDimitry Andric LVOffsetElementMap::const_iterator Iter = Map.find(Offset);
1457bdd1243dSDimitry Andric LVElement *Element = Iter != Map.end() ? Iter->second : nullptr;
1458bdd1243dSDimitry Andric OS << "[" << hexString(Offset) << "]";
1459bdd1243dSDimitry Andric if (Element)
1460bdd1243dSDimitry Andric OS << " " << formattedKind(Element->kind()) << " "
1461bdd1243dSDimitry Andric << formattedName(Element->getName());
1462bdd1243dSDimitry Andric OS << "\n";
1463bdd1243dSDimitry Andric };
1464bdd1243dSDimitry Andric auto PrintInvalidLocations = [&](const LVOffsetLocationsMap &Map,
1465bdd1243dSDimitry Andric const char *Header) {
1466bdd1243dSDimitry Andric PrintHeader(Header);
1467bdd1243dSDimitry Andric for (LVOffsetLocationsMap::const_reference Entry : Map) {
1468bdd1243dSDimitry Andric PrintElement(WarningOffsets, Entry.first);
146906c3fb27SDimitry Andric for (const LVLocation *Location : Entry.second)
1470bdd1243dSDimitry Andric OS << hexSquareString(Location->getOffset()) << " "
1471bdd1243dSDimitry Andric << Location->getIntervalInfo() << "\n";
1472bdd1243dSDimitry Andric }
1473bdd1243dSDimitry Andric PrintFooter(Map);
1474bdd1243dSDimitry Andric };
1475bdd1243dSDimitry Andric
1476bdd1243dSDimitry Andric if (options().getInternalTag() && getReader().isBinaryTypeELF()) {
1477bdd1243dSDimitry Andric PrintHeader("Unsupported DWARF Tags");
1478bdd1243dSDimitry Andric for (LVTagOffsetsMap::const_reference Entry : DebugTags) {
1479bdd1243dSDimitry Andric OS << format("\n0x%02x", (unsigned)Entry.first) << ", "
1480bdd1243dSDimitry Andric << dwarf::TagString(Entry.first) << "\n";
1481bdd1243dSDimitry Andric unsigned Count = 0;
148206c3fb27SDimitry Andric for (const LVOffset &Offset : Entry.second)
1483bdd1243dSDimitry Andric PrintOffset(Count, Offset);
1484bdd1243dSDimitry Andric OS << "\n";
1485bdd1243dSDimitry Andric }
1486bdd1243dSDimitry Andric PrintFooter(DebugTags);
1487bdd1243dSDimitry Andric }
1488bdd1243dSDimitry Andric
1489bdd1243dSDimitry Andric if (options().getWarningCoverages()) {
1490bdd1243dSDimitry Andric PrintHeader("Symbols Invalid Coverages");
1491bdd1243dSDimitry Andric for (LVOffsetSymbolMap::const_reference Entry : InvalidCoverages) {
1492bdd1243dSDimitry Andric // Symbol basic information.
1493bdd1243dSDimitry Andric LVSymbol *Symbol = Entry.second;
1494bdd1243dSDimitry Andric OS << hexSquareString(Entry.first) << " {Coverage} "
1495bdd1243dSDimitry Andric << format("%.2f%%", Symbol->getCoveragePercentage()) << " "
1496bdd1243dSDimitry Andric << formattedKind(Symbol->kind()) << " "
1497bdd1243dSDimitry Andric << formattedName(Symbol->getName()) << "\n";
1498bdd1243dSDimitry Andric }
1499bdd1243dSDimitry Andric PrintFooter(InvalidCoverages);
1500bdd1243dSDimitry Andric }
1501bdd1243dSDimitry Andric
1502bdd1243dSDimitry Andric if (options().getWarningLines()) {
1503bdd1243dSDimitry Andric PrintHeader("Lines Zero References");
1504bdd1243dSDimitry Andric for (LVOffsetLinesMap::const_reference Entry : LinesZero) {
1505bdd1243dSDimitry Andric PrintElement(WarningOffsets, Entry.first);
1506bdd1243dSDimitry Andric unsigned Count = 0;
150706c3fb27SDimitry Andric for (const LVLine *Line : Entry.second)
1508bdd1243dSDimitry Andric PrintOffset(Count, Line->getOffset());
1509bdd1243dSDimitry Andric OS << "\n";
1510bdd1243dSDimitry Andric }
1511bdd1243dSDimitry Andric PrintFooter(LinesZero);
1512bdd1243dSDimitry Andric }
1513bdd1243dSDimitry Andric
1514bdd1243dSDimitry Andric if (options().getWarningLocations())
1515bdd1243dSDimitry Andric PrintInvalidLocations(InvalidLocations, "Invalid Location Ranges");
1516bdd1243dSDimitry Andric
1517bdd1243dSDimitry Andric if (options().getWarningRanges())
1518bdd1243dSDimitry Andric PrintInvalidLocations(InvalidRanges, "Invalid Code Ranges");
1519bdd1243dSDimitry Andric }
1520bdd1243dSDimitry Andric
printTotals(raw_ostream & OS) const1521bdd1243dSDimitry Andric void LVScopeCompileUnit::printTotals(raw_ostream &OS) const {
1522bdd1243dSDimitry Andric OS << "\nTotals by lexical level:\n";
1523bdd1243dSDimitry Andric for (size_t Index = 1; Index <= MaxSeenLevel; ++Index)
1524bdd1243dSDimitry Andric OS << format("[%03d]: %10d (%6.2f%%)\n", Index, Totals[Index].first,
1525bdd1243dSDimitry Andric Totals[Index].second);
1526bdd1243dSDimitry Andric }
1527bdd1243dSDimitry Andric
printScopeSize(const LVScope * Scope,raw_ostream & OS)1528bdd1243dSDimitry Andric void LVScopeCompileUnit::printScopeSize(const LVScope *Scope, raw_ostream &OS) {
1529bdd1243dSDimitry Andric LVSizesMap::const_iterator Iter = Sizes.find(Scope);
1530bdd1243dSDimitry Andric if (Iter != Sizes.end()) {
1531bdd1243dSDimitry Andric LVOffset Size = Iter->second;
1532bdd1243dSDimitry Andric assert(CUContributionSize && "Invalid CU contribution size.");
1533bdd1243dSDimitry Andric // Get a percentage rounded to two decimal digits. This avoids
1534bdd1243dSDimitry Andric // implementation-defined rounding inside printing functions.
1535bdd1243dSDimitry Andric float Percentage =
1536bdd1243dSDimitry Andric rint((float(Size) / CUContributionSize) * 100.0 * 100.0) / 100.0;
1537bdd1243dSDimitry Andric OS << format("%10" PRId64 " (%6.2f%%) : ", Size, Percentage);
1538bdd1243dSDimitry Andric Scope->print(OS);
1539bdd1243dSDimitry Andric
1540bdd1243dSDimitry Andric // Keep record of the total sizes at each lexical level.
1541bdd1243dSDimitry Andric LVLevel Level = Scope->getLevel();
1542bdd1243dSDimitry Andric if (Level > MaxSeenLevel)
1543bdd1243dSDimitry Andric MaxSeenLevel = Level;
1544bdd1243dSDimitry Andric if (Level >= Totals.size())
1545bdd1243dSDimitry Andric Totals.resize(2 * Level);
1546bdd1243dSDimitry Andric Totals[Level].first += Size;
1547bdd1243dSDimitry Andric Totals[Level].second += Percentage;
1548bdd1243dSDimitry Andric }
1549bdd1243dSDimitry Andric }
1550bdd1243dSDimitry Andric
printSizes(raw_ostream & OS) const1551bdd1243dSDimitry Andric void LVScopeCompileUnit::printSizes(raw_ostream &OS) const {
1552bdd1243dSDimitry Andric // Recursively print the contributions for each scope.
1553bdd1243dSDimitry Andric std::function<void(const LVScope *Scope)> PrintScope =
1554bdd1243dSDimitry Andric [&](const LVScope *Scope) {
1555bdd1243dSDimitry Andric // If we have selection criteria, then use only the selected scopes.
1556bdd1243dSDimitry Andric if (options().getSelectExecute() && options().getReportAnyView()) {
1557bdd1243dSDimitry Andric for (const LVScope *Scope : MatchedScopes)
1558bdd1243dSDimitry Andric if (Scope->getLevel() < options().getOutputLevel())
1559bdd1243dSDimitry Andric printScopeSize(Scope, OS);
1560bdd1243dSDimitry Andric return;
1561bdd1243dSDimitry Andric }
1562bdd1243dSDimitry Andric if (Scope->getLevel() < options().getOutputLevel()) {
1563bdd1243dSDimitry Andric if (const LVScopes *Scopes = Scope->getScopes())
1564bdd1243dSDimitry Andric for (const LVScope *Scope : *Scopes) {
1565bdd1243dSDimitry Andric printScopeSize(Scope, OS);
1566bdd1243dSDimitry Andric PrintScope(Scope);
1567bdd1243dSDimitry Andric }
1568bdd1243dSDimitry Andric }
1569bdd1243dSDimitry Andric };
1570bdd1243dSDimitry Andric
1571bdd1243dSDimitry Andric bool PrintScopes = options().getPrintScopes();
1572bdd1243dSDimitry Andric if (!PrintScopes)
1573bdd1243dSDimitry Andric options().setPrintScopes();
1574bdd1243dSDimitry Andric getReader().setCompileUnit(const_cast<LVScopeCompileUnit *>(this));
1575bdd1243dSDimitry Andric
1576bdd1243dSDimitry Andric OS << "\nScope Sizes:\n";
1577bdd1243dSDimitry Andric options().resetPrintFormatting();
1578bdd1243dSDimitry Andric options().setPrintOffset();
1579bdd1243dSDimitry Andric
1580bdd1243dSDimitry Andric // Print the scopes regardless if the user has requested any scopes
1581bdd1243dSDimitry Andric // printing. Set the option just to allow printing the contributions.
1582bdd1243dSDimitry Andric printScopeSize(this, OS);
1583bdd1243dSDimitry Andric PrintScope(this);
1584bdd1243dSDimitry Andric
1585bdd1243dSDimitry Andric // Print total scope sizes by level.
1586bdd1243dSDimitry Andric printTotals(OS);
1587bdd1243dSDimitry Andric
1588bdd1243dSDimitry Andric options().resetPrintOffset();
1589bdd1243dSDimitry Andric options().setPrintFormatting();
1590bdd1243dSDimitry Andric
1591bdd1243dSDimitry Andric if (!PrintScopes)
1592bdd1243dSDimitry Andric options().resetPrintScopes();
1593bdd1243dSDimitry Andric }
1594bdd1243dSDimitry Andric
printSummary(raw_ostream & OS) const1595bdd1243dSDimitry Andric void LVScopeCompileUnit::printSummary(raw_ostream &OS) const {
1596bdd1243dSDimitry Andric printSummary(OS, options().getSelectExecute() ? Found : Printed, "Printed");
1597bdd1243dSDimitry Andric }
1598bdd1243dSDimitry Andric
1599bdd1243dSDimitry Andric // Print summary details for the scopes tree.
printSummary(raw_ostream & OS,const LVCounter & Counter,const char * Header) const1600bdd1243dSDimitry Andric void LVScopeCompileUnit::printSummary(raw_ostream &OS, const LVCounter &Counter,
1601bdd1243dSDimitry Andric const char *Header) const {
1602bdd1243dSDimitry Andric std::string Separator = std::string(29, '-');
1603bdd1243dSDimitry Andric auto PrintSeparator = [&]() { OS << Separator << "\n"; };
1604bdd1243dSDimitry Andric auto PrintHeadingRow = [&](const char *T, const char *U, const char *V) {
1605bdd1243dSDimitry Andric OS << format("%-9s%9s %9s\n", T, U, V);
1606bdd1243dSDimitry Andric };
1607bdd1243dSDimitry Andric auto PrintDataRow = [&](const char *T, unsigned U, unsigned V) {
1608bdd1243dSDimitry Andric OS << format("%-9s%9d %9d\n", T, U, V);
1609bdd1243dSDimitry Andric };
1610bdd1243dSDimitry Andric
1611bdd1243dSDimitry Andric OS << "\n";
1612bdd1243dSDimitry Andric PrintSeparator();
1613bdd1243dSDimitry Andric PrintHeadingRow("Element", "Total", Header);
1614bdd1243dSDimitry Andric PrintSeparator();
1615bdd1243dSDimitry Andric PrintDataRow("Scopes", Allocated.Scopes, Counter.Scopes);
1616bdd1243dSDimitry Andric PrintDataRow("Symbols", Allocated.Symbols, Counter.Symbols);
1617bdd1243dSDimitry Andric PrintDataRow("Types", Allocated.Types, Counter.Types);
1618bdd1243dSDimitry Andric PrintDataRow("Lines", Allocated.Lines, Counter.Lines);
1619bdd1243dSDimitry Andric PrintSeparator();
1620bdd1243dSDimitry Andric PrintDataRow(
1621bdd1243dSDimitry Andric "Total",
1622bdd1243dSDimitry Andric Allocated.Scopes + Allocated.Symbols + Allocated.Lines + Allocated.Types,
1623bdd1243dSDimitry Andric Counter.Scopes + Counter.Symbols + Counter.Lines + Counter.Types);
1624bdd1243dSDimitry Andric }
1625bdd1243dSDimitry Andric
printMatchedElements(raw_ostream & OS,bool UseMatchedElements)1626bdd1243dSDimitry Andric void LVScopeCompileUnit::printMatchedElements(raw_ostream &OS,
1627bdd1243dSDimitry Andric bool UseMatchedElements) {
1628bdd1243dSDimitry Andric LVSortFunction SortFunction = getSortFunction();
1629bdd1243dSDimitry Andric if (SortFunction)
1630bdd1243dSDimitry Andric std::stable_sort(MatchedElements.begin(), MatchedElements.end(),
1631bdd1243dSDimitry Andric SortFunction);
1632bdd1243dSDimitry Andric
1633bdd1243dSDimitry Andric // Check the type of elements required to be printed. 'MatchedElements'
1634bdd1243dSDimitry Andric // contains generic elements (lines, scopes, symbols, types). If we have a
1635bdd1243dSDimitry Andric // request to print any generic element, then allow the normal printing.
1636bdd1243dSDimitry Andric if (options().getPrintAnyElement()) {
1637bdd1243dSDimitry Andric if (UseMatchedElements)
1638bdd1243dSDimitry Andric OS << "\n";
1639bdd1243dSDimitry Andric print(OS);
1640bdd1243dSDimitry Andric
1641bdd1243dSDimitry Andric if (UseMatchedElements) {
1642bdd1243dSDimitry Andric // Print the details for the matched elements.
1643bdd1243dSDimitry Andric for (const LVElement *Element : MatchedElements)
1644bdd1243dSDimitry Andric Element->print(OS);
1645bdd1243dSDimitry Andric } else {
1646bdd1243dSDimitry Andric // Print the view for the matched scopes.
1647bdd1243dSDimitry Andric for (const LVScope *Scope : MatchedScopes) {
1648bdd1243dSDimitry Andric Scope->print(OS);
1649bdd1243dSDimitry Andric if (const LVElements *Elements = Scope->getChildren())
1650bdd1243dSDimitry Andric for (LVElement *Element : *Elements)
1651bdd1243dSDimitry Andric Element->print(OS);
1652bdd1243dSDimitry Andric }
1653bdd1243dSDimitry Andric }
1654bdd1243dSDimitry Andric
1655bdd1243dSDimitry Andric // Print any requested summary.
1656bdd1243dSDimitry Andric if (options().getPrintSummary()) {
1657bdd1243dSDimitry Andric // In the case of '--report=details' the matched elements are
1658bdd1243dSDimitry Andric // already counted; just proceed to print any requested summary.
1659bdd1243dSDimitry Andric // Otherwise, count them and print the summary.
1660bdd1243dSDimitry Andric if (!options().getReportList()) {
1661bdd1243dSDimitry Andric for (LVElement *Element : MatchedElements) {
1662bdd1243dSDimitry Andric if (!Element->getIncludeInPrint())
1663bdd1243dSDimitry Andric continue;
1664bdd1243dSDimitry Andric if (Element->getIsType())
1665bdd1243dSDimitry Andric ++Found.Types;
1666bdd1243dSDimitry Andric else if (Element->getIsSymbol())
1667bdd1243dSDimitry Andric ++Found.Symbols;
1668bdd1243dSDimitry Andric else if (Element->getIsScope())
1669bdd1243dSDimitry Andric ++Found.Scopes;
1670bdd1243dSDimitry Andric else if (Element->getIsLine())
1671bdd1243dSDimitry Andric ++Found.Lines;
1672bdd1243dSDimitry Andric else
1673bdd1243dSDimitry Andric assert(Element && "Invalid element.");
1674bdd1243dSDimitry Andric }
1675bdd1243dSDimitry Andric }
1676bdd1243dSDimitry Andric printSummary(OS, Found, "Printed");
1677bdd1243dSDimitry Andric }
1678bdd1243dSDimitry Andric }
1679bdd1243dSDimitry Andric
1680bdd1243dSDimitry Andric // Check if we have a request to print sizes for the matched elements
1681bdd1243dSDimitry Andric // that are scopes.
1682bdd1243dSDimitry Andric if (options().getPrintSizes()) {
1683bdd1243dSDimitry Andric OS << "\n";
1684bdd1243dSDimitry Andric print(OS);
1685bdd1243dSDimitry Andric
1686bdd1243dSDimitry Andric OS << "\nScope Sizes:\n";
1687bdd1243dSDimitry Andric printScopeSize(this, OS);
1688bdd1243dSDimitry Andric for (LVElement *Element : MatchedElements)
1689bdd1243dSDimitry Andric if (Element->getIsScope())
1690bdd1243dSDimitry Andric // Print sizes only for scopes.
1691bdd1243dSDimitry Andric printScopeSize(static_cast<LVScope *>(Element), OS);
1692bdd1243dSDimitry Andric
1693bdd1243dSDimitry Andric printTotals(OS);
1694bdd1243dSDimitry Andric }
1695bdd1243dSDimitry Andric }
1696bdd1243dSDimitry Andric
print(raw_ostream & OS,bool Full) const1697bdd1243dSDimitry Andric void LVScopeCompileUnit::print(raw_ostream &OS, bool Full) const {
1698bdd1243dSDimitry Andric // Reset counters for printed and found elements.
1699bdd1243dSDimitry Andric const_cast<LVScopeCompileUnit *>(this)->Found.reset();
1700bdd1243dSDimitry Andric const_cast<LVScopeCompileUnit *>(this)->Printed.reset();
1701bdd1243dSDimitry Andric
1702bdd1243dSDimitry Andric if (getReader().doPrintScope(this) && options().getPrintFormatting())
1703bdd1243dSDimitry Andric OS << "\n";
1704bdd1243dSDimitry Andric
1705bdd1243dSDimitry Andric LVScope::print(OS, Full);
1706bdd1243dSDimitry Andric }
1707bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1708bdd1243dSDimitry Andric void LVScopeCompileUnit::printExtra(raw_ostream &OS, bool Full) const {
1709bdd1243dSDimitry Andric OS << formattedKind(kind()) << " '" << getName() << "'\n";
1710bdd1243dSDimitry Andric if (options().getPrintFormatting() && options().getAttributeProducer())
1711bdd1243dSDimitry Andric printAttributes(OS, Full, "{Producer} ",
1712bdd1243dSDimitry Andric const_cast<LVScopeCompileUnit *>(this), getProducer(),
1713bdd1243dSDimitry Andric /*UseQuotes=*/true,
1714bdd1243dSDimitry Andric /*PrintRef=*/false);
1715bdd1243dSDimitry Andric
1716bdd1243dSDimitry Andric // Reset file index, to allow its children to print the correct filename.
1717bdd1243dSDimitry Andric options().resetFilenameIndex();
1718bdd1243dSDimitry Andric
1719bdd1243dSDimitry Andric // Print any files, directories, public names and active ranges.
1720bdd1243dSDimitry Andric if (Full) {
1721bdd1243dSDimitry Andric printLocalNames(OS, Full);
1722bdd1243dSDimitry Andric printActiveRanges(OS, Full);
1723bdd1243dSDimitry Andric }
1724bdd1243dSDimitry Andric }
1725bdd1243dSDimitry Andric
1726bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1727bdd1243dSDimitry Andric // DWARF enumeration (DW_TAG_enumeration_type).
1728bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1729bdd1243dSDimitry Andric bool LVScopeEnumeration::equals(const LVScope *Scope) const {
1730bdd1243dSDimitry Andric if (!LVScope::equals(Scope))
1731bdd1243dSDimitry Andric return false;
1732bdd1243dSDimitry Andric return equalNumberOfChildren(Scope);
1733bdd1243dSDimitry Andric }
1734bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1735bdd1243dSDimitry Andric void LVScopeEnumeration::printExtra(raw_ostream &OS, bool Full) const {
1736bdd1243dSDimitry Andric // Print the full type name.
1737bdd1243dSDimitry Andric OS << formattedKind(kind()) << " " << (getIsEnumClass() ? "class " : "")
1738bdd1243dSDimitry Andric << formattedName(getName());
1739bdd1243dSDimitry Andric if (getHasType())
1740bdd1243dSDimitry Andric OS << " -> " << typeOffsetAsString()
1741bdd1243dSDimitry Andric << formattedNames(getTypeQualifiedName(), typeAsString());
1742bdd1243dSDimitry Andric OS << "\n";
1743bdd1243dSDimitry Andric }
1744bdd1243dSDimitry Andric
1745bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1746bdd1243dSDimitry Andric // DWARF formal parameter pack (DW_TAG_GNU_formal_parameter_pack).
1747bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1748bdd1243dSDimitry Andric bool LVScopeFormalPack::equals(const LVScope *Scope) const {
1749bdd1243dSDimitry Andric if (!LVScope::equals(Scope))
1750bdd1243dSDimitry Andric return false;
1751bdd1243dSDimitry Andric return equalNumberOfChildren(Scope);
1752bdd1243dSDimitry Andric }
1753bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1754bdd1243dSDimitry Andric void LVScopeFormalPack::printExtra(raw_ostream &OS, bool Full) const {
1755bdd1243dSDimitry Andric OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
1756bdd1243dSDimitry Andric }
1757bdd1243dSDimitry Andric
1758bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1759bdd1243dSDimitry Andric // DWARF function.
1760bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
resolveReferences()1761bdd1243dSDimitry Andric void LVScopeFunction::resolveReferences() {
1762bdd1243dSDimitry Andric // Before we resolve any references to other elements, check if we have
1763bdd1243dSDimitry Andric // to insert missing elements, that have been stripped, which will help
1764bdd1243dSDimitry Andric // the logical view comparison.
1765bdd1243dSDimitry Andric if (options().getAttributeInserted() && getHasReferenceAbstract() &&
1766bdd1243dSDimitry Andric !getAddedMissing()) {
1767bdd1243dSDimitry Andric // Add missing elements at the function scope.
1768bdd1243dSDimitry Andric addMissingElements(getReference());
1769bdd1243dSDimitry Andric if (Scopes)
1770bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes)
1771bdd1243dSDimitry Andric if (Scope->getHasReferenceAbstract() && !Scope->getAddedMissing())
1772bdd1243dSDimitry Andric Scope->addMissingElements(Scope->getReference());
1773bdd1243dSDimitry Andric }
1774bdd1243dSDimitry Andric
1775bdd1243dSDimitry Andric LVScope::resolveReferences();
1776bdd1243dSDimitry Andric
1777bdd1243dSDimitry Andric // The DWARF 'extern' attribute is generated at the class level.
1778bdd1243dSDimitry Andric // 0000003f DW_TAG_class_type "CLASS"
1779bdd1243dSDimitry Andric // 00000048 DW_TAG_subprogram "bar"
1780bdd1243dSDimitry Andric // DW_AT_external DW_FORM_flag_present
1781bdd1243dSDimitry Andric // 00000070 DW_TAG_subprogram "bar"
1782bdd1243dSDimitry Andric // DW_AT_specification DW_FORM_ref4 0x00000048
178306c3fb27SDimitry Andric // CodeView does not include any information at the class level to
178406c3fb27SDimitry Andric // mark the member function as external.
1785bdd1243dSDimitry Andric // If there is a reference linking the declaration and definition, mark
1786bdd1243dSDimitry Andric // the definition as extern, to facilitate the logical view comparison.
1787bdd1243dSDimitry Andric if (getHasReferenceSpecification()) {
1788bdd1243dSDimitry Andric LVScope *Reference = getReference();
1789bdd1243dSDimitry Andric if (Reference && Reference->getIsExternal()) {
1790bdd1243dSDimitry Andric Reference->resetIsExternal();
1791bdd1243dSDimitry Andric setIsExternal();
1792bdd1243dSDimitry Andric }
1793bdd1243dSDimitry Andric }
1794bdd1243dSDimitry Andric
1795bdd1243dSDimitry Andric // Resolve the function associated type.
1796bdd1243dSDimitry Andric if (!getType())
1797bdd1243dSDimitry Andric if (LVScope *Reference = getReference())
1798bdd1243dSDimitry Andric setType(Reference->getType());
1799bdd1243dSDimitry Andric }
1800bdd1243dSDimitry Andric
setName(StringRef ObjectName)1801bdd1243dSDimitry Andric void LVScopeFunction::setName(StringRef ObjectName) {
1802bdd1243dSDimitry Andric LVScope::setName(ObjectName);
1803bdd1243dSDimitry Andric // Check for system generated functions.
1804bdd1243dSDimitry Andric getReader().isSystemEntry(this, ObjectName);
1805bdd1243dSDimitry Andric }
1806bdd1243dSDimitry Andric
resolveExtra()1807bdd1243dSDimitry Andric void LVScopeFunction::resolveExtra() {
1808bdd1243dSDimitry Andric // Check if we need to encode the template arguments.
1809bdd1243dSDimitry Andric if (getIsTemplate())
1810bdd1243dSDimitry Andric resolveTemplate();
1811bdd1243dSDimitry Andric }
1812bdd1243dSDimitry Andric
equals(const LVScope * Scope) const1813bdd1243dSDimitry Andric bool LVScopeFunction::equals(const LVScope *Scope) const {
1814bdd1243dSDimitry Andric if (!LVScope::equals(Scope))
1815bdd1243dSDimitry Andric return false;
1816bdd1243dSDimitry Andric
1817bdd1243dSDimitry Andric // When comparing logical elements, ignore any difference in the children.
1818bdd1243dSDimitry Andric if (options().getCompareContext() && !equalNumberOfChildren(Scope))
1819bdd1243dSDimitry Andric return false;
1820bdd1243dSDimitry Andric
1821bdd1243dSDimitry Andric // Check if the linkage name matches.
1822bdd1243dSDimitry Andric if (getLinkageNameIndex() != Scope->getLinkageNameIndex())
1823bdd1243dSDimitry Andric return false;
1824bdd1243dSDimitry Andric
1825bdd1243dSDimitry Andric // Check if the parameters match in the case of templates.
1826bdd1243dSDimitry Andric if (!LVType::parametersMatch(getTypes(), Scope->getTypes()))
1827bdd1243dSDimitry Andric return false;
1828bdd1243dSDimitry Andric
1829bdd1243dSDimitry Andric // Check if the arguments match.
1830bdd1243dSDimitry Andric if (!LVSymbol::parametersMatch(getSymbols(), Scope->getSymbols()))
1831bdd1243dSDimitry Andric return false;
1832bdd1243dSDimitry Andric
1833bdd1243dSDimitry Andric // Check if the lines match.
1834bdd1243dSDimitry Andric if (options().getCompareLines() &&
1835bdd1243dSDimitry Andric !LVLine::equals(getLines(), Scope->getLines()))
1836bdd1243dSDimitry Andric return false;
1837bdd1243dSDimitry Andric
1838bdd1243dSDimitry Andric // Check if any reference is the same.
1839bdd1243dSDimitry Andric if (!referenceMatch(Scope))
1840bdd1243dSDimitry Andric return false;
1841bdd1243dSDimitry Andric
1842bdd1243dSDimitry Andric if (getReference() && !getReference()->equals(Scope->getReference()))
1843bdd1243dSDimitry Andric return false;
1844bdd1243dSDimitry Andric
1845bdd1243dSDimitry Andric return true;
1846bdd1243dSDimitry Andric }
1847bdd1243dSDimitry Andric
findEqualScope(const LVScopes * Scopes) const1848bdd1243dSDimitry Andric LVScope *LVScopeFunction::findEqualScope(const LVScopes *Scopes) const {
1849bdd1243dSDimitry Andric assert(Scopes && "Scopes must not be nullptr");
1850bdd1243dSDimitry Andric // Go through candidates and try to find a best match.
1851bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes)
1852bdd1243dSDimitry Andric // Match arguments, children, lines, references.
1853bdd1243dSDimitry Andric if (equals(Scope))
1854bdd1243dSDimitry Andric return Scope;
1855bdd1243dSDimitry Andric return nullptr;
1856bdd1243dSDimitry Andric }
1857bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1858bdd1243dSDimitry Andric void LVScopeFunction::printExtra(raw_ostream &OS, bool Full) const {
1859bdd1243dSDimitry Andric LVScope *Reference = getReference();
1860bdd1243dSDimitry Andric
1861bdd1243dSDimitry Andric // Inline attributes based on the reference element.
1862bdd1243dSDimitry Andric uint32_t InlineCode =
1863bdd1243dSDimitry Andric Reference ? Reference->getInlineCode() : getInlineCode();
1864bdd1243dSDimitry Andric
1865bdd1243dSDimitry Andric // Accessibility depends on the parent (class, structure).
1866bdd1243dSDimitry Andric uint32_t AccessCode = 0;
1867bdd1243dSDimitry Andric if (getIsMember())
1868bdd1243dSDimitry Andric AccessCode = getParentScope()->getIsClass() ? dwarf::DW_ACCESS_private
1869bdd1243dSDimitry Andric : dwarf::DW_ACCESS_public;
1870bdd1243dSDimitry Andric
1871bdd1243dSDimitry Andric std::string Attributes =
1872bdd1243dSDimitry Andric getIsCallSite()
1873bdd1243dSDimitry Andric ? ""
1874bdd1243dSDimitry Andric : formatAttributes(externalString(), accessibilityString(AccessCode),
1875bdd1243dSDimitry Andric inlineCodeString(InlineCode), virtualityString());
1876bdd1243dSDimitry Andric
1877bdd1243dSDimitry Andric OS << formattedKind(kind()) << " " << Attributes << formattedName(getName())
1878bdd1243dSDimitry Andric << discriminatorAsString() << " -> " << typeOffsetAsString()
1879bdd1243dSDimitry Andric << formattedNames(getTypeQualifiedName(), typeAsString()) << "\n";
1880bdd1243dSDimitry Andric
1881bdd1243dSDimitry Andric // Print any active ranges.
1882bdd1243dSDimitry Andric if (Full) {
1883bdd1243dSDimitry Andric if (getIsTemplateResolved())
1884bdd1243dSDimitry Andric printEncodedArgs(OS, Full);
1885bdd1243dSDimitry Andric printActiveRanges(OS, Full);
1886bdd1243dSDimitry Andric if (getLinkageNameIndex())
1887bdd1243dSDimitry Andric printLinkageName(OS, Full, const_cast<LVScopeFunction *>(this),
1888bdd1243dSDimitry Andric const_cast<LVScopeFunction *>(this));
1889bdd1243dSDimitry Andric if (Reference)
1890bdd1243dSDimitry Andric Reference->printReference(OS, Full, const_cast<LVScopeFunction *>(this));
1891bdd1243dSDimitry Andric }
1892bdd1243dSDimitry Andric }
1893bdd1243dSDimitry Andric
1894bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1895bdd1243dSDimitry Andric // DWARF inlined function (DW_TAG_inlined_function).
1896bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
resolveExtra()1897bdd1243dSDimitry Andric void LVScopeFunctionInlined::resolveExtra() {
1898bdd1243dSDimitry Andric // Check if we need to encode the template arguments.
1899bdd1243dSDimitry Andric if (getIsTemplate())
1900bdd1243dSDimitry Andric resolveTemplate();
1901bdd1243dSDimitry Andric }
1902bdd1243dSDimitry Andric
equals(const LVScope * Scope) const1903bdd1243dSDimitry Andric bool LVScopeFunctionInlined::equals(const LVScope *Scope) const {
1904bdd1243dSDimitry Andric if (!LVScopeFunction::equals(Scope))
1905bdd1243dSDimitry Andric return false;
1906bdd1243dSDimitry Andric
1907bdd1243dSDimitry Andric // Check if any reference is the same.
1908bdd1243dSDimitry Andric if (getHasDiscriminator() && Scope->getHasDiscriminator())
1909bdd1243dSDimitry Andric if (getDiscriminator() != Scope->getDiscriminator())
1910bdd1243dSDimitry Andric return false;
1911bdd1243dSDimitry Andric
1912bdd1243dSDimitry Andric // Check the call site information.
1913bdd1243dSDimitry Andric if (getCallFilenameIndex() != Scope->getCallFilenameIndex() ||
1914bdd1243dSDimitry Andric getCallLineNumber() != Scope->getCallLineNumber())
1915bdd1243dSDimitry Andric return false;
1916bdd1243dSDimitry Andric
1917bdd1243dSDimitry Andric return true;
1918bdd1243dSDimitry Andric }
1919bdd1243dSDimitry Andric
findEqualScope(const LVScopes * Scopes) const1920bdd1243dSDimitry Andric LVScope *LVScopeFunctionInlined::findEqualScope(const LVScopes *Scopes) const {
1921bdd1243dSDimitry Andric return LVScopeFunction::findEqualScope(Scopes);
1922bdd1243dSDimitry Andric }
1923bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1924bdd1243dSDimitry Andric void LVScopeFunctionInlined::printExtra(raw_ostream &OS, bool Full) const {
1925bdd1243dSDimitry Andric LVScopeFunction::printExtra(OS, Full);
1926bdd1243dSDimitry Andric }
1927bdd1243dSDimitry Andric
1928bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1929bdd1243dSDimitry Andric // DWARF subroutine type.
1930bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1931bdd1243dSDimitry Andric // Resolve a Subroutine Type (Callback).
resolveExtra()1932bdd1243dSDimitry Andric void LVScopeFunctionType::resolveExtra() {
1933bdd1243dSDimitry Andric if (getIsMemberPointerResolved())
1934bdd1243dSDimitry Andric return;
1935bdd1243dSDimitry Andric setIsMemberPointerResolved();
1936bdd1243dSDimitry Andric
1937bdd1243dSDimitry Andric // The encoded string has the return type and the formal parameters type.
1938bdd1243dSDimitry Andric std::string Name(typeAsString());
1939bdd1243dSDimitry Andric Name.append(" (*)");
1940bdd1243dSDimitry Andric Name.append("(");
1941bdd1243dSDimitry Andric
1942bdd1243dSDimitry Andric // Traverse the scope symbols, looking for those which are parameters.
1943bdd1243dSDimitry Andric if (const LVSymbols *Symbols = getSymbols()) {
1944bdd1243dSDimitry Andric bool AddComma = false;
1945bdd1243dSDimitry Andric for (LVSymbol *Symbol : *Symbols)
1946bdd1243dSDimitry Andric if (Symbol->getIsParameter()) {
1947bdd1243dSDimitry Andric Symbol->resolve();
1948bdd1243dSDimitry Andric if (LVElement *Type = Symbol->getType())
1949bdd1243dSDimitry Andric Type->resolveName();
1950bdd1243dSDimitry Andric if (AddComma)
1951bdd1243dSDimitry Andric Name.append(", ");
1952bdd1243dSDimitry Andric Name.append(std::string(Symbol->getTypeName()));
1953bdd1243dSDimitry Andric AddComma = true;
1954bdd1243dSDimitry Andric }
1955bdd1243dSDimitry Andric }
1956bdd1243dSDimitry Andric
1957bdd1243dSDimitry Andric Name.append(")");
1958bdd1243dSDimitry Andric
1959bdd1243dSDimitry Andric // Update the scope name, to reflect the encoded parameters.
1960bdd1243dSDimitry Andric setName(Name);
1961bdd1243dSDimitry Andric }
1962bdd1243dSDimitry Andric
1963bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
1964bdd1243dSDimitry Andric // DWARF namespace (DW_TAG_namespace).
1965bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1966bdd1243dSDimitry Andric bool LVScopeNamespace::equals(const LVScope *Scope) const {
1967bdd1243dSDimitry Andric if (!LVScope::equals(Scope))
1968bdd1243dSDimitry Andric return false;
1969bdd1243dSDimitry Andric
1970bdd1243dSDimitry Andric if (!equalNumberOfChildren(Scope))
1971bdd1243dSDimitry Andric return false;
1972bdd1243dSDimitry Andric
1973bdd1243dSDimitry Andric // Check if any reference is the same.
1974bdd1243dSDimitry Andric if (!referenceMatch(Scope))
1975bdd1243dSDimitry Andric return false;
1976bdd1243dSDimitry Andric
1977bdd1243dSDimitry Andric if (getReference() && !getReference()->equals(Scope->getReference()))
1978bdd1243dSDimitry Andric return false;
1979bdd1243dSDimitry Andric
1980bdd1243dSDimitry Andric return true;
1981bdd1243dSDimitry Andric }
1982bdd1243dSDimitry Andric
findEqualScope(const LVScopes * Scopes) const1983bdd1243dSDimitry Andric LVScope *LVScopeNamespace::findEqualScope(const LVScopes *Scopes) const {
1984bdd1243dSDimitry Andric assert(Scopes && "Scopes must not be nullptr");
1985bdd1243dSDimitry Andric // Go through candidates and try to find a best match.
1986bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes)
1987bdd1243dSDimitry Andric if (equals(Scope))
1988bdd1243dSDimitry Andric return Scope;
1989bdd1243dSDimitry Andric return nullptr;
1990bdd1243dSDimitry Andric }
1991bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const1992bdd1243dSDimitry Andric void LVScopeNamespace::printExtra(raw_ostream &OS, bool Full) const {
1993bdd1243dSDimitry Andric OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
1994bdd1243dSDimitry Andric
1995bdd1243dSDimitry Andric // Print any active ranges.
1996bdd1243dSDimitry Andric if (Full) {
1997bdd1243dSDimitry Andric printActiveRanges(OS, Full);
1998bdd1243dSDimitry Andric
1999bdd1243dSDimitry Andric if (LVScope *Reference = getReference())
2000bdd1243dSDimitry Andric Reference->printReference(OS, Full, const_cast<LVScopeNamespace *>(this));
2001bdd1243dSDimitry Andric }
2002bdd1243dSDimitry Andric }
2003bdd1243dSDimitry Andric
2004bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
2005bdd1243dSDimitry Andric // An object file (single or multiple CUs).
2006bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
processRangeInformation()2007bdd1243dSDimitry Andric void LVScopeRoot::processRangeInformation() {
2008bdd1243dSDimitry Andric if (!options().getAttributeAnyLocation())
2009bdd1243dSDimitry Andric return;
2010bdd1243dSDimitry Andric
2011bdd1243dSDimitry Andric if (Scopes)
2012bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes) {
2013bdd1243dSDimitry Andric LVScopeCompileUnit *CompileUnit =
2014bdd1243dSDimitry Andric static_cast<LVScopeCompileUnit *>(Scope);
2015bdd1243dSDimitry Andric getReader().setCompileUnit(CompileUnit);
2016bdd1243dSDimitry Andric CompileUnit->processRangeLocationCoverage();
2017bdd1243dSDimitry Andric }
2018bdd1243dSDimitry Andric }
2019bdd1243dSDimitry Andric
transformScopedName()202006c3fb27SDimitry Andric void LVScopeRoot::transformScopedName() {
202106c3fb27SDimitry Andric // Recursively transform all names.
202206c3fb27SDimitry Andric std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
202306c3fb27SDimitry Andric auto Traverse = [&](const auto *Set) {
202406c3fb27SDimitry Andric if (Set)
202506c3fb27SDimitry Andric for (const auto &Entry : *Set)
202606c3fb27SDimitry Andric Entry->setInnerComponent();
202706c3fb27SDimitry Andric };
202806c3fb27SDimitry Andric if (const LVScopes *Scopes = Parent->getScopes())
202906c3fb27SDimitry Andric for (LVScope *Scope : *Scopes) {
203006c3fb27SDimitry Andric Scope->setInnerComponent();
203106c3fb27SDimitry Andric TraverseScope(Scope);
203206c3fb27SDimitry Andric }
203306c3fb27SDimitry Andric Traverse(Parent->getSymbols());
203406c3fb27SDimitry Andric Traverse(Parent->getTypes());
203506c3fb27SDimitry Andric Traverse(Parent->getLines());
203606c3fb27SDimitry Andric };
203706c3fb27SDimitry Andric
203806c3fb27SDimitry Andric // Start traversing the scopes root and transform the element name.
203906c3fb27SDimitry Andric TraverseScope(this);
204006c3fb27SDimitry Andric }
204106c3fb27SDimitry Andric
equals(const LVScope * Scope) const2042bdd1243dSDimitry Andric bool LVScopeRoot::equals(const LVScope *Scope) const {
2043bdd1243dSDimitry Andric return LVScope::equals(Scope);
2044bdd1243dSDimitry Andric }
2045bdd1243dSDimitry Andric
print(raw_ostream & OS,bool Full) const2046bdd1243dSDimitry Andric void LVScopeRoot::print(raw_ostream &OS, bool Full) const {
2047bdd1243dSDimitry Andric OS << "\nLogical View:\n";
2048bdd1243dSDimitry Andric LVScope::print(OS, Full);
2049bdd1243dSDimitry Andric }
2050bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const2051bdd1243dSDimitry Andric void LVScopeRoot::printExtra(raw_ostream &OS, bool Full) const {
2052bdd1243dSDimitry Andric OS << formattedKind(kind()) << " " << formattedName(getName()) << "";
2053bdd1243dSDimitry Andric if (options().getAttributeFormat())
2054bdd1243dSDimitry Andric OS << " -> " << getFileFormatName();
2055bdd1243dSDimitry Andric OS << "\n";
2056bdd1243dSDimitry Andric }
2057bdd1243dSDimitry Andric
doPrintMatches(bool Split,raw_ostream & OS,bool UseMatchedElements) const2058bdd1243dSDimitry Andric Error LVScopeRoot::doPrintMatches(bool Split, raw_ostream &OS,
2059bdd1243dSDimitry Andric bool UseMatchedElements) const {
2060bdd1243dSDimitry Andric // During a view output splitting, use the output stream created by the
2061bdd1243dSDimitry Andric // split context, then switch to the reader output stream.
2062bdd1243dSDimitry Andric static raw_ostream *StreamSplit = &OS;
2063bdd1243dSDimitry Andric
2064bdd1243dSDimitry Andric if (Scopes) {
2065bdd1243dSDimitry Andric if (UseMatchedElements)
2066bdd1243dSDimitry Andric options().resetPrintFormatting();
2067bdd1243dSDimitry Andric print(OS);
2068bdd1243dSDimitry Andric
2069bdd1243dSDimitry Andric for (LVScope *Scope : *Scopes) {
2070bdd1243dSDimitry Andric getReader().setCompileUnit(const_cast<LVScope *>(Scope));
2071bdd1243dSDimitry Andric
2072bdd1243dSDimitry Andric // If 'Split', we use the scope name (CU name) as the ouput file; the
2073bdd1243dSDimitry Andric // delimiters in the pathname, must be replaced by a normal character.
2074bdd1243dSDimitry Andric if (Split) {
2075bdd1243dSDimitry Andric std::string ScopeName(Scope->getName());
2076bdd1243dSDimitry Andric if (std::error_code EC =
2077bdd1243dSDimitry Andric getReaderSplitContext().open(ScopeName, ".txt", OS))
2078bdd1243dSDimitry Andric return createStringError(EC, "Unable to create split output file %s",
2079bdd1243dSDimitry Andric ScopeName.c_str());
2080bdd1243dSDimitry Andric StreamSplit = static_cast<raw_ostream *>(&getReaderSplitContext().os());
2081bdd1243dSDimitry Andric }
2082bdd1243dSDimitry Andric
2083bdd1243dSDimitry Andric Scope->printMatchedElements(*StreamSplit, UseMatchedElements);
2084bdd1243dSDimitry Andric
2085bdd1243dSDimitry Andric // Done printing the compile unit. Restore the original output context.
2086bdd1243dSDimitry Andric if (Split) {
2087bdd1243dSDimitry Andric getReaderSplitContext().close();
2088bdd1243dSDimitry Andric StreamSplit = &getReader().outputStream();
2089bdd1243dSDimitry Andric }
2090bdd1243dSDimitry Andric }
2091bdd1243dSDimitry Andric if (UseMatchedElements)
2092bdd1243dSDimitry Andric options().setPrintFormatting();
2093bdd1243dSDimitry Andric }
2094bdd1243dSDimitry Andric
2095bdd1243dSDimitry Andric return Error::success();
2096bdd1243dSDimitry Andric }
2097bdd1243dSDimitry Andric
2098bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
2099bdd1243dSDimitry Andric // DWARF template parameter pack (DW_TAG_GNU_template_parameter_pack).
2100bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const2101bdd1243dSDimitry Andric bool LVScopeTemplatePack::equals(const LVScope *Scope) const {
2102bdd1243dSDimitry Andric if (!LVScope::equals(Scope))
2103bdd1243dSDimitry Andric return false;
2104bdd1243dSDimitry Andric return equalNumberOfChildren(Scope);
2105bdd1243dSDimitry Andric }
2106bdd1243dSDimitry Andric
printExtra(raw_ostream & OS,bool Full) const2107bdd1243dSDimitry Andric void LVScopeTemplatePack::printExtra(raw_ostream &OS, bool Full) const {
2108bdd1243dSDimitry Andric OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
2109bdd1243dSDimitry Andric }
2110