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