xref: /llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp (revision f9306f6de3bd19a2dcacd64566852a5f92c86e77)
1e28b9357SCarlos Alberto Enciso //===-- LVScope.cpp -------------------------------------------------------===//
2e28b9357SCarlos Alberto Enciso //
3e28b9357SCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e28b9357SCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information.
5e28b9357SCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e28b9357SCarlos Alberto Enciso //
7e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
8e28b9357SCarlos Alberto Enciso //
9e28b9357SCarlos Alberto Enciso // This implements the LVScope class.
10e28b9357SCarlos Alberto Enciso //
11e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
12e28b9357SCarlos Alberto Enciso 
13e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
14e98a4c5aSCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
15e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
163c397c90SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
173c397c90SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVRange.h"
18e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
19e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
20e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
21e28b9357SCarlos Alberto Enciso 
22e28b9357SCarlos Alberto Enciso using namespace llvm;
23e28b9357SCarlos Alberto Enciso using namespace llvm::logicalview;
24e28b9357SCarlos Alberto Enciso 
25e28b9357SCarlos Alberto Enciso #define DEBUG_TYPE "Scope"
26e28b9357SCarlos Alberto Enciso 
27e28b9357SCarlos Alberto Enciso namespace {
28e28b9357SCarlos Alberto Enciso const char *const KindArray = "Array";
29e28b9357SCarlos Alberto Enciso const char *const KindBlock = "Block";
30e28b9357SCarlos Alberto Enciso const char *const KindCallSite = "CallSite";
31e28b9357SCarlos Alberto Enciso const char *const KindClass = "Class";
32e28b9357SCarlos Alberto Enciso const char *const KindCompileUnit = "CompileUnit";
33e28b9357SCarlos Alberto Enciso const char *const KindEnumeration = "Enumeration";
34e28b9357SCarlos Alberto Enciso const char *const KindFile = "File";
35e28b9357SCarlos Alberto Enciso const char *const KindFunction = "Function";
36e28b9357SCarlos Alberto Enciso const char *const KindInlinedFunction = "InlinedFunction";
37e28b9357SCarlos Alberto Enciso const char *const KindNamespace = "Namespace";
38e28b9357SCarlos Alberto Enciso const char *const KindStruct = "Struct";
39e28b9357SCarlos Alberto Enciso const char *const KindTemplateAlias = "TemplateAlias";
40e28b9357SCarlos Alberto Enciso const char *const KindTemplatePack = "TemplatePack";
41e28b9357SCarlos Alberto Enciso const char *const KindUndefined = "Undefined";
42e28b9357SCarlos Alberto Enciso const char *const KindUnion = "Union";
43e28b9357SCarlos Alberto Enciso } // end anonymous namespace
44e28b9357SCarlos Alberto Enciso 
45e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
46e28b9357SCarlos Alberto Enciso // DWARF lexical block, such as: namespace, function, compile unit, module, etc.
47e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
48e28b9357SCarlos Alberto Enciso // Return a string representation for the scope kind.
kind() const49e28b9357SCarlos Alberto Enciso const char *LVScope::kind() const {
50e28b9357SCarlos Alberto Enciso   const char *Kind = KindUndefined;
51e28b9357SCarlos Alberto Enciso   if (getIsArray())
52e28b9357SCarlos Alberto Enciso     Kind = KindArray;
53e28b9357SCarlos Alberto Enciso   else if (getIsBlock())
54e28b9357SCarlos Alberto Enciso     Kind = KindBlock;
55e28b9357SCarlos Alberto Enciso   else if (getIsCallSite())
56e28b9357SCarlos Alberto Enciso     Kind = KindCallSite;
57e28b9357SCarlos Alberto Enciso   else if (getIsCompileUnit())
58e28b9357SCarlos Alberto Enciso     Kind = KindCompileUnit;
59e28b9357SCarlos Alberto Enciso   else if (getIsEnumeration())
60e28b9357SCarlos Alberto Enciso     Kind = KindEnumeration;
61e28b9357SCarlos Alberto Enciso   else if (getIsInlinedFunction())
62e28b9357SCarlos Alberto Enciso     Kind = KindInlinedFunction;
63e28b9357SCarlos Alberto Enciso   else if (getIsNamespace())
64e28b9357SCarlos Alberto Enciso     Kind = KindNamespace;
65e28b9357SCarlos Alberto Enciso   else if (getIsTemplatePack())
66e28b9357SCarlos Alberto Enciso     Kind = KindTemplatePack;
67e28b9357SCarlos Alberto Enciso   else if (getIsRoot())
68e28b9357SCarlos Alberto Enciso     Kind = KindFile;
69e28b9357SCarlos Alberto Enciso   else if (getIsTemplateAlias())
70e28b9357SCarlos Alberto Enciso     Kind = KindTemplateAlias;
71e28b9357SCarlos Alberto Enciso   else if (getIsClass())
72e28b9357SCarlos Alberto Enciso     Kind = KindClass;
73e28b9357SCarlos Alberto Enciso   else if (getIsFunction())
74e28b9357SCarlos Alberto Enciso     Kind = KindFunction;
75e28b9357SCarlos Alberto Enciso   else if (getIsStructure())
76e28b9357SCarlos Alberto Enciso     Kind = KindStruct;
77e28b9357SCarlos Alberto Enciso   else if (getIsUnion())
78e28b9357SCarlos Alberto Enciso     Kind = KindUnion;
79e28b9357SCarlos Alberto Enciso   return Kind;
80e28b9357SCarlos Alberto Enciso }
81e28b9357SCarlos Alberto Enciso 
820332a8e7SCarlos Alberto Enciso LVScopeDispatch LVScope::Dispatch = {
830332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsAggregate, &LVScope::getIsAggregate},
840332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsArray, &LVScope::getIsArray},
850332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsBlock, &LVScope::getIsBlock},
860332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsCallSite, &LVScope::getIsCallSite},
870332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsCatchBlock, &LVScope::getIsCatchBlock},
880332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsClass, &LVScope::getIsClass},
890332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsCompileUnit, &LVScope::getIsCompileUnit},
900332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsEntryPoint, &LVScope::getIsEntryPoint},
910332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsEnumeration, &LVScope::getIsEnumeration},
920332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsFunction, &LVScope::getIsFunction},
930332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsFunctionType, &LVScope::getIsFunctionType},
940332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsInlinedFunction, &LVScope::getIsInlinedFunction},
950332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsLabel, &LVScope::getIsLabel},
960332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsLexicalBlock, &LVScope::getIsLexicalBlock},
970332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsNamespace, &LVScope::getIsNamespace},
980332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsRoot, &LVScope::getIsRoot},
990332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsStructure, &LVScope::getIsStructure},
1000332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsTemplate, &LVScope::getIsTemplate},
1010332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsTemplateAlias, &LVScope::getIsTemplateAlias},
1020332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsTemplatePack, &LVScope::getIsTemplatePack},
1030332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsTryBlock, &LVScope::getIsTryBlock},
1040332a8e7SCarlos Alberto Enciso     {LVScopeKind::IsUnion, &LVScope::getIsUnion}};
1050332a8e7SCarlos Alberto Enciso 
addToChildren(LVElement * Element)106e28b9357SCarlos Alberto Enciso void LVScope::addToChildren(LVElement *Element) {
107e28b9357SCarlos Alberto Enciso   if (!Children)
1087fbcc244SCarlos Alberto Enciso     Children = std::make_unique<LVElements>();
109e28b9357SCarlos Alberto Enciso   Children->push_back(Element);
110e28b9357SCarlos Alberto Enciso }
111e28b9357SCarlos Alberto Enciso 
addElement(LVElement * Element)112e28b9357SCarlos Alberto Enciso void LVScope::addElement(LVElement *Element) {
113e28b9357SCarlos Alberto Enciso   assert(Element && "Invalid element.");
114e28b9357SCarlos Alberto Enciso   if (Element->getIsType())
115e28b9357SCarlos Alberto Enciso     addElement(static_cast<LVType *>(Element));
116e28b9357SCarlos Alberto Enciso   else if (Element->getIsScope())
117e28b9357SCarlos Alberto Enciso     addElement(static_cast<LVScope *>(Element));
118e28b9357SCarlos Alberto Enciso   else if (Element->getIsSymbol())
119e28b9357SCarlos Alberto Enciso     addElement(static_cast<LVSymbol *>(Element));
120e28b9357SCarlos Alberto Enciso   else if (Element->getIsLine())
121e28b9357SCarlos Alberto Enciso     addElement(static_cast<LVLine *>(Element));
122e28b9357SCarlos Alberto Enciso   else
123e28b9357SCarlos Alberto Enciso     llvm_unreachable("Invalid Element.");
124e28b9357SCarlos Alberto Enciso }
125e28b9357SCarlos Alberto Enciso 
126e28b9357SCarlos Alberto Enciso // Adds the line info item to the ones stored in the scope.
addElement(LVLine * Line)127e28b9357SCarlos Alberto Enciso void LVScope::addElement(LVLine *Line) {
128e28b9357SCarlos Alberto Enciso   assert(Line && "Invalid line.");
129e28b9357SCarlos Alberto Enciso   assert(!Line->getParent() && "Line already inserted");
130e28b9357SCarlos Alberto Enciso   if (!Lines)
1317fbcc244SCarlos Alberto Enciso     Lines = std::make_unique<LVLines>();
132e28b9357SCarlos Alberto Enciso 
133e28b9357SCarlos Alberto Enciso   // Add it to parent.
134e28b9357SCarlos Alberto Enciso   Lines->push_back(Line);
135e28b9357SCarlos Alberto Enciso   Line->setParent(this);
136e28b9357SCarlos Alberto Enciso 
137e28b9357SCarlos Alberto Enciso   // Notify the reader about the new element being added.
138e28b9357SCarlos Alberto Enciso   getReaderCompileUnit()->addedElement(Line);
139e28b9357SCarlos Alberto Enciso 
140e28b9357SCarlos Alberto Enciso   // All logical elements added to the children, are sorted by any of the
141e28b9357SCarlos Alberto Enciso   // following criterias: offset, name, line number, kind.
142e28b9357SCarlos Alberto Enciso   // Do not add the line records to the children, as they represent the
143e28b9357SCarlos Alberto Enciso   // logical view for the text section and any sorting will not preserve
144e28b9357SCarlos Alberto Enciso   // the original sequence.
145e28b9357SCarlos Alberto Enciso 
146e28b9357SCarlos Alberto Enciso   // Indicate that this tree branch has lines.
147e28b9357SCarlos Alberto Enciso   traverseParents(&LVScope::getHasLines, &LVScope::setHasLines);
148e28b9357SCarlos Alberto Enciso }
149e28b9357SCarlos Alberto Enciso 
1503c397c90SCarlos Alberto Enciso // Add a location.
addObject(LVLocation * Location)1513c397c90SCarlos Alberto Enciso void LVScope::addObject(LVLocation *Location) {
1523c397c90SCarlos Alberto Enciso   assert(Location && "Invalid location.");
1533c397c90SCarlos Alberto Enciso   assert(!Location->getParent() && "Location already inserted");
1543c397c90SCarlos Alberto Enciso   if (!Ranges)
1557fbcc244SCarlos Alberto Enciso     Ranges = std::make_unique<LVLocations>();
1563c397c90SCarlos Alberto Enciso 
1573c397c90SCarlos Alberto Enciso   // Add it to parent.
1583c397c90SCarlos Alberto Enciso   Location->setParent(this);
1593c397c90SCarlos Alberto Enciso   Location->setOffset(getOffset());
1603c397c90SCarlos Alberto Enciso 
1613c397c90SCarlos Alberto Enciso   Ranges->push_back(Location);
1623c397c90SCarlos Alberto Enciso   setHasRanges();
1633c397c90SCarlos Alberto Enciso }
1643c397c90SCarlos Alberto Enciso 
165e28b9357SCarlos Alberto Enciso // Adds the scope to the child scopes and sets the parent in the child.
addElement(LVScope * Scope)166e28b9357SCarlos Alberto Enciso void LVScope::addElement(LVScope *Scope) {
167e28b9357SCarlos Alberto Enciso   assert(Scope && "Invalid scope.");
168e28b9357SCarlos Alberto Enciso   assert(!Scope->getParent() && "Scope already inserted");
169e28b9357SCarlos Alberto Enciso   if (!Scopes)
1707fbcc244SCarlos Alberto Enciso     Scopes = std::make_unique<LVScopes>();
171e28b9357SCarlos Alberto Enciso 
172e28b9357SCarlos Alberto Enciso   // Add it to parent.
173e28b9357SCarlos Alberto Enciso   Scopes->push_back(Scope);
174e28b9357SCarlos Alberto Enciso   addToChildren(Scope);
175e28b9357SCarlos Alberto Enciso   Scope->setParent(this);
176e28b9357SCarlos Alberto Enciso 
177e28b9357SCarlos Alberto Enciso   // Notify the reader about the new element being added.
178e28b9357SCarlos Alberto Enciso   getReaderCompileUnit()->addedElement(Scope);
179e28b9357SCarlos Alberto Enciso 
180e28b9357SCarlos Alberto Enciso   // If the element is a global reference, mark its parent as having global
181e28b9357SCarlos Alberto Enciso   // references; that information is used, to print only those branches
182e28b9357SCarlos Alberto Enciso   // with global references.
183e28b9357SCarlos Alberto Enciso   if (Scope->getIsGlobalReference())
184e28b9357SCarlos Alberto Enciso     traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);
185e28b9357SCarlos Alberto Enciso   else
186e28b9357SCarlos Alberto Enciso     traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);
187e28b9357SCarlos Alberto Enciso 
188e28b9357SCarlos Alberto Enciso   // Indicate that this tree branch has scopes.
189e28b9357SCarlos Alberto Enciso   traverseParents(&LVScope::getHasScopes, &LVScope::setHasScopes);
190e28b9357SCarlos Alberto Enciso }
191e28b9357SCarlos Alberto Enciso 
192e28b9357SCarlos Alberto Enciso // Adds a symbol to the ones stored in the scope.
addElement(LVSymbol * Symbol)193e28b9357SCarlos Alberto Enciso void LVScope::addElement(LVSymbol *Symbol) {
194e28b9357SCarlos Alberto Enciso   assert(Symbol && "Invalid symbol.");
195e28b9357SCarlos Alberto Enciso   assert(!Symbol->getParent() && "Symbol already inserted");
196e28b9357SCarlos Alberto Enciso   if (!Symbols)
1977fbcc244SCarlos Alberto Enciso     Symbols = std::make_unique<LVSymbols>();
198e28b9357SCarlos Alberto Enciso 
199e28b9357SCarlos Alberto Enciso   // Add it to parent.
200e28b9357SCarlos Alberto Enciso   Symbols->push_back(Symbol);
201e28b9357SCarlos Alberto Enciso   addToChildren(Symbol);
202e28b9357SCarlos Alberto Enciso   Symbol->setParent(this);
203e28b9357SCarlos Alberto Enciso 
204e28b9357SCarlos Alberto Enciso   // Notify the reader about the new element being added.
205e28b9357SCarlos Alberto Enciso   getReaderCompileUnit()->addedElement(Symbol);
206e28b9357SCarlos Alberto Enciso 
207e28b9357SCarlos Alberto Enciso   // If the element is a global reference, mark its parent as having global
208e28b9357SCarlos Alberto Enciso   // references; that information is used, to print only those branches
209e28b9357SCarlos Alberto Enciso   // with global references.
210e28b9357SCarlos Alberto Enciso   if (Symbol->getIsGlobalReference())
211e28b9357SCarlos Alberto Enciso     traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);
212e28b9357SCarlos Alberto Enciso   else
213e28b9357SCarlos Alberto Enciso     traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);
214e28b9357SCarlos Alberto Enciso 
215e28b9357SCarlos Alberto Enciso   // Indicate that this tree branch has symbols.
216e28b9357SCarlos Alberto Enciso   traverseParents(&LVScope::getHasSymbols, &LVScope::setHasSymbols);
217e28b9357SCarlos Alberto Enciso }
218e28b9357SCarlos Alberto Enciso 
219e28b9357SCarlos Alberto Enciso // Adds a type to the ones stored in the scope.
addElement(LVType * Type)220e28b9357SCarlos Alberto Enciso void LVScope::addElement(LVType *Type) {
221e28b9357SCarlos Alberto Enciso   assert(Type && "Invalid type.");
222e28b9357SCarlos Alberto Enciso   assert(!Type->getParent() && "Type already inserted");
223e28b9357SCarlos Alberto Enciso   if (!Types)
2247fbcc244SCarlos Alberto Enciso     Types = std::make_unique<LVTypes>();
225e28b9357SCarlos Alberto Enciso 
226e28b9357SCarlos Alberto Enciso   // Add it to parent.
227e28b9357SCarlos Alberto Enciso   Types->push_back(Type);
228e28b9357SCarlos Alberto Enciso   addToChildren(Type);
229e28b9357SCarlos Alberto Enciso   Type->setParent(this);
230e28b9357SCarlos Alberto Enciso 
231e28b9357SCarlos Alberto Enciso   // Notify the reader about the new element being added.
232e28b9357SCarlos Alberto Enciso   getReaderCompileUnit()->addedElement(Type);
233e28b9357SCarlos Alberto Enciso 
234e28b9357SCarlos Alberto Enciso   // If the element is a global reference, mark its parent as having global
235e28b9357SCarlos Alberto Enciso   // references; that information is used, to print only those branches
236e28b9357SCarlos Alberto Enciso   // with global references.
237e28b9357SCarlos Alberto Enciso   if (Type->getIsGlobalReference())
238e28b9357SCarlos Alberto Enciso     traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);
239e28b9357SCarlos Alberto Enciso   else
240e28b9357SCarlos Alberto Enciso     traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);
241e28b9357SCarlos Alberto Enciso 
242e28b9357SCarlos Alberto Enciso   // Indicate that this tree branch has types.
243e28b9357SCarlos Alberto Enciso   traverseParents(&LVScope::getHasTypes, &LVScope::setHasTypes);
244e28b9357SCarlos Alberto Enciso }
245e28b9357SCarlos Alberto Enciso 
2463c397c90SCarlos Alberto Enciso // Add a pair of ranges.
addObject(LVAddress LowerAddress,LVAddress UpperAddress)2473c397c90SCarlos Alberto Enciso void LVScope::addObject(LVAddress LowerAddress, LVAddress UpperAddress) {
2483c397c90SCarlos Alberto Enciso   // Pack the ranges into a Location object.
2497fbcc244SCarlos Alberto Enciso   LVLocation *Location = getReader().createLocation();
2503c397c90SCarlos Alberto Enciso   Location->setLowerAddress(LowerAddress);
2513c397c90SCarlos Alberto Enciso   Location->setUpperAddress(UpperAddress);
2523c397c90SCarlos Alberto Enciso   Location->setIsAddressRange();
2533c397c90SCarlos Alberto Enciso 
2543c397c90SCarlos Alberto Enciso   addObject(Location);
2553c397c90SCarlos Alberto Enciso }
2563c397c90SCarlos Alberto Enciso 
removeElement(LVElement * Element)257e28b9357SCarlos Alberto Enciso bool LVScope::removeElement(LVElement *Element) {
258e28b9357SCarlos Alberto Enciso   auto Predicate = [Element](LVElement *Item) -> bool {
259e28b9357SCarlos Alberto Enciso     return Item == Element;
260e28b9357SCarlos Alberto Enciso   };
261e28b9357SCarlos Alberto Enciso   auto RemoveElement = [Element, Predicate](auto &Container) -> bool {
262e28b9357SCarlos Alberto Enciso     auto Iter = std::remove_if(Container->begin(), Container->end(), Predicate);
263e28b9357SCarlos Alberto Enciso     if (Iter != Container->end()) {
264e28b9357SCarlos Alberto Enciso       Container->erase(Iter, Container->end());
265e28b9357SCarlos Alberto Enciso       Element->resetParent();
266e28b9357SCarlos Alberto Enciso       return true;
267e28b9357SCarlos Alberto Enciso     }
268e28b9357SCarlos Alberto Enciso     return false;
269e28b9357SCarlos Alberto Enciso   };
270e28b9357SCarlos Alberto Enciso 
271e28b9357SCarlos Alberto Enciso   // As 'children' contains only (scopes, symbols and types), check if the
272e28b9357SCarlos Alberto Enciso   // element we are deleting is a line.
273e28b9357SCarlos Alberto Enciso   if (Element->getIsLine())
274e28b9357SCarlos Alberto Enciso     return RemoveElement(Lines);
275e28b9357SCarlos Alberto Enciso 
276e28b9357SCarlos Alberto Enciso   if (RemoveElement(Children)) {
277e28b9357SCarlos Alberto Enciso     if (Element->getIsSymbol())
278e28b9357SCarlos Alberto Enciso       return RemoveElement(Symbols);
279e28b9357SCarlos Alberto Enciso     if (Element->getIsType())
280e28b9357SCarlos Alberto Enciso       return RemoveElement(Types);
281e28b9357SCarlos Alberto Enciso     if (Element->getIsScope())
282e28b9357SCarlos Alberto Enciso       return RemoveElement(Scopes);
283e28b9357SCarlos Alberto Enciso     llvm_unreachable("Invalid element.");
284e28b9357SCarlos Alberto Enciso   }
285e28b9357SCarlos Alberto Enciso 
286e28b9357SCarlos Alberto Enciso   return false;
287e28b9357SCarlos Alberto Enciso }
288e28b9357SCarlos Alberto Enciso 
addMissingElements(LVScope * Reference)289e28b9357SCarlos Alberto Enciso void LVScope::addMissingElements(LVScope *Reference) {
290e28b9357SCarlos Alberto Enciso   setAddedMissing();
291e28b9357SCarlos Alberto Enciso   if (!Reference)
292e28b9357SCarlos Alberto Enciso     return;
293e28b9357SCarlos Alberto Enciso 
294e28b9357SCarlos Alberto Enciso   // Get abstract symbols for the given scope reference.
295e28b9357SCarlos Alberto Enciso   const LVSymbols *ReferenceSymbols = Reference->getSymbols();
296e28b9357SCarlos Alberto Enciso   if (!ReferenceSymbols)
297e28b9357SCarlos Alberto Enciso     return;
298e28b9357SCarlos Alberto Enciso 
299e28b9357SCarlos Alberto Enciso   LVSymbols References;
300e28b9357SCarlos Alberto Enciso   References.append(ReferenceSymbols->begin(), ReferenceSymbols->end());
301e28b9357SCarlos Alberto Enciso 
302e28b9357SCarlos Alberto Enciso   // Erase abstract symbols already in this scope from the collection of
303e28b9357SCarlos Alberto Enciso   // symbols in the referenced scope.
304e28b9357SCarlos Alberto Enciso   if (getSymbols())
305e28b9357SCarlos Alberto Enciso     for (const LVSymbol *Symbol : *getSymbols())
306e28b9357SCarlos Alberto Enciso       if (Symbol->getHasReferenceAbstract())
307*f9306f6dSKazu Hirata         llvm::erase(References, Symbol->getReference());
308e28b9357SCarlos Alberto Enciso 
309e28b9357SCarlos Alberto Enciso   // If we have elements left in 'References', those are the elements that
310e28b9357SCarlos Alberto Enciso   // need to be inserted in the current scope.
311e28b9357SCarlos Alberto Enciso   if (References.size()) {
312e28b9357SCarlos Alberto Enciso     LLVM_DEBUG({
313e28b9357SCarlos Alberto Enciso       dbgs() << "Insert Missing Inlined Elements\n"
314e28b9357SCarlos Alberto Enciso              << "Offset = " << hexSquareString(getOffset()) << " "
315e28b9357SCarlos Alberto Enciso              << "Abstract = " << hexSquareString(Reference->getOffset())
316e28b9357SCarlos Alberto Enciso              << "\n";
317e28b9357SCarlos Alberto Enciso     });
318e28b9357SCarlos Alberto Enciso     for (LVSymbol *Reference : References) {
319e28b9357SCarlos Alberto Enciso       LLVM_DEBUG({
320e28b9357SCarlos Alberto Enciso         dbgs() << "Missing Offset = " << hexSquareString(Reference->getOffset())
321e28b9357SCarlos Alberto Enciso                << "\n";
322e28b9357SCarlos Alberto Enciso       });
323e28b9357SCarlos Alberto Enciso       // We can't clone the abstract origin reference, as it contain extra
324e28b9357SCarlos Alberto Enciso       // information that is incorrect for the element to be inserted.
325e28b9357SCarlos Alberto Enciso       // As the symbol being added does not exist in the debug section,
326e28b9357SCarlos Alberto Enciso       // use its parent scope offset, to indicate its DIE location.
3277fbcc244SCarlos Alberto Enciso       LVSymbol *Symbol = getReader().createSymbol();
328e28b9357SCarlos Alberto Enciso       addElement(Symbol);
329e28b9357SCarlos Alberto Enciso       Symbol->setOffset(getOffset());
330e28b9357SCarlos Alberto Enciso       Symbol->setIsOptimized();
331e28b9357SCarlos Alberto Enciso       Symbol->setReference(Reference);
332e28b9357SCarlos Alberto Enciso 
333e28b9357SCarlos Alberto Enciso       // The symbol can be a constant, parameter or variable.
334e28b9357SCarlos Alberto Enciso       if (Reference->getIsConstant())
335e28b9357SCarlos Alberto Enciso         Symbol->setIsConstant();
336e28b9357SCarlos Alberto Enciso       else if (Reference->getIsParameter())
337e28b9357SCarlos Alberto Enciso         Symbol->setIsParameter();
338e28b9357SCarlos Alberto Enciso       else if (Reference->getIsVariable())
339e28b9357SCarlos Alberto Enciso         Symbol->setIsVariable();
340e28b9357SCarlos Alberto Enciso       else
341e28b9357SCarlos Alberto Enciso         llvm_unreachable("Invalid symbol kind.");
342e28b9357SCarlos Alberto Enciso     }
343e28b9357SCarlos Alberto Enciso   }
344e28b9357SCarlos Alberto Enciso }
345e28b9357SCarlos Alberto Enciso 
updateLevel(LVScope * Parent,bool Moved)346e28b9357SCarlos Alberto Enciso void LVScope::updateLevel(LVScope *Parent, bool Moved) {
347e28b9357SCarlos Alberto Enciso   // Update the level for the element itself and all its children, using the
348e28b9357SCarlos Alberto Enciso   // given scope parent as reference.
349e28b9357SCarlos Alberto Enciso   setLevel(Parent->getLevel() + 1);
350e28b9357SCarlos Alberto Enciso 
351e28b9357SCarlos Alberto Enciso   // Update the children.
352e28b9357SCarlos Alberto Enciso   if (Children)
353e28b9357SCarlos Alberto Enciso     for (LVElement *Element : *Children)
354e28b9357SCarlos Alberto Enciso       Element->updateLevel(this, Moved);
355e28b9357SCarlos Alberto Enciso 
356e28b9357SCarlos Alberto Enciso   // Update any lines.
357e28b9357SCarlos Alberto Enciso   if (Lines)
358e28b9357SCarlos Alberto Enciso     for (LVLine *Line : *Lines)
359e28b9357SCarlos Alberto Enciso       Line->updateLevel(this, Moved);
360e28b9357SCarlos Alberto Enciso }
361e28b9357SCarlos Alberto Enciso 
resolve()362e28b9357SCarlos Alberto Enciso void LVScope::resolve() {
363e28b9357SCarlos Alberto Enciso   if (getIsResolved())
364e28b9357SCarlos Alberto Enciso     return;
365e28b9357SCarlos Alberto Enciso 
366e28b9357SCarlos Alberto Enciso   // Resolve the element itself.
367e28b9357SCarlos Alberto Enciso   LVElement::resolve();
368e28b9357SCarlos Alberto Enciso 
369e28b9357SCarlos Alberto Enciso   // Resolve the children.
370e28b9357SCarlos Alberto Enciso   if (Children)
371e28b9357SCarlos Alberto Enciso     for (LVElement *Element : *Children) {
372e28b9357SCarlos Alberto Enciso       if (getIsGlobalReference())
373e28b9357SCarlos Alberto Enciso         // If the scope is a global reference, mark all its children as well.
374e28b9357SCarlos Alberto Enciso         Element->setIsGlobalReference();
375e28b9357SCarlos Alberto Enciso       Element->resolve();
376e28b9357SCarlos Alberto Enciso     }
377e28b9357SCarlos Alberto Enciso }
378e28b9357SCarlos Alberto Enciso 
resolveName()379e28b9357SCarlos Alberto Enciso void LVScope::resolveName() {
380e28b9357SCarlos Alberto Enciso   if (getIsResolvedName())
381e28b9357SCarlos Alberto Enciso     return;
382e28b9357SCarlos Alberto Enciso   setIsResolvedName();
383e28b9357SCarlos Alberto Enciso 
384e28b9357SCarlos Alberto Enciso   // If the scope is a template, resolve the template parameters and get
385e28b9357SCarlos Alberto Enciso   // the name for the template with the encoded arguments.
386e28b9357SCarlos Alberto Enciso   if (getIsTemplate())
387e28b9357SCarlos Alberto Enciso     resolveTemplate();
388e28b9357SCarlos Alberto Enciso   else {
389e28b9357SCarlos Alberto Enciso     if (LVElement *BaseType = getType()) {
390e28b9357SCarlos Alberto Enciso       BaseType->resolveName();
391e28b9357SCarlos Alberto Enciso       resolveFullname(BaseType);
392e28b9357SCarlos Alberto Enciso     }
393e28b9357SCarlos Alberto Enciso   }
394e28b9357SCarlos Alberto Enciso 
395e28b9357SCarlos Alberto Enciso   // In the case of unnamed scopes, try to generate a name for it, using
396e28b9357SCarlos Alberto Enciso   // the parents name and the line information. In the case of compiler
397e28b9357SCarlos Alberto Enciso   // generated functions, use its linkage name if is available.
398e28b9357SCarlos Alberto Enciso   if (!isNamed()) {
399e28b9357SCarlos Alberto Enciso     if (getIsArtificial())
400e28b9357SCarlos Alberto Enciso       setName(getLinkageName());
401e28b9357SCarlos Alberto Enciso     else
402e28b9357SCarlos Alberto Enciso       generateName();
403e28b9357SCarlos Alberto Enciso   }
404e28b9357SCarlos Alberto Enciso 
405e28b9357SCarlos Alberto Enciso   LVElement::resolveName();
4060332a8e7SCarlos Alberto Enciso 
4070332a8e7SCarlos Alberto Enciso   // Resolve any given pattern.
4080332a8e7SCarlos Alberto Enciso   patterns().resolvePatternMatch(this);
409e28b9357SCarlos Alberto Enciso }
410e28b9357SCarlos Alberto Enciso 
resolveReferences()411e28b9357SCarlos Alberto Enciso void LVScope::resolveReferences() {
412e28b9357SCarlos Alberto Enciso   // The scopes can have the following references to other elements:
413e28b9357SCarlos Alberto Enciso   //   A type:
414e28b9357SCarlos Alberto Enciso   //     DW_AT_type             ->  Type or Scope
415e28b9357SCarlos Alberto Enciso   //     DW_AT_import           ->  Type
416e28b9357SCarlos Alberto Enciso   //   A Reference:
417e28b9357SCarlos Alberto Enciso   //     DW_AT_specification    ->  Scope
418e28b9357SCarlos Alberto Enciso   //     DW_AT_abstract_origin  ->  Scope
419e28b9357SCarlos Alberto Enciso   //     DW_AT_extension        ->  Scope
420e28b9357SCarlos Alberto Enciso 
421e28b9357SCarlos Alberto Enciso   // Resolve any referenced scope.
422e28b9357SCarlos Alberto Enciso   LVScope *Reference = getReference();
423e28b9357SCarlos Alberto Enciso   if (Reference) {
424e28b9357SCarlos Alberto Enciso     Reference->resolve();
425e28b9357SCarlos Alberto Enciso     // Recursively resolve the scope names.
426e28b9357SCarlos Alberto Enciso     resolveReferencesChain();
427e28b9357SCarlos Alberto Enciso   }
428e28b9357SCarlos Alberto Enciso 
429e28b9357SCarlos Alberto Enciso   // Set the file/line information using the Debug Information entry.
430e28b9357SCarlos Alberto Enciso   setFile(Reference);
431e28b9357SCarlos Alberto Enciso 
432e28b9357SCarlos Alberto Enciso   // Resolve any referenced type or scope.
433e28b9357SCarlos Alberto Enciso   if (LVElement *Element = getType())
434e28b9357SCarlos Alberto Enciso     Element->resolve();
435e28b9357SCarlos Alberto Enciso }
436e28b9357SCarlos Alberto Enciso 
resolveElements()437e28b9357SCarlos Alberto Enciso void LVScope::resolveElements() {
438e28b9357SCarlos Alberto Enciso   // The current element represents the Root. Traverse each Compile Unit.
439e28b9357SCarlos Alberto Enciso   if (!Scopes)
440e28b9357SCarlos Alberto Enciso     return;
441e28b9357SCarlos Alberto Enciso 
442e28b9357SCarlos Alberto Enciso   for (LVScope *Scope : *Scopes) {
443e28b9357SCarlos Alberto Enciso     LVScopeCompileUnit *CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
444e28b9357SCarlos Alberto Enciso     getReader().setCompileUnit(CompileUnit);
445e28b9357SCarlos Alberto Enciso     CompileUnit->resolve();
4460332a8e7SCarlos Alberto Enciso     // Propagate any matching information into the scopes tree.
4470332a8e7SCarlos Alberto Enciso     CompileUnit->propagatePatternMatch();
448e28b9357SCarlos Alberto Enciso   }
449e28b9357SCarlos Alberto Enciso }
450e28b9357SCarlos Alberto Enciso 
resolveReferencesChain()451e28b9357SCarlos Alberto Enciso StringRef LVScope::resolveReferencesChain() {
452e28b9357SCarlos Alberto Enciso   // If the scope has a DW_AT_specification or DW_AT_abstract_origin,
453e28b9357SCarlos Alberto Enciso   // follow the chain to resolve the name from those references.
454e28b9357SCarlos Alberto Enciso   if (getHasReference() && !isNamed())
455e28b9357SCarlos Alberto Enciso     setName(getReference()->resolveReferencesChain());
456e28b9357SCarlos Alberto Enciso 
457e28b9357SCarlos Alberto Enciso   return getName();
458e28b9357SCarlos Alberto Enciso }
459e28b9357SCarlos Alberto Enciso 
460e28b9357SCarlos Alberto Enciso // Get template parameter types.
getTemplateParameterTypes(LVTypes & Params)461e28b9357SCarlos Alberto Enciso bool LVScope::getTemplateParameterTypes(LVTypes &Params) {
462e28b9357SCarlos Alberto Enciso   // Traverse the scope types and populate the given container with those
463e28b9357SCarlos Alberto Enciso   // types that are template parameters; that container will be used by
464e28b9357SCarlos Alberto Enciso   // 'encodeTemplateArguments' to resolve them.
465e28b9357SCarlos Alberto Enciso   if (const LVTypes *Types = getTypes())
466e28b9357SCarlos Alberto Enciso     for (LVType *Type : *Types)
467e28b9357SCarlos Alberto Enciso       if (Type->getIsTemplateParam()) {
468e28b9357SCarlos Alberto Enciso         Type->resolve();
469e28b9357SCarlos Alberto Enciso         Params.push_back(Type);
470e28b9357SCarlos Alberto Enciso       }
471e28b9357SCarlos Alberto Enciso 
472e28b9357SCarlos Alberto Enciso   return !Params.empty();
473e28b9357SCarlos Alberto Enciso }
474e28b9357SCarlos Alberto Enciso 
475e28b9357SCarlos Alberto Enciso // Resolve the template parameters/arguments relationship.
resolveTemplate()476e28b9357SCarlos Alberto Enciso void LVScope::resolveTemplate() {
477e28b9357SCarlos Alberto Enciso   if (getIsTemplateResolved())
478e28b9357SCarlos Alberto Enciso     return;
479e28b9357SCarlos Alberto Enciso   setIsTemplateResolved();
480e28b9357SCarlos Alberto Enciso 
481e28b9357SCarlos Alberto Enciso   // Check if we need to encode the template arguments.
482e28b9357SCarlos Alberto Enciso   if (options().getAttributeEncoded()) {
483e28b9357SCarlos Alberto Enciso     LVTypes Params;
484e28b9357SCarlos Alberto Enciso     if (getTemplateParameterTypes(Params)) {
485e28b9357SCarlos Alberto Enciso       std::string EncodedArgs;
486e28b9357SCarlos Alberto Enciso       // Encode the arguments as part of the template name and update the
487e28b9357SCarlos Alberto Enciso       // template name, to reflect the encoded parameters.
488e28b9357SCarlos Alberto Enciso       encodeTemplateArguments(EncodedArgs, &Params);
489d22f050eSGregory Alfonso       setEncodedArgs(EncodedArgs);
490e28b9357SCarlos Alberto Enciso     }
491e28b9357SCarlos Alberto Enciso   }
492e28b9357SCarlos Alberto Enciso }
493e28b9357SCarlos Alberto Enciso 
494e28b9357SCarlos Alberto Enciso // Get the qualified name for the template.
getQualifiedName(std::string & QualifiedName) const495e28b9357SCarlos Alberto Enciso void LVScope::getQualifiedName(std::string &QualifiedName) const {
496e28b9357SCarlos Alberto Enciso   if (getIsRoot() || getIsCompileUnit())
497e28b9357SCarlos Alberto Enciso     return;
498e28b9357SCarlos Alberto Enciso 
499e28b9357SCarlos Alberto Enciso   if (LVScope *Parent = getParentScope())
500e28b9357SCarlos Alberto Enciso     Parent->getQualifiedName(QualifiedName);
501e28b9357SCarlos Alberto Enciso   if (!QualifiedName.empty())
502e28b9357SCarlos Alberto Enciso     QualifiedName.append("::");
503e28b9357SCarlos Alberto Enciso   QualifiedName.append(std::string(getName()));
504e28b9357SCarlos Alberto Enciso }
505e28b9357SCarlos Alberto Enciso 
506e28b9357SCarlos Alberto Enciso // Encode the template arguments as part of the template name.
encodeTemplateArguments(std::string & Name) const507e28b9357SCarlos Alberto Enciso void LVScope::encodeTemplateArguments(std::string &Name) const {
508e28b9357SCarlos Alberto Enciso   // Qualify only when we are expanding parameters that are template
509e28b9357SCarlos Alberto Enciso   // instances; the debugger will assume the current scope symbol as
510e28b9357SCarlos Alberto Enciso   // the qualifying tag for the symbol being generated, which gives:
511e28b9357SCarlos Alberto Enciso   //   namespace std {
512e28b9357SCarlos Alberto Enciso   //     ...
513e28b9357SCarlos Alberto Enciso   //     set<float,std::less<float>,std::allocator<float>>
514e28b9357SCarlos Alberto Enciso   //     ...
515e28b9357SCarlos Alberto Enciso   //   }
516e28b9357SCarlos Alberto Enciso   // The 'set' symbol is assumed to have the qualified tag 'std'.
517e28b9357SCarlos Alberto Enciso 
518e28b9357SCarlos Alberto Enciso   // We are resolving a template parameter which is another template. If
519e28b9357SCarlos Alberto Enciso   // it is already resolved, just get the qualified name and return.
520e28b9357SCarlos Alberto Enciso   std::string BaseName;
521e28b9357SCarlos Alberto Enciso   getQualifiedName(BaseName);
522e28b9357SCarlos Alberto Enciso   if (getIsTemplateResolved())
523e28b9357SCarlos Alberto Enciso     Name.append(BaseName);
524e28b9357SCarlos Alberto Enciso }
525e28b9357SCarlos Alberto Enciso 
encodeTemplateArguments(std::string & Name,const LVTypes * Types) const526e28b9357SCarlos Alberto Enciso void LVScope::encodeTemplateArguments(std::string &Name,
527e28b9357SCarlos Alberto Enciso                                       const LVTypes *Types) const {
528e28b9357SCarlos Alberto Enciso   // The encoded string will start with the scope name.
529e28b9357SCarlos Alberto Enciso   Name.append("<");
530e28b9357SCarlos Alberto Enciso 
531e28b9357SCarlos Alberto Enciso   // The list of types are the template parameters.
532e28b9357SCarlos Alberto Enciso   if (Types) {
533e28b9357SCarlos Alberto Enciso     bool AddComma = false;
534e28b9357SCarlos Alberto Enciso     for (const LVType *Type : *Types) {
535e28b9357SCarlos Alberto Enciso       if (AddComma)
536e28b9357SCarlos Alberto Enciso         Name.append(", ");
537e28b9357SCarlos Alberto Enciso       Type->encodeTemplateArgument(Name);
538e28b9357SCarlos Alberto Enciso       AddComma = true;
539e28b9357SCarlos Alberto Enciso     }
540e28b9357SCarlos Alberto Enciso   }
541e28b9357SCarlos Alberto Enciso 
542e28b9357SCarlos Alberto Enciso   Name.append(">");
543e28b9357SCarlos Alberto Enciso }
544e28b9357SCarlos Alberto Enciso 
resolvePrinting() const545e28b9357SCarlos Alberto Enciso bool LVScope::resolvePrinting() const {
5462c155d37SCarlos Alberto Enciso   // The warnings collected during the scope creation as per compile unit.
5472c155d37SCarlos Alberto Enciso   // If there is a request for printing warnings, always print its associate
5482c155d37SCarlos Alberto Enciso   // Compile Unit.
5492c155d37SCarlos Alberto Enciso   if (options().getPrintWarnings() && (getIsRoot() || getIsCompileUnit()))
5502c155d37SCarlos Alberto Enciso     return true;
5512c155d37SCarlos Alberto Enciso 
5520332a8e7SCarlos Alberto Enciso   // In selection mode, always print the root scope regardless of the
5530332a8e7SCarlos Alberto Enciso   // number of matched elements. If no matches, the root by itself will
5540332a8e7SCarlos Alberto Enciso   // indicate no matches.
5550332a8e7SCarlos Alberto Enciso   if (options().getSelectExecute()) {
5560332a8e7SCarlos Alberto Enciso     return getIsRoot() || getIsCompileUnit() || getHasPattern();
5570332a8e7SCarlos Alberto Enciso   }
5580332a8e7SCarlos Alberto Enciso 
559e28b9357SCarlos Alberto Enciso   bool Globals = options().getAttributeGlobal();
560e28b9357SCarlos Alberto Enciso   bool Locals = options().getAttributeLocal();
561e28b9357SCarlos Alberto Enciso   if ((Globals && Locals) || (!Globals && !Locals)) {
562e28b9357SCarlos Alberto Enciso     // Print both Global and Local.
563e28b9357SCarlos Alberto Enciso   } else {
564e28b9357SCarlos Alberto Enciso     // Check for Global or Local Objects.
565e28b9357SCarlos Alberto Enciso     if ((Globals && !(getHasGlobals() || getIsGlobalReference())) ||
566e28b9357SCarlos Alberto Enciso         (Locals && !(getHasLocals() || !getIsGlobalReference())))
567e28b9357SCarlos Alberto Enciso       return false;
568e28b9357SCarlos Alberto Enciso   }
569e28b9357SCarlos Alberto Enciso 
570e28b9357SCarlos Alberto Enciso   // For the case of functions, skip it if is compiler generated.
571e28b9357SCarlos Alberto Enciso   if (getIsFunction() && getIsArtificial() &&
572e28b9357SCarlos Alberto Enciso       !options().getAttributeGenerated())
573e28b9357SCarlos Alberto Enciso     return false;
574e28b9357SCarlos Alberto Enciso 
575e28b9357SCarlos Alberto Enciso   return true;
576e28b9357SCarlos Alberto Enciso }
577e28b9357SCarlos Alberto Enciso 
doPrint(bool Split,bool Match,bool Print,raw_ostream & OS,bool Full) const578e28b9357SCarlos Alberto Enciso Error LVScope::doPrint(bool Split, bool Match, bool Print, raw_ostream &OS,
579e28b9357SCarlos Alberto Enciso                        bool Full) const {
580e28b9357SCarlos Alberto Enciso   // During a view output splitting, use the output stream created by the
581e28b9357SCarlos Alberto Enciso   // split context, then switch to the reader output stream.
582e28b9357SCarlos Alberto Enciso   raw_ostream *StreamSplit = &OS;
583e28b9357SCarlos Alberto Enciso 
584e7950fceSCarlos Alberto Enciso   // Ignore the CU generated by the VS toolchain, when compiling to PDB.
585e7950fceSCarlos Alberto Enciso   if (getIsSystem() && !options().getAttributeSystem())
586e7950fceSCarlos Alberto Enciso     return Error::success();
587e7950fceSCarlos Alberto Enciso 
588e28b9357SCarlos Alberto Enciso   // If 'Split', we use the scope name (CU name) as the ouput file; the
589e28b9357SCarlos Alberto Enciso   // delimiters in the pathname, must be replaced by a normal character.
590e28b9357SCarlos Alberto Enciso   if (getIsCompileUnit()) {
591e28b9357SCarlos Alberto Enciso     getReader().setCompileUnit(const_cast<LVScope *>(this));
592e28b9357SCarlos Alberto Enciso     if (Split) {
593e28b9357SCarlos Alberto Enciso       std::string ScopeName(getName());
594e28b9357SCarlos Alberto Enciso       if (std::error_code EC =
595e28b9357SCarlos Alberto Enciso               getReaderSplitContext().open(ScopeName, ".txt", OS))
596e28b9357SCarlos Alberto Enciso         return createStringError(EC, "Unable to create split output file %s",
597e28b9357SCarlos Alberto Enciso                                  ScopeName.c_str());
598e28b9357SCarlos Alberto Enciso       StreamSplit = static_cast<raw_ostream *>(&getReaderSplitContext().os());
599e28b9357SCarlos Alberto Enciso     }
600e28b9357SCarlos Alberto Enciso   }
601e28b9357SCarlos Alberto Enciso 
602e28b9357SCarlos Alberto Enciso   // Ignore discarded or stripped scopes (functions).
603e28b9357SCarlos Alberto Enciso   bool DoPrint = (options().getAttributeDiscarded()) ? true : !getIsDiscarded();
604e28b9357SCarlos Alberto Enciso 
605e28b9357SCarlos Alberto Enciso   // If we are in compare mode, the only conditions are related to the
606e28b9357SCarlos Alberto Enciso   // element being missing. In the case of elements comparison, we print the
607e28b9357SCarlos Alberto Enciso   // augmented view, that includes added elements.
608e28b9357SCarlos Alberto Enciso   // In print mode, we check other conditions, such as local, global, etc.
609e28b9357SCarlos Alberto Enciso   if (DoPrint) {
610e28b9357SCarlos Alberto Enciso     DoPrint =
611e28b9357SCarlos Alberto Enciso         getIsInCompare() ? options().getReportExecute() : resolvePrinting();
612e28b9357SCarlos Alberto Enciso   }
613e28b9357SCarlos Alberto Enciso 
614e28b9357SCarlos Alberto Enciso   // At this point we have checked for very specific options, to decide if the
615e28b9357SCarlos Alberto Enciso   // element will be printed. Include the caller's test for element general
616e28b9357SCarlos Alberto Enciso   // print.
617e28b9357SCarlos Alberto Enciso   DoPrint = DoPrint && (Print || options().getOutputSplit());
618e28b9357SCarlos Alberto Enciso 
619e28b9357SCarlos Alberto Enciso   if (DoPrint) {
620e28b9357SCarlos Alberto Enciso     // Print the element itself.
621e28b9357SCarlos Alberto Enciso     print(*StreamSplit, Full);
622e28b9357SCarlos Alberto Enciso 
623e28b9357SCarlos Alberto Enciso     // Check if we have reached the requested lexical level specified in the
624e28b9357SCarlos Alberto Enciso     // command line options. Input file is level zero and the CU is level 1.
625e28b9357SCarlos Alberto Enciso     if ((getIsRoot() || options().getPrintAnyElement()) &&
626e28b9357SCarlos Alberto Enciso         options().getPrintFormatting() &&
627e28b9357SCarlos Alberto Enciso         getLevel() < options().getOutputLevel()) {
628e28b9357SCarlos Alberto Enciso       // Print the children.
629e28b9357SCarlos Alberto Enciso       if (Children)
630e28b9357SCarlos Alberto Enciso         for (const LVElement *Element : *Children) {
631e28b9357SCarlos Alberto Enciso           if (Match && !Element->getHasPattern())
632e28b9357SCarlos Alberto Enciso             continue;
633e28b9357SCarlos Alberto Enciso           if (Error Err =
634e28b9357SCarlos Alberto Enciso                   Element->doPrint(Split, Match, Print, *StreamSplit, Full))
635e28b9357SCarlos Alberto Enciso             return Err;
636e28b9357SCarlos Alberto Enciso         }
637e28b9357SCarlos Alberto Enciso 
638e28b9357SCarlos Alberto Enciso       // Print the line records.
639e28b9357SCarlos Alberto Enciso       if (Lines)
640e28b9357SCarlos Alberto Enciso         for (const LVLine *Line : *Lines) {
641e28b9357SCarlos Alberto Enciso           if (Match && !Line->getHasPattern())
642e28b9357SCarlos Alberto Enciso             continue;
643e28b9357SCarlos Alberto Enciso           if (Error Err =
644e28b9357SCarlos Alberto Enciso                   Line->doPrint(Split, Match, Print, *StreamSplit, Full))
645e28b9357SCarlos Alberto Enciso             return Err;
646e28b9357SCarlos Alberto Enciso         }
6472c155d37SCarlos Alberto Enciso 
6482c155d37SCarlos Alberto Enciso       // Print the warnings.
6492c155d37SCarlos Alberto Enciso       if (options().getPrintWarnings())
6502c155d37SCarlos Alberto Enciso         printWarnings(*StreamSplit, Full);
651e28b9357SCarlos Alberto Enciso     }
652e28b9357SCarlos Alberto Enciso   }
653e28b9357SCarlos Alberto Enciso 
654e28b9357SCarlos Alberto Enciso   // Done printing the compile unit. Print any requested summary and
655e28b9357SCarlos Alberto Enciso   // restore the original output context.
656e28b9357SCarlos Alberto Enciso   if (getIsCompileUnit()) {
657e28b9357SCarlos Alberto Enciso     if (options().getPrintSummary())
658e28b9357SCarlos Alberto Enciso       printSummary(*StreamSplit);
659e28b9357SCarlos Alberto Enciso     if (options().getPrintSizes())
660e28b9357SCarlos Alberto Enciso       printSizes(*StreamSplit);
661e28b9357SCarlos Alberto Enciso     if (Split) {
662e28b9357SCarlos Alberto Enciso       getReaderSplitContext().close();
663e28b9357SCarlos Alberto Enciso       StreamSplit = &getReader().outputStream();
664e28b9357SCarlos Alberto Enciso     }
665e28b9357SCarlos Alberto Enciso   }
666e28b9357SCarlos Alberto Enciso 
6672c155d37SCarlos Alberto Enciso   if (getIsRoot() && options().getPrintWarnings()) {
6682c155d37SCarlos Alberto Enciso     getReader().printRecords(*StreamSplit);
6692c155d37SCarlos Alberto Enciso   }
6702c155d37SCarlos Alberto Enciso 
671e28b9357SCarlos Alberto Enciso   return Error::success();
672e28b9357SCarlos Alberto Enciso }
673e28b9357SCarlos Alberto Enciso 
sort()674e28b9357SCarlos Alberto Enciso void LVScope::sort() {
675e28b9357SCarlos Alberto Enciso   // Preserve the lines order as they are associated with user code.
676e28b9357SCarlos Alberto Enciso   LVSortFunction SortFunction = getSortFunction();
677e28b9357SCarlos Alberto Enciso   if (SortFunction) {
678e28b9357SCarlos Alberto Enciso     std::function<void(LVScope * Parent, LVSortFunction SortFunction)> Sort =
679e28b9357SCarlos Alberto Enciso         [&](LVScope *Parent, LVSortFunction SortFunction) {
6807fbcc244SCarlos Alberto Enciso           auto Traverse = [&](auto &Set, LVSortFunction SortFunction) {
681e28b9357SCarlos Alberto Enciso             if (Set)
682e28b9357SCarlos Alberto Enciso               std::stable_sort(Set->begin(), Set->end(), SortFunction);
683e28b9357SCarlos Alberto Enciso           };
684e28b9357SCarlos Alberto Enciso           Traverse(Parent->Types, SortFunction);
685e28b9357SCarlos Alberto Enciso           Traverse(Parent->Symbols, SortFunction);
686e28b9357SCarlos Alberto Enciso           Traverse(Parent->Scopes, SortFunction);
6873c397c90SCarlos Alberto Enciso           Traverse(Parent->Ranges, compareRange);
688e28b9357SCarlos Alberto Enciso           Traverse(Parent->Children, SortFunction);
689e28b9357SCarlos Alberto Enciso 
690e28b9357SCarlos Alberto Enciso           if (Parent->Scopes)
691e28b9357SCarlos Alberto Enciso             for (LVScope *Scope : *Parent->Scopes)
692e28b9357SCarlos Alberto Enciso               Sort(Scope, SortFunction);
693e28b9357SCarlos Alberto Enciso         };
694e28b9357SCarlos Alberto Enciso 
695e28b9357SCarlos Alberto Enciso     // Start traversing the scopes root and transform the element name.
696e28b9357SCarlos Alberto Enciso     Sort(this, SortFunction);
697e28b9357SCarlos Alberto Enciso   }
698e28b9357SCarlos Alberto Enciso }
699e28b9357SCarlos Alberto Enciso 
traverseParents(LVScopeGetFunction GetFunction,LVScopeSetFunction SetFunction)700e28b9357SCarlos Alberto Enciso void LVScope::traverseParents(LVScopeGetFunction GetFunction,
701e28b9357SCarlos Alberto Enciso                               LVScopeSetFunction SetFunction) {
702e28b9357SCarlos Alberto Enciso   // Traverse the parent tree.
703e28b9357SCarlos Alberto Enciso   LVScope *Parent = this;
704e28b9357SCarlos Alberto Enciso   while (Parent) {
705e28b9357SCarlos Alberto Enciso     // Terminates if the 'SetFunction' has been already executed.
706e28b9357SCarlos Alberto Enciso     if ((Parent->*GetFunction)())
707e28b9357SCarlos Alberto Enciso       break;
708e28b9357SCarlos Alberto Enciso     (Parent->*SetFunction)();
709e28b9357SCarlos Alberto Enciso     Parent = Parent->getParentScope();
710e28b9357SCarlos Alberto Enciso   }
711e28b9357SCarlos Alberto Enciso }
712e28b9357SCarlos Alberto Enciso 
traverseParentsAndChildren(LVObjectGetFunction GetFunction,LVObjectSetFunction SetFunction)713e28b9357SCarlos Alberto Enciso void LVScope::traverseParentsAndChildren(LVObjectGetFunction GetFunction,
714e28b9357SCarlos Alberto Enciso                                          LVObjectSetFunction SetFunction) {
715e28b9357SCarlos Alberto Enciso   if (options().getReportParents()) {
716e28b9357SCarlos Alberto Enciso     // First traverse the parent tree.
717e28b9357SCarlos Alberto Enciso     LVScope *Parent = this;
718e28b9357SCarlos Alberto Enciso     while (Parent) {
719e28b9357SCarlos Alberto Enciso       // Terminates if the 'SetFunction' has been already executed.
720e28b9357SCarlos Alberto Enciso       if ((Parent->*GetFunction)())
721e28b9357SCarlos Alberto Enciso         break;
722e28b9357SCarlos Alberto Enciso       (Parent->*SetFunction)();
723e28b9357SCarlos Alberto Enciso       Parent = Parent->getParentScope();
724e28b9357SCarlos Alberto Enciso     }
725e28b9357SCarlos Alberto Enciso   }
726e28b9357SCarlos Alberto Enciso 
727e28b9357SCarlos Alberto Enciso   std::function<void(LVScope * Scope)> TraverseChildren = [&](LVScope *Scope) {
728e28b9357SCarlos Alberto Enciso     auto Traverse = [&](const auto *Set) {
729e28b9357SCarlos Alberto Enciso       if (Set)
730e28b9357SCarlos Alberto Enciso         for (const auto &Entry : *Set)
731e28b9357SCarlos Alberto Enciso           (Entry->*SetFunction)();
732e28b9357SCarlos Alberto Enciso     };
733e28b9357SCarlos Alberto Enciso 
734e28b9357SCarlos Alberto Enciso     (Scope->*SetFunction)();
735e28b9357SCarlos Alberto Enciso 
736e28b9357SCarlos Alberto Enciso     Traverse(Scope->getTypes());
737e28b9357SCarlos Alberto Enciso     Traverse(Scope->getSymbols());
738e28b9357SCarlos Alberto Enciso     Traverse(Scope->getLines());
739e28b9357SCarlos Alberto Enciso 
740e28b9357SCarlos Alberto Enciso     if (const LVScopes *Scopes = Scope->getScopes())
741e28b9357SCarlos Alberto Enciso       for (LVScope *Scope : *Scopes)
742e28b9357SCarlos Alberto Enciso         TraverseChildren(Scope);
743e28b9357SCarlos Alberto Enciso   };
744e28b9357SCarlos Alberto Enciso 
745e28b9357SCarlos Alberto Enciso   if (options().getReportChildren())
746e28b9357SCarlos Alberto Enciso     TraverseChildren(this);
747e28b9357SCarlos Alberto Enciso }
748e28b9357SCarlos Alberto Enciso 
7493c397c90SCarlos Alberto Enciso // Traverse the symbol location ranges and for each range:
7503c397c90SCarlos Alberto Enciso // - Apply the 'ValidLocation' validation criteria.
7513c397c90SCarlos Alberto Enciso // - Add any failed range to the 'LocationList'.
7523c397c90SCarlos Alberto Enciso // - Calculate location coverage.
getLocations(LVLocations & LocationList,LVValidLocation ValidLocation,bool RecordInvalid)7533c397c90SCarlos Alberto Enciso void LVScope::getLocations(LVLocations &LocationList,
7543c397c90SCarlos Alberto Enciso                            LVValidLocation ValidLocation, bool RecordInvalid) {
7553c397c90SCarlos Alberto Enciso   // Traverse scopes and symbols.
7563c397c90SCarlos Alberto Enciso   if (Symbols)
7573c397c90SCarlos Alberto Enciso     for (LVSymbol *Symbol : *Symbols)
7583c397c90SCarlos Alberto Enciso       Symbol->getLocations(LocationList, ValidLocation, RecordInvalid);
7593c397c90SCarlos Alberto Enciso   if (Scopes)
7603c397c90SCarlos Alberto Enciso     for (LVScope *Scope : *Scopes)
7613c397c90SCarlos Alberto Enciso       Scope->getLocations(LocationList, ValidLocation, RecordInvalid);
7623c397c90SCarlos Alberto Enciso }
7633c397c90SCarlos Alberto Enciso 
7643c397c90SCarlos Alberto Enciso // Traverse the scope ranges and for each range:
7653c397c90SCarlos Alberto Enciso // - Apply the 'ValidLocation' validation criteria.
7663c397c90SCarlos Alberto Enciso // - Add any failed range to the 'LocationList'.
7673c397c90SCarlos Alberto Enciso // - Calculate location coverage.
getRanges(LVLocations & LocationList,LVValidLocation ValidLocation,bool RecordInvalid)7683c397c90SCarlos Alberto Enciso void LVScope::getRanges(LVLocations &LocationList,
7693c397c90SCarlos Alberto Enciso                         LVValidLocation ValidLocation, bool RecordInvalid) {
7703c397c90SCarlos Alberto Enciso   // Ignore discarded or stripped scopes (functions).
7713c397c90SCarlos Alberto Enciso   if (getIsDiscarded())
7723c397c90SCarlos Alberto Enciso     return;
7733c397c90SCarlos Alberto Enciso 
7743c397c90SCarlos Alberto Enciso   // Process the ranges for current scope.
7753c397c90SCarlos Alberto Enciso   if (Ranges) {
7763c397c90SCarlos Alberto Enciso     for (LVLocation *Location : *Ranges) {
7773c397c90SCarlos Alberto Enciso       // Add the invalid location object.
7783c397c90SCarlos Alberto Enciso       if (!(Location->*ValidLocation)() && RecordInvalid)
7793c397c90SCarlos Alberto Enciso         LocationList.push_back(Location);
7803c397c90SCarlos Alberto Enciso     }
7813c397c90SCarlos Alberto Enciso 
7823c397c90SCarlos Alberto Enciso     // Calculate coverage factor.
7833c397c90SCarlos Alberto Enciso     calculateCoverage();
7843c397c90SCarlos Alberto Enciso   }
7853c397c90SCarlos Alberto Enciso 
7863c397c90SCarlos Alberto Enciso   // Traverse the scopes.
7873c397c90SCarlos Alberto Enciso   if (Scopes)
7883c397c90SCarlos Alberto Enciso     for (LVScope *Scope : *Scopes)
7893c397c90SCarlos Alberto Enciso       Scope->getRanges(LocationList, ValidLocation, RecordInvalid);
7903c397c90SCarlos Alberto Enciso }
7913c397c90SCarlos Alberto Enciso 
7923c397c90SCarlos Alberto Enciso // Get all the ranges associated with scopes.
getRanges(LVRange & RangeList)7933c397c90SCarlos Alberto Enciso void LVScope::getRanges(LVRange &RangeList) {
7943c397c90SCarlos Alberto Enciso   // Ignore discarded or stripped scopes (functions).
7953c397c90SCarlos Alberto Enciso   if (getIsDiscarded())
7963c397c90SCarlos Alberto Enciso     return;
7973c397c90SCarlos Alberto Enciso 
7983c397c90SCarlos Alberto Enciso   if (Ranges)
7993c397c90SCarlos Alberto Enciso     RangeList.addEntry(this);
8003c397c90SCarlos Alberto Enciso   if (Scopes)
8013c397c90SCarlos Alberto Enciso     for (LVScope *Scope : *Scopes)
8023c397c90SCarlos Alberto Enciso       Scope->getRanges(RangeList);
8033c397c90SCarlos Alberto Enciso }
8043c397c90SCarlos Alberto Enciso 
outermostParent(LVAddress Address)8053c397c90SCarlos Alberto Enciso LVScope *LVScope::outermostParent(LVAddress Address) {
8063c397c90SCarlos Alberto Enciso   LVScope *Parent = this;
8073c397c90SCarlos Alberto Enciso   while (Parent) {
8083c397c90SCarlos Alberto Enciso     const LVLocations *ParentRanges = Parent->getRanges();
8093c397c90SCarlos Alberto Enciso     if (ParentRanges)
8103c397c90SCarlos Alberto Enciso       for (const LVLocation *Location : *ParentRanges)
8113c397c90SCarlos Alberto Enciso         if (Location->getLowerAddress() <= Address)
8123c397c90SCarlos Alberto Enciso           return Parent;
8133c397c90SCarlos Alberto Enciso     Parent = Parent->getParentScope();
8143c397c90SCarlos Alberto Enciso   }
8153c397c90SCarlos Alberto Enciso   return Parent;
8163c397c90SCarlos Alberto Enciso }
8173c397c90SCarlos Alberto Enciso 
findIn(const LVScopes * Targets) const818e98a4c5aSCarlos Alberto Enciso LVScope *LVScope::findIn(const LVScopes *Targets) const {
819e98a4c5aSCarlos Alberto Enciso   if (!Targets)
820e98a4c5aSCarlos Alberto Enciso     return nullptr;
821e98a4c5aSCarlos Alberto Enciso 
822e98a4c5aSCarlos Alberto Enciso   // In the case of overloaded functions, sometimes the DWARF used to
823e98a4c5aSCarlos Alberto Enciso   // describe them, does not give suficient information. Try to find a
824e98a4c5aSCarlos Alberto Enciso   // perfect match or mark them as possible conflicts.
825e98a4c5aSCarlos Alberto Enciso   LVScopes Candidates;
826e98a4c5aSCarlos Alberto Enciso   for (LVScope *Target : *Targets)
827e98a4c5aSCarlos Alberto Enciso     if (LVScope::equals(Target))
828e98a4c5aSCarlos Alberto Enciso       Candidates.push_back(Target);
829e98a4c5aSCarlos Alberto Enciso 
830e98a4c5aSCarlos Alberto Enciso   LLVM_DEBUG({
831e98a4c5aSCarlos Alberto Enciso     if (!Candidates.empty()) {
832e98a4c5aSCarlos Alberto Enciso       dbgs() << "\n[LVScope::findIn]\n"
833e98a4c5aSCarlos Alberto Enciso              << "Reference: "
834e98a4c5aSCarlos Alberto Enciso              << "Offset = " << hexSquareString(getOffset()) << ", "
835e98a4c5aSCarlos Alberto Enciso              << "Level = " << getLevel() << ", "
836e98a4c5aSCarlos Alberto Enciso              << "Kind = " << formattedKind(kind()) << ", "
837e98a4c5aSCarlos Alberto Enciso              << "Name = " << formattedName(getName()) << "\n";
838e98a4c5aSCarlos Alberto Enciso       for (const LVScope *Candidate : Candidates)
839e98a4c5aSCarlos Alberto Enciso         dbgs() << "Candidate: "
840e98a4c5aSCarlos Alberto Enciso                << "Offset = " << hexSquareString(Candidate->getOffset()) << ", "
841e98a4c5aSCarlos Alberto Enciso                << "Level = " << Candidate->getLevel() << ", "
842e98a4c5aSCarlos Alberto Enciso                << "Kind = " << formattedKind(Candidate->kind()) << ", "
843e98a4c5aSCarlos Alberto Enciso                << "Name = " << formattedName(Candidate->getName()) << "\n";
844e98a4c5aSCarlos Alberto Enciso     }
845e98a4c5aSCarlos Alberto Enciso   });
846e98a4c5aSCarlos Alberto Enciso 
847e98a4c5aSCarlos Alberto Enciso   if (!Candidates.empty())
848e98a4c5aSCarlos Alberto Enciso     return (Candidates.size() == 1)
849e98a4c5aSCarlos Alberto Enciso                ? (equals(Candidates[0]) ? Candidates[0] : nullptr)
850e98a4c5aSCarlos Alberto Enciso                : findEqualScope(&Candidates);
851e98a4c5aSCarlos Alberto Enciso 
852e98a4c5aSCarlos Alberto Enciso   return nullptr;
853e98a4c5aSCarlos Alberto Enciso }
854e98a4c5aSCarlos Alberto Enciso 
equalNumberOfChildren(const LVScope * Scope) const855e98a4c5aSCarlos Alberto Enciso bool LVScope::equalNumberOfChildren(const LVScope *Scope) const {
856e98a4c5aSCarlos Alberto Enciso   // Same number of children. Take into account which elements are requested
857e98a4c5aSCarlos Alberto Enciso   // to be included in the comparison.
858e98a4c5aSCarlos Alberto Enciso   return !(
859e98a4c5aSCarlos Alberto Enciso       (options().getCompareScopes() && scopeCount() != Scope->scopeCount()) ||
860e98a4c5aSCarlos Alberto Enciso       (options().getCompareSymbols() &&
861e98a4c5aSCarlos Alberto Enciso        symbolCount() != Scope->symbolCount()) ||
862e98a4c5aSCarlos Alberto Enciso       (options().getCompareTypes() && typeCount() != Scope->typeCount()) ||
863e98a4c5aSCarlos Alberto Enciso       (options().getCompareLines() && lineCount() != Scope->lineCount()));
864e98a4c5aSCarlos Alberto Enciso }
865e98a4c5aSCarlos Alberto Enciso 
markMissingParents(const LVScope * Target,bool TraverseChildren)866e98a4c5aSCarlos Alberto Enciso void LVScope::markMissingParents(const LVScope *Target, bool TraverseChildren) {
8677fbcc244SCarlos Alberto Enciso   auto SetCompareState = [&](auto &Container) {
868e98a4c5aSCarlos Alberto Enciso     if (Container)
869e98a4c5aSCarlos Alberto Enciso       for (auto *Entry : *Container)
870e98a4c5aSCarlos Alberto Enciso         Entry->setIsInCompare();
871e98a4c5aSCarlos Alberto Enciso   };
872e98a4c5aSCarlos Alberto Enciso   SetCompareState(Types);
873e98a4c5aSCarlos Alberto Enciso   SetCompareState(Symbols);
874e98a4c5aSCarlos Alberto Enciso   SetCompareState(Lines);
875e98a4c5aSCarlos Alberto Enciso   SetCompareState(Scopes);
876e98a4c5aSCarlos Alberto Enciso 
877e98a4c5aSCarlos Alberto Enciso   // At this point, we are ready to start comparing the current scope, once
878e98a4c5aSCarlos Alberto Enciso   // the compare bits have been set.
879e98a4c5aSCarlos Alberto Enciso   if (options().getCompareTypes() && getTypes() && Target->getTypes())
880e98a4c5aSCarlos Alberto Enciso     LVType::markMissingParents(getTypes(), Target->getTypes());
881e98a4c5aSCarlos Alberto Enciso   if (options().getCompareSymbols() && getSymbols() && Target->getSymbols())
882e98a4c5aSCarlos Alberto Enciso     LVSymbol::markMissingParents(getSymbols(), Target->getSymbols());
883e98a4c5aSCarlos Alberto Enciso   if (options().getCompareLines() && getLines() && Target->getLines())
884e98a4c5aSCarlos Alberto Enciso     LVLine::markMissingParents(getLines(), Target->getLines());
885e98a4c5aSCarlos Alberto Enciso   if (getScopes() && Target->getScopes())
886e98a4c5aSCarlos Alberto Enciso     LVScope::markMissingParents(getScopes(), Target->getScopes(),
887e98a4c5aSCarlos Alberto Enciso                                 TraverseChildren);
888e98a4c5aSCarlos Alberto Enciso }
889e98a4c5aSCarlos Alberto Enciso 
markMissingParents(const LVScopes * References,const LVScopes * Targets,bool TraverseChildren)890e98a4c5aSCarlos Alberto Enciso void LVScope::markMissingParents(const LVScopes *References,
891e98a4c5aSCarlos Alberto Enciso                                  const LVScopes *Targets,
892e98a4c5aSCarlos Alberto Enciso                                  bool TraverseChildren) {
893e98a4c5aSCarlos Alberto Enciso   if (!(References && Targets))
894e98a4c5aSCarlos Alberto Enciso     return;
895e98a4c5aSCarlos Alberto Enciso 
896e98a4c5aSCarlos Alberto Enciso   LLVM_DEBUG({
897e98a4c5aSCarlos Alberto Enciso     dbgs() << "\n[LVScope::markMissingParents]\n";
898e98a4c5aSCarlos Alberto Enciso     for (const LVScope *Reference : *References)
899e98a4c5aSCarlos Alberto Enciso       dbgs() << "References: "
900e98a4c5aSCarlos Alberto Enciso              << "Offset = " << hexSquareString(Reference->getOffset()) << ", "
901e98a4c5aSCarlos Alberto Enciso              << "Level = " << Reference->getLevel() << ", "
902e98a4c5aSCarlos Alberto Enciso              << "Kind = " << formattedKind(Reference->kind()) << ", "
903e98a4c5aSCarlos Alberto Enciso              << "Name = " << formattedName(Reference->getName()) << "\n";
904e98a4c5aSCarlos Alberto Enciso     for (const LVScope *Target : *Targets)
905e98a4c5aSCarlos Alberto Enciso       dbgs() << "Targets   : "
906e98a4c5aSCarlos Alberto Enciso              << "Offset = " << hexSquareString(Target->getOffset()) << ", "
907e98a4c5aSCarlos Alberto Enciso              << "Level = " << Target->getLevel() << ", "
908e98a4c5aSCarlos Alberto Enciso              << "Kind = " << formattedKind(Target->kind()) << ", "
909e98a4c5aSCarlos Alberto Enciso              << "Name = " << formattedName(Target->getName()) << "\n";
910e98a4c5aSCarlos Alberto Enciso   });
911e98a4c5aSCarlos Alberto Enciso 
912e98a4c5aSCarlos Alberto Enciso   for (LVScope *Reference : *References) {
913e98a4c5aSCarlos Alberto Enciso     // Don't process 'Block' scopes, as we can't identify them.
914e98a4c5aSCarlos Alberto Enciso     if (Reference->getIsBlock() || Reference->getIsGeneratedName())
915e98a4c5aSCarlos Alberto Enciso       continue;
916e98a4c5aSCarlos Alberto Enciso 
917e98a4c5aSCarlos Alberto Enciso     LLVM_DEBUG({
918e98a4c5aSCarlos Alberto Enciso       dbgs() << "\nSearch Reference: "
919e98a4c5aSCarlos Alberto Enciso              << "Offset = " << hexSquareString(Reference->getOffset()) << " "
920e98a4c5aSCarlos Alberto Enciso              << "Name = " << formattedName(Reference->getName()) << "\n";
921e98a4c5aSCarlos Alberto Enciso     });
922e98a4c5aSCarlos Alberto Enciso     LVScope *Target = Reference->findIn(Targets);
923e98a4c5aSCarlos Alberto Enciso     if (Target) {
924e98a4c5aSCarlos Alberto Enciso       LLVM_DEBUG({
925e98a4c5aSCarlos Alberto Enciso         dbgs() << "\nFound Target: "
926e98a4c5aSCarlos Alberto Enciso                << "Offset = " << hexSquareString(Target->getOffset()) << " "
927e98a4c5aSCarlos Alberto Enciso                << "Name = " << formattedName(Target->getName()) << "\n";
928e98a4c5aSCarlos Alberto Enciso       });
929e98a4c5aSCarlos Alberto Enciso       if (TraverseChildren)
930e98a4c5aSCarlos Alberto Enciso         Reference->markMissingParents(Target, TraverseChildren);
931e98a4c5aSCarlos Alberto Enciso     } else {
932e98a4c5aSCarlos Alberto Enciso       LLVM_DEBUG({
933e98a4c5aSCarlos Alberto Enciso         dbgs() << "Missing Reference: "
934e98a4c5aSCarlos Alberto Enciso                << "Offset = " << hexSquareString(Reference->getOffset()) << " "
935e98a4c5aSCarlos Alberto Enciso                << "Name = " << formattedName(Reference->getName()) << "\n";
936e98a4c5aSCarlos Alberto Enciso       });
937e98a4c5aSCarlos Alberto Enciso       Reference->markBranchAsMissing();
938e98a4c5aSCarlos Alberto Enciso     }
939e98a4c5aSCarlos Alberto Enciso   }
940e98a4c5aSCarlos Alberto Enciso }
941e98a4c5aSCarlos Alberto Enciso 
equals(const LVScope * Scope) const942e98a4c5aSCarlos Alberto Enciso bool LVScope::equals(const LVScope *Scope) const {
943e98a4c5aSCarlos Alberto Enciso   if (!LVElement::equals(Scope))
944e98a4c5aSCarlos Alberto Enciso     return false;
945e98a4c5aSCarlos Alberto Enciso   // For lexical scopes, check if their parents are the same.
946e98a4c5aSCarlos Alberto Enciso   if (getIsLexicalBlock() && Scope->getIsLexicalBlock())
947e98a4c5aSCarlos Alberto Enciso     return getParentScope()->equals(Scope->getParentScope());
948e98a4c5aSCarlos Alberto Enciso   return true;
949e98a4c5aSCarlos Alberto Enciso }
950e98a4c5aSCarlos Alberto Enciso 
findEqualScope(const LVScopes * Scopes) const951e98a4c5aSCarlos Alberto Enciso LVScope *LVScope::findEqualScope(const LVScopes *Scopes) const {
952e98a4c5aSCarlos Alberto Enciso   assert(Scopes && "Scopes must not be nullptr");
953e98a4c5aSCarlos Alberto Enciso   for (LVScope *Scope : *Scopes)
954e98a4c5aSCarlos Alberto Enciso     if (equals(Scope))
955e98a4c5aSCarlos Alberto Enciso       return Scope;
956e98a4c5aSCarlos Alberto Enciso   return nullptr;
957e98a4c5aSCarlos Alberto Enciso }
958e98a4c5aSCarlos Alberto Enciso 
equals(const LVScopes * References,const LVScopes * Targets)959e98a4c5aSCarlos Alberto Enciso bool LVScope::equals(const LVScopes *References, const LVScopes *Targets) {
960e98a4c5aSCarlos Alberto Enciso   if (!References && !Targets)
961e98a4c5aSCarlos Alberto Enciso     return true;
962e98a4c5aSCarlos Alberto Enciso   if (References && Targets && References->size() == Targets->size()) {
963e98a4c5aSCarlos Alberto Enciso     for (const LVScope *Reference : *References)
964e98a4c5aSCarlos Alberto Enciso       if (!Reference->findIn(Targets))
965e98a4c5aSCarlos Alberto Enciso         return false;
966e98a4c5aSCarlos Alberto Enciso     return true;
967e98a4c5aSCarlos Alberto Enciso   }
968e98a4c5aSCarlos Alberto Enciso   return false;
969e98a4c5aSCarlos Alberto Enciso }
970e98a4c5aSCarlos Alberto Enciso 
report(LVComparePass Pass)971e98a4c5aSCarlos Alberto Enciso void LVScope::report(LVComparePass Pass) {
972e98a4c5aSCarlos Alberto Enciso   getComparator().printItem(this, Pass);
973e98a4c5aSCarlos Alberto Enciso   getComparator().push(this);
974e98a4c5aSCarlos Alberto Enciso   if (Children)
975e98a4c5aSCarlos Alberto Enciso     for (LVElement *Element : *Children)
976e98a4c5aSCarlos Alberto Enciso       Element->report(Pass);
977e98a4c5aSCarlos Alberto Enciso 
978e98a4c5aSCarlos Alberto Enciso   if (Lines)
979e98a4c5aSCarlos Alberto Enciso     for (LVLine *Line : *Lines)
980e98a4c5aSCarlos Alberto Enciso       Line->report(Pass);
981e98a4c5aSCarlos Alberto Enciso   getComparator().pop();
982e98a4c5aSCarlos Alberto Enciso }
983e98a4c5aSCarlos Alberto Enciso 
printActiveRanges(raw_ostream & OS,bool Full) const9843c397c90SCarlos Alberto Enciso void LVScope::printActiveRanges(raw_ostream &OS, bool Full) const {
9853c397c90SCarlos Alberto Enciso   if (options().getPrintFormatting() && options().getAttributeRange() &&
9863c397c90SCarlos Alberto Enciso       Ranges) {
9873c397c90SCarlos Alberto Enciso     for (const LVLocation *Location : *Ranges)
9883c397c90SCarlos Alberto Enciso       Location->print(OS, Full);
9893c397c90SCarlos Alberto Enciso   }
9903c397c90SCarlos Alberto Enciso }
9913c397c90SCarlos Alberto Enciso 
printEncodedArgs(raw_ostream & OS,bool Full) const992e28b9357SCarlos Alberto Enciso void LVScope::printEncodedArgs(raw_ostream &OS, bool Full) const {
993e28b9357SCarlos Alberto Enciso   if (options().getPrintFormatting() && options().getAttributeEncoded())
994e28b9357SCarlos Alberto Enciso     printAttributes(OS, Full, "{Encoded} ", const_cast<LVScope *>(this),
995e28b9357SCarlos Alberto Enciso                     getEncodedArgs(), /*UseQuotes=*/false, /*PrintRef=*/false);
996e28b9357SCarlos Alberto Enciso }
997e28b9357SCarlos Alberto Enciso 
print(raw_ostream & OS,bool Full) const998e28b9357SCarlos Alberto Enciso void LVScope::print(raw_ostream &OS, bool Full) const {
999e28b9357SCarlos Alberto Enciso   if (getIncludeInPrint() && getReader().doPrintScope(this)) {
1000e28b9357SCarlos Alberto Enciso     // For a summary (printed elements), do not count the scope root.
10010332a8e7SCarlos Alberto Enciso     // For a summary (selected elements) do not count a compile unit.
10020332a8e7SCarlos Alberto Enciso     if (!(getIsRoot() || (getIsCompileUnit() && options().getSelectExecute())))
1003e28b9357SCarlos Alberto Enciso       getReaderCompileUnit()->incrementPrintedScopes();
1004e28b9357SCarlos Alberto Enciso     LVElement::print(OS, Full);
1005e28b9357SCarlos Alberto Enciso     printExtra(OS, Full);
1006e28b9357SCarlos Alberto Enciso   }
1007e28b9357SCarlos Alberto Enciso }
1008e28b9357SCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1009e28b9357SCarlos Alberto Enciso void LVScope::printExtra(raw_ostream &OS, bool Full) const {
1010e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind());
1011e28b9357SCarlos Alberto Enciso   // Do not print any type or name for a lexical block.
1012e28b9357SCarlos Alberto Enciso   if (!getIsBlock()) {
1013e28b9357SCarlos Alberto Enciso     OS << " " << formattedName(getName());
1014e28b9357SCarlos Alberto Enciso     if (!getIsAggregate())
1015e28b9357SCarlos Alberto Enciso       OS << " -> " << typeOffsetAsString()
1016e28b9357SCarlos Alberto Enciso          << formattedNames(getTypeQualifiedName(), typeAsString());
1017e28b9357SCarlos Alberto Enciso   }
1018e28b9357SCarlos Alberto Enciso   OS << "\n";
10193c397c90SCarlos Alberto Enciso 
10203c397c90SCarlos Alberto Enciso   // Print any active ranges.
10213c397c90SCarlos Alberto Enciso   if (Full && getIsBlock())
10223c397c90SCarlos Alberto Enciso     printActiveRanges(OS, Full);
1023e28b9357SCarlos Alberto Enciso }
1024e28b9357SCarlos Alberto Enciso 
1025e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1026e28b9357SCarlos Alberto Enciso // DWARF Union/Structure/Class.
1027e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1028e98a4c5aSCarlos Alberto Enciso bool LVScopeAggregate::equals(const LVScope *Scope) const {
1029e98a4c5aSCarlos Alberto Enciso   if (!LVScope::equals(Scope))
1030e98a4c5aSCarlos Alberto Enciso     return false;
1031e98a4c5aSCarlos Alberto Enciso 
1032e98a4c5aSCarlos Alberto Enciso   if (!equalNumberOfChildren(Scope))
1033e98a4c5aSCarlos Alberto Enciso     return false;
1034e98a4c5aSCarlos Alberto Enciso 
1035e98a4c5aSCarlos Alberto Enciso   // Check if the parameters match in the case of templates.
1036e98a4c5aSCarlos Alberto Enciso   if (!LVType::parametersMatch(getTypes(), Scope->getTypes()))
1037e98a4c5aSCarlos Alberto Enciso     return false;
1038e98a4c5aSCarlos Alberto Enciso 
1039e98a4c5aSCarlos Alberto Enciso   if (!isNamed() && !Scope->isNamed())
1040e98a4c5aSCarlos Alberto Enciso     // In the case of unnamed union/structure/class compare the file name.
1041e98a4c5aSCarlos Alberto Enciso     if (getFilenameIndex() != Scope->getFilenameIndex())
1042e98a4c5aSCarlos Alberto Enciso       return false;
1043e98a4c5aSCarlos Alberto Enciso 
1044e98a4c5aSCarlos Alberto Enciso   return true;
1045e98a4c5aSCarlos Alberto Enciso }
1046e98a4c5aSCarlos Alberto Enciso 
findEqualScope(const LVScopes * Scopes) const1047e98a4c5aSCarlos Alberto Enciso LVScope *LVScopeAggregate::findEqualScope(const LVScopes *Scopes) const {
1048e98a4c5aSCarlos Alberto Enciso   assert(Scopes && "Scopes must not be nullptr");
1049e98a4c5aSCarlos Alberto Enciso   for (LVScope *Scope : *Scopes)
1050e98a4c5aSCarlos Alberto Enciso     if (equals(Scope))
1051e98a4c5aSCarlos Alberto Enciso       return Scope;
1052e98a4c5aSCarlos Alberto Enciso   return nullptr;
1053e98a4c5aSCarlos Alberto Enciso }
1054e98a4c5aSCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1055e28b9357SCarlos Alberto Enciso void LVScopeAggregate::printExtra(raw_ostream &OS, bool Full) const {
1056e28b9357SCarlos Alberto Enciso   LVScope::printExtra(OS, Full);
1057e28b9357SCarlos Alberto Enciso   if (Full) {
1058e28b9357SCarlos Alberto Enciso     if (getIsTemplateResolved())
1059e28b9357SCarlos Alberto Enciso       printEncodedArgs(OS, Full);
1060e28b9357SCarlos Alberto Enciso     LVScope *Reference = getReference();
1061e28b9357SCarlos Alberto Enciso     if (Reference)
1062e28b9357SCarlos Alberto Enciso       Reference->printReference(OS, Full, const_cast<LVScopeAggregate *>(this));
1063e28b9357SCarlos Alberto Enciso   }
1064e28b9357SCarlos Alberto Enciso }
1065e28b9357SCarlos Alberto Enciso 
1066e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1067e28b9357SCarlos Alberto Enciso // DWARF Template alias.
1068e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1069e98a4c5aSCarlos Alberto Enciso bool LVScopeAlias::equals(const LVScope *Scope) const {
1070e98a4c5aSCarlos Alberto Enciso   if (!LVScope::equals(Scope))
1071e98a4c5aSCarlos Alberto Enciso     return false;
1072e98a4c5aSCarlos Alberto Enciso   return equalNumberOfChildren(Scope);
1073e98a4c5aSCarlos Alberto Enciso }
1074e98a4c5aSCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1075e28b9357SCarlos Alberto Enciso void LVScopeAlias::printExtra(raw_ostream &OS, bool Full) const {
1076e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "
1077e28b9357SCarlos Alberto Enciso      << typeOffsetAsString()
1078e28b9357SCarlos Alberto Enciso      << formattedNames(getTypeQualifiedName(), typeAsString()) << "\n";
1079e28b9357SCarlos Alberto Enciso }
1080e28b9357SCarlos Alberto Enciso 
1081e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1082e28b9357SCarlos Alberto Enciso // DWARF array (DW_TAG_array_type).
1083e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
resolveExtra()1084e28b9357SCarlos Alberto Enciso void LVScopeArray::resolveExtra() {
1085e28b9357SCarlos Alberto Enciso   // If the scope is an array, resolve the subrange entries and get those
1086e28b9357SCarlos Alberto Enciso   // values encoded and assigned to the scope type.
1087e28b9357SCarlos Alberto Enciso   // Encode the array subrange entries as part of the name.
1088e28b9357SCarlos Alberto Enciso   if (getIsArrayResolved())
1089e28b9357SCarlos Alberto Enciso     return;
1090e28b9357SCarlos Alberto Enciso   setIsArrayResolved();
1091e28b9357SCarlos Alberto Enciso 
1092e28b9357SCarlos Alberto Enciso   // There are 2 cases to represent the bounds information for an array:
1093e28b9357SCarlos Alberto Enciso   // 1) DW_TAG_array_type
1094e28b9357SCarlos Alberto Enciso   //      DW_AT_type --> ref_type
1095e28b9357SCarlos Alberto Enciso   //      DW_TAG_subrange_type
1096e28b9357SCarlos Alberto Enciso   //        DW_AT_type --> ref_type (type of object)
1097e28b9357SCarlos Alberto Enciso   //        DW_AT_count --> value (number of elements in subrange)
1098e28b9357SCarlos Alberto Enciso 
1099e28b9357SCarlos Alberto Enciso   // 2) DW_TAG_array_type
1100e28b9357SCarlos Alberto Enciso   //      DW_AT_type --> ref_type
1101e28b9357SCarlos Alberto Enciso   //        DW_TAG_subrange_type
1102e28b9357SCarlos Alberto Enciso   //          DW_AT_lower_bound --> value
1103e28b9357SCarlos Alberto Enciso   //          DW_AT_upper_bound --> value
1104e28b9357SCarlos Alberto Enciso 
1105e28b9357SCarlos Alberto Enciso   // The idea is to represent the bounds as a string, depending on the format:
1106e28b9357SCarlos Alberto Enciso   // 1) [count]
1107e28b9357SCarlos Alberto Enciso   // 2) [lower][upper]
1108e28b9357SCarlos Alberto Enciso 
1109e28b9357SCarlos Alberto Enciso   // Traverse scope types, looking for those types that are subranges.
1110e28b9357SCarlos Alberto Enciso   LVTypes Subranges;
1111e28b9357SCarlos Alberto Enciso   if (const LVTypes *Types = getTypes())
1112e28b9357SCarlos Alberto Enciso     for (LVType *Type : *Types)
1113e28b9357SCarlos Alberto Enciso       if (Type->getIsSubrange()) {
1114e28b9357SCarlos Alberto Enciso         Type->resolve();
1115e28b9357SCarlos Alberto Enciso         Subranges.push_back(Type);
1116e28b9357SCarlos Alberto Enciso       }
1117e28b9357SCarlos Alberto Enciso 
1118e28b9357SCarlos Alberto Enciso   // Use the subrange types to generate the high level name for the array.
1119e28b9357SCarlos Alberto Enciso   // Check the type has been fully resolved.
1120e28b9357SCarlos Alberto Enciso   if (LVElement *BaseType = getType()) {
1121e28b9357SCarlos Alberto Enciso     BaseType->resolveName();
1122e28b9357SCarlos Alberto Enciso     resolveFullname(BaseType);
1123e28b9357SCarlos Alberto Enciso   }
1124e28b9357SCarlos Alberto Enciso 
1125e28b9357SCarlos Alberto Enciso   // In 'resolveFullname' a check is done for double spaces in the type name.
1126e28b9357SCarlos Alberto Enciso   std::stringstream ArrayInfo;
1127e28b9357SCarlos Alberto Enciso   if (ElementType)
1128e28b9357SCarlos Alberto Enciso     ArrayInfo << getTypeName().str() << " ";
1129e28b9357SCarlos Alberto Enciso 
1130e28b9357SCarlos Alberto Enciso   for (const LVType *Type : Subranges) {
1131e28b9357SCarlos Alberto Enciso     if (Type->getIsSubrangeCount())
1132e28b9357SCarlos Alberto Enciso       // Check if we have DW_AT_count subrange style.
1133e28b9357SCarlos Alberto Enciso       ArrayInfo << "[" << Type->getCount() << "]";
1134e28b9357SCarlos Alberto Enciso     else {
1135e28b9357SCarlos Alberto Enciso       // Get lower and upper subrange values.
1136e28b9357SCarlos Alberto Enciso       unsigned LowerBound;
1137e28b9357SCarlos Alberto Enciso       unsigned UpperBound;
1138e28b9357SCarlos Alberto Enciso       std::tie(LowerBound, UpperBound) = Type->getBounds();
1139e28b9357SCarlos Alberto Enciso 
1140e28b9357SCarlos Alberto Enciso       // The representation depends on the bound values. If the lower value
1141e28b9357SCarlos Alberto Enciso       // is zero, treat the pair as the elements count. Otherwise, just use
1142e28b9357SCarlos Alberto Enciso       // the pair, as they are representing arrays in languages other than
1143e28b9357SCarlos Alberto Enciso       // C/C++ and the lower limit is not zero.
1144e28b9357SCarlos Alberto Enciso       if (LowerBound)
1145e28b9357SCarlos Alberto Enciso         ArrayInfo << "[" << LowerBound << ".." << UpperBound << "]";
1146e28b9357SCarlos Alberto Enciso       else
1147e28b9357SCarlos Alberto Enciso         ArrayInfo << "[" << UpperBound + 1 << "]";
1148e28b9357SCarlos Alberto Enciso     }
1149e28b9357SCarlos Alberto Enciso   }
1150e28b9357SCarlos Alberto Enciso 
1151e28b9357SCarlos Alberto Enciso   // Update the scope name, to reflect the encoded subranges.
1152e28b9357SCarlos Alberto Enciso   setName(ArrayInfo.str());
1153e28b9357SCarlos Alberto Enciso }
1154e28b9357SCarlos Alberto Enciso 
equals(const LVScope * Scope) const1155e98a4c5aSCarlos Alberto Enciso bool LVScopeArray::equals(const LVScope *Scope) const {
1156e98a4c5aSCarlos Alberto Enciso   if (!LVScope::equals(Scope))
1157e98a4c5aSCarlos Alberto Enciso     return false;
1158e98a4c5aSCarlos Alberto Enciso 
1159e98a4c5aSCarlos Alberto Enciso   if (!equalNumberOfChildren(Scope))
1160e98a4c5aSCarlos Alberto Enciso     return false;
1161e98a4c5aSCarlos Alberto Enciso 
1162e98a4c5aSCarlos Alberto Enciso   // Despite the arrays are encoded, to reflect the dimensions, we have to
1163e98a4c5aSCarlos Alberto Enciso   // check the subranges, in order to determine if they are the same.
1164e98a4c5aSCarlos Alberto Enciso   if (!LVType::equals(getTypes(), Scope->getTypes()))
1165e98a4c5aSCarlos Alberto Enciso     return false;
1166e98a4c5aSCarlos Alberto Enciso 
1167e98a4c5aSCarlos Alberto Enciso   return true;
1168e98a4c5aSCarlos Alberto Enciso }
1169e98a4c5aSCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1170e28b9357SCarlos Alberto Enciso void LVScopeArray::printExtra(raw_ostream &OS, bool Full) const {
1171e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind()) << " " << typeOffsetAsString()
1172e28b9357SCarlos Alberto Enciso      << formattedName(getName()) << "\n";
1173e28b9357SCarlos Alberto Enciso }
1174e28b9357SCarlos Alberto Enciso 
1175e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1176e28b9357SCarlos Alberto Enciso // An object file (single or multiple CUs).
1177e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
addSize(LVScope * Scope,LVOffset Lower,LVOffset Upper)1178e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::addSize(LVScope *Scope, LVOffset Lower,
1179e28b9357SCarlos Alberto Enciso                                  LVOffset Upper) {
1180e28b9357SCarlos Alberto Enciso   LLVM_DEBUG({
1181e28b9357SCarlos Alberto Enciso     dbgs() << format(
11827292d051SMichał Górny         "CU [0x%08" PRIx64 "], Scope [0x%08" PRIx64 "], Range [0x%08" PRIx64
11837292d051SMichał Górny         ":0x%08" PRIx64 "], Size = %" PRId64 "\n",
1184e28b9357SCarlos Alberto Enciso         getOffset(), Scope->getOffset(), Lower, Upper, Upper - Lower);
1185e28b9357SCarlos Alberto Enciso   });
1186e28b9357SCarlos Alberto Enciso 
1187e28b9357SCarlos Alberto Enciso   // There is no need to check for a previous entry, as we are traversing the
1188e28b9357SCarlos Alberto Enciso   // debug information in sequential order.
1189e28b9357SCarlos Alberto Enciso   LVOffset Size = Upper - Lower;
1190e28b9357SCarlos Alberto Enciso   Sizes[Scope] = Size;
1191e28b9357SCarlos Alberto Enciso   if (this == Scope)
1192e28b9357SCarlos Alberto Enciso     // Record contribution size for the compilation unit.
1193e28b9357SCarlos Alberto Enciso     CUContributionSize = Size;
1194e28b9357SCarlos Alberto Enciso }
1195e28b9357SCarlos Alberto Enciso 
11960332a8e7SCarlos Alberto Enciso // Update parents and children with pattern information.
propagatePatternMatch()11970332a8e7SCarlos Alberto Enciso void LVScopeCompileUnit::propagatePatternMatch() {
11980332a8e7SCarlos Alberto Enciso   // At this stage, we have finished creating the Scopes tree and we have
11990332a8e7SCarlos Alberto Enciso   // a list of elements that match the pattern specified in the command line.
12000332a8e7SCarlos Alberto Enciso   // The pattern corresponds to a scope or element; mark parents and/or
12010332a8e7SCarlos Alberto Enciso   // children as having that pattern, before any printing is done.
12020332a8e7SCarlos Alberto Enciso   if (!options().getSelectExecute())
12030332a8e7SCarlos Alberto Enciso     return;
12040332a8e7SCarlos Alberto Enciso 
12050332a8e7SCarlos Alberto Enciso   if (MatchedScopes.size()) {
12060332a8e7SCarlos Alberto Enciso     for (LVScope *Scope : MatchedScopes)
12070332a8e7SCarlos Alberto Enciso       Scope->traverseParentsAndChildren(&LVScope::getHasPattern,
12080332a8e7SCarlos Alberto Enciso                                         &LVScope::setHasPattern);
12090332a8e7SCarlos Alberto Enciso   } else {
12100332a8e7SCarlos Alberto Enciso     // Mark the compile unit as having a pattern to enable any requests to
12110332a8e7SCarlos Alberto Enciso     // print sizes and summary as that information is recorded at that level.
12120332a8e7SCarlos Alberto Enciso     setHasPattern();
12130332a8e7SCarlos Alberto Enciso   }
12140332a8e7SCarlos Alberto Enciso }
12150332a8e7SCarlos Alberto Enciso 
processRangeLocationCoverage(LVValidLocation ValidLocation)12163c397c90SCarlos Alberto Enciso void LVScopeCompileUnit::processRangeLocationCoverage(
12173c397c90SCarlos Alberto Enciso     LVValidLocation ValidLocation) {
12183c397c90SCarlos Alberto Enciso   if (options().getAttributeRange()) {
12193c397c90SCarlos Alberto Enciso     // Traverse the scopes to get scopes that have invalid ranges.
12203c397c90SCarlos Alberto Enciso     LVLocations Locations;
12212c155d37SCarlos Alberto Enciso     bool RecordInvalid = options().getWarningRanges();
12223c397c90SCarlos Alberto Enciso     getRanges(Locations, ValidLocation, RecordInvalid);
12232c155d37SCarlos Alberto Enciso 
12242c155d37SCarlos Alberto Enciso     // Validate ranges associated with scopes.
12252c155d37SCarlos Alberto Enciso     if (RecordInvalid)
12262c155d37SCarlos Alberto Enciso       for (LVLocation *Location : Locations)
12272c155d37SCarlos Alberto Enciso         addInvalidRange(Location);
12283c397c90SCarlos Alberto Enciso   }
12293c397c90SCarlos Alberto Enciso 
12303c397c90SCarlos Alberto Enciso   if (options().getAttributeLocation()) {
12313c397c90SCarlos Alberto Enciso     // Traverse the scopes to get locations that have invalid ranges.
12323c397c90SCarlos Alberto Enciso     LVLocations Locations;
12332c155d37SCarlos Alberto Enciso     bool RecordInvalid = options().getWarningLocations();
12343c397c90SCarlos Alberto Enciso     getLocations(Locations, ValidLocation, RecordInvalid);
12352c155d37SCarlos Alberto Enciso 
12362c155d37SCarlos Alberto Enciso     // Validate ranges associated with locations.
12372c155d37SCarlos Alberto Enciso     if (RecordInvalid)
12382c155d37SCarlos Alberto Enciso       for (LVLocation *Location : Locations)
12392c155d37SCarlos Alberto Enciso         addInvalidLocation(Location);
12403c397c90SCarlos Alberto Enciso   }
12413c397c90SCarlos Alberto Enciso }
12423c397c90SCarlos Alberto Enciso 
addMapping(LVLine * Line,LVSectionIndex SectionIndex)12434f06d46fSCarlos Alberto Enciso void LVScopeCompileUnit::addMapping(LVLine *Line, LVSectionIndex SectionIndex) {
12444f06d46fSCarlos Alberto Enciso   LVAddress Address = Line->getOffset();
12454f06d46fSCarlos Alberto Enciso   SectionMappings.add(SectionIndex, Address, Line);
1246e28b9357SCarlos Alberto Enciso }
1247e28b9357SCarlos Alberto Enciso 
lineLowerBound(LVAddress Address,LVScope * Scope) const12484f06d46fSCarlos Alberto Enciso LVLine *LVScopeCompileUnit::lineLowerBound(LVAddress Address,
12494f06d46fSCarlos Alberto Enciso                                            LVScope *Scope) const {
12504f06d46fSCarlos Alberto Enciso   LVSectionIndex SectionIndex = getReader().getSectionIndex(Scope);
12514f06d46fSCarlos Alberto Enciso   LVAddressToLine *Map = SectionMappings.findMap(SectionIndex);
12524f06d46fSCarlos Alberto Enciso   if (!Map || Map->empty())
12532c155d37SCarlos Alberto Enciso     return nullptr;
12544f06d46fSCarlos Alberto Enciso   LVAddressToLine::const_iterator Iter = Map->lower_bound(Address);
12554f06d46fSCarlos Alberto Enciso   return (Iter != Map->end()) ? Iter->second : nullptr;
12564f06d46fSCarlos Alberto Enciso }
12574f06d46fSCarlos Alberto Enciso 
lineUpperBound(LVAddress Address,LVScope * Scope) const12584f06d46fSCarlos Alberto Enciso LVLine *LVScopeCompileUnit::lineUpperBound(LVAddress Address,
12594f06d46fSCarlos Alberto Enciso                                            LVScope *Scope) const {
12604f06d46fSCarlos Alberto Enciso   LVSectionIndex SectionIndex = getReader().getSectionIndex(Scope);
12614f06d46fSCarlos Alberto Enciso   LVAddressToLine *Map = SectionMappings.findMap(SectionIndex);
12624f06d46fSCarlos Alberto Enciso   if (!Map || Map->empty())
12634f06d46fSCarlos Alberto Enciso     return nullptr;
12644f06d46fSCarlos Alberto Enciso   LVAddressToLine::const_iterator Iter = Map->upper_bound(Address);
12654f06d46fSCarlos Alberto Enciso   if (Iter != Map->begin())
1266e28b9357SCarlos Alberto Enciso     Iter = std::prev(Iter);
12672c155d37SCarlos Alberto Enciso   return Iter->second;
1268e28b9357SCarlos Alberto Enciso }
1269e28b9357SCarlos Alberto Enciso 
lineRange(LVLocation * Location) const12704f06d46fSCarlos Alberto Enciso LVLineRange LVScopeCompileUnit::lineRange(LVLocation *Location) const {
12714f06d46fSCarlos Alberto Enciso   // The parent of a location can be a symbol or a scope.
12724f06d46fSCarlos Alberto Enciso   LVElement *Element = Location->getParent();
12734f06d46fSCarlos Alberto Enciso   LVScope *Parent = Element->getIsScope() ? static_cast<LVScope *>(Element)
12744f06d46fSCarlos Alberto Enciso                                           : Element->getParentScope();
12754f06d46fSCarlos Alberto Enciso   LVLine *LowLine = lineLowerBound(Location->getLowerAddress(), Parent);
12764f06d46fSCarlos Alberto Enciso   LVLine *HighLine = lineUpperBound(Location->getUpperAddress(), Parent);
12774f06d46fSCarlos Alberto Enciso   return LVLineRange(LowLine, HighLine);
12784f06d46fSCarlos Alberto Enciso }
12794f06d46fSCarlos Alberto Enciso 
getFilename(size_t Index) const1280e28b9357SCarlos Alberto Enciso StringRef LVScopeCompileUnit::getFilename(size_t Index) const {
1281e28b9357SCarlos Alberto Enciso   if (Index <= 0 || Index > Filenames.size())
1282e28b9357SCarlos Alberto Enciso     return StringRef();
1283e28b9357SCarlos Alberto Enciso   return getStringPool().getString(Filenames[Index - 1]);
1284e28b9357SCarlos Alberto Enciso }
1285e28b9357SCarlos Alberto Enciso 
equals(const LVScope * Scope) const1286e98a4c5aSCarlos Alberto Enciso bool LVScopeCompileUnit::equals(const LVScope *Scope) const {
1287e98a4c5aSCarlos Alberto Enciso   if (!LVScope::equals(Scope))
1288e98a4c5aSCarlos Alberto Enciso     return false;
1289e98a4c5aSCarlos Alberto Enciso 
1290e98a4c5aSCarlos Alberto Enciso   return getNameIndex() == Scope->getNameIndex();
1291e98a4c5aSCarlos Alberto Enciso }
1292e98a4c5aSCarlos Alberto Enciso 
incrementPrintedLines()12930332a8e7SCarlos Alberto Enciso void LVScopeCompileUnit::incrementPrintedLines() {
12940332a8e7SCarlos Alberto Enciso   options().getSelectExecute() ? ++Found.Lines : ++Printed.Lines;
12950332a8e7SCarlos Alberto Enciso }
incrementPrintedScopes()12960332a8e7SCarlos Alberto Enciso void LVScopeCompileUnit::incrementPrintedScopes() {
12970332a8e7SCarlos Alberto Enciso   options().getSelectExecute() ? ++Found.Scopes : ++Printed.Scopes;
12980332a8e7SCarlos Alberto Enciso }
incrementPrintedSymbols()12990332a8e7SCarlos Alberto Enciso void LVScopeCompileUnit::incrementPrintedSymbols() {
13000332a8e7SCarlos Alberto Enciso   options().getSelectExecute() ? ++Found.Symbols : ++Printed.Symbols;
13010332a8e7SCarlos Alberto Enciso }
incrementPrintedTypes()13020332a8e7SCarlos Alberto Enciso void LVScopeCompileUnit::incrementPrintedTypes() {
13030332a8e7SCarlos Alberto Enciso   options().getSelectExecute() ? ++Found.Types : ++Printed.Types;
13040332a8e7SCarlos Alberto Enciso }
1305e28b9357SCarlos Alberto Enciso 
1306e28b9357SCarlos Alberto Enciso // Values are used by '--summary' option (allocated).
increment(LVLine * Line)1307e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::increment(LVLine *Line) {
1308e28b9357SCarlos Alberto Enciso   if (Line->getIncludeInPrint())
1309e28b9357SCarlos Alberto Enciso     ++Allocated.Lines;
1310e28b9357SCarlos Alberto Enciso }
increment(LVScope * Scope)1311e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::increment(LVScope *Scope) {
1312e28b9357SCarlos Alberto Enciso   if (Scope->getIncludeInPrint())
1313e28b9357SCarlos Alberto Enciso     ++Allocated.Scopes;
1314e28b9357SCarlos Alberto Enciso }
increment(LVSymbol * Symbol)1315e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::increment(LVSymbol *Symbol) {
1316e28b9357SCarlos Alberto Enciso   if (Symbol->getIncludeInPrint())
1317e28b9357SCarlos Alberto Enciso     ++Allocated.Symbols;
1318e28b9357SCarlos Alberto Enciso }
increment(LVType * Type)1319e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::increment(LVType *Type) {
1320e28b9357SCarlos Alberto Enciso   if (Type->getIncludeInPrint())
1321e28b9357SCarlos Alberto Enciso     ++Allocated.Types;
1322e28b9357SCarlos Alberto Enciso }
1323e28b9357SCarlos Alberto Enciso 
1324e28b9357SCarlos Alberto Enciso // A new element has been added to the scopes tree. Take the following steps:
1325e28b9357SCarlos Alberto Enciso // Increase the added element counters, for printing summary.
1326e98a4c5aSCarlos Alberto Enciso // During comparison notify the Reader of the new element.
addedElement(LVLine * Line)1327e98a4c5aSCarlos Alberto Enciso void LVScopeCompileUnit::addedElement(LVLine *Line) {
1328e98a4c5aSCarlos Alberto Enciso   increment(Line);
1329e98a4c5aSCarlos Alberto Enciso   getReader().notifyAddedElement(Line);
1330e98a4c5aSCarlos Alberto Enciso }
addedElement(LVScope * Scope)1331e98a4c5aSCarlos Alberto Enciso void LVScopeCompileUnit::addedElement(LVScope *Scope) {
1332e98a4c5aSCarlos Alberto Enciso   increment(Scope);
1333e98a4c5aSCarlos Alberto Enciso   getReader().notifyAddedElement(Scope);
1334e98a4c5aSCarlos Alberto Enciso }
addedElement(LVSymbol * Symbol)1335e98a4c5aSCarlos Alberto Enciso void LVScopeCompileUnit::addedElement(LVSymbol *Symbol) {
1336e98a4c5aSCarlos Alberto Enciso   increment(Symbol);
1337e98a4c5aSCarlos Alberto Enciso   getReader().notifyAddedElement(Symbol);
1338e98a4c5aSCarlos Alberto Enciso }
addedElement(LVType * Type)1339e98a4c5aSCarlos Alberto Enciso void LVScopeCompileUnit::addedElement(LVType *Type) {
1340e98a4c5aSCarlos Alberto Enciso   increment(Type);
1341e98a4c5aSCarlos Alberto Enciso   getReader().notifyAddedElement(Type);
1342e98a4c5aSCarlos Alberto Enciso }
1343e28b9357SCarlos Alberto Enciso 
13442c155d37SCarlos Alberto Enciso // Record unsuported DWARF tags.
addDebugTag(dwarf::Tag Target,LVOffset Offset)13452c155d37SCarlos Alberto Enciso void LVScopeCompileUnit::addDebugTag(dwarf::Tag Target, LVOffset Offset) {
13467fbcc244SCarlos Alberto Enciso   addItem<LVTagOffsetsMap, dwarf::Tag, LVOffset>(&DebugTags, Target, Offset);
13472c155d37SCarlos Alberto Enciso }
13482c155d37SCarlos Alberto Enciso 
13492c155d37SCarlos Alberto Enciso // Record elements with invalid offsets.
addInvalidOffset(LVOffset Offset,LVElement * Element)13502c155d37SCarlos Alberto Enciso void LVScopeCompileUnit::addInvalidOffset(LVOffset Offset, LVElement *Element) {
13512c155d37SCarlos Alberto Enciso   if (WarningOffsets.find(Offset) == WarningOffsets.end())
13522c155d37SCarlos Alberto Enciso     WarningOffsets.emplace(Offset, Element);
13532c155d37SCarlos Alberto Enciso }
13542c155d37SCarlos Alberto Enciso 
13552c155d37SCarlos Alberto Enciso // Record symbols with invalid coverage values.
addInvalidCoverage(LVSymbol * Symbol)13562c155d37SCarlos Alberto Enciso void LVScopeCompileUnit::addInvalidCoverage(LVSymbol *Symbol) {
13572c155d37SCarlos Alberto Enciso   LVOffset Offset = Symbol->getOffset();
13582c155d37SCarlos Alberto Enciso   if (InvalidCoverages.find(Offset) == InvalidCoverages.end())
13592c155d37SCarlos Alberto Enciso     InvalidCoverages.emplace(Offset, Symbol);
13602c155d37SCarlos Alberto Enciso }
13612c155d37SCarlos Alberto Enciso 
13622c155d37SCarlos Alberto Enciso // Record symbols with invalid locations.
addInvalidLocation(LVLocation * Location)13632c155d37SCarlos Alberto Enciso void LVScopeCompileUnit::addInvalidLocation(LVLocation *Location) {
13642c155d37SCarlos Alberto Enciso   addInvalidLocationOrRange(Location, Location->getParentSymbol(),
13652c155d37SCarlos Alberto Enciso                             &InvalidLocations);
13662c155d37SCarlos Alberto Enciso }
13672c155d37SCarlos Alberto Enciso 
13682c155d37SCarlos Alberto Enciso // Record scopes with invalid ranges.
addInvalidRange(LVLocation * Location)13692c155d37SCarlos Alberto Enciso void LVScopeCompileUnit::addInvalidRange(LVLocation *Location) {
13702c155d37SCarlos Alberto Enciso   addInvalidLocationOrRange(Location, Location->getParentScope(),
13712c155d37SCarlos Alberto Enciso                             &InvalidRanges);
13722c155d37SCarlos Alberto Enciso }
13732c155d37SCarlos Alberto Enciso 
13742c155d37SCarlos Alberto Enciso // Record line zero.
addLineZero(LVLine * Line)13752c155d37SCarlos Alberto Enciso void LVScopeCompileUnit::addLineZero(LVLine *Line) {
13762c155d37SCarlos Alberto Enciso   LVScope *Scope = Line->getParentScope();
13772c155d37SCarlos Alberto Enciso   LVOffset Offset = Scope->getOffset();
13782c155d37SCarlos Alberto Enciso   addInvalidOffset(Offset, Scope);
13797fbcc244SCarlos Alberto Enciso   addItem<LVOffsetLinesMap, LVOffset, LVLine *>(&LinesZero, Offset, Line);
13802c155d37SCarlos Alberto Enciso }
13812c155d37SCarlos Alberto Enciso 
printLocalNames(raw_ostream & OS,bool Full) const1382e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::printLocalNames(raw_ostream &OS, bool Full) const {
1383e28b9357SCarlos Alberto Enciso   if (!options().getPrintFormatting())
1384e28b9357SCarlos Alberto Enciso     return;
1385e28b9357SCarlos Alberto Enciso 
1386e28b9357SCarlos Alberto Enciso   // Calculate an indentation value, to preserve a nice layout.
1387e28b9357SCarlos Alberto Enciso   size_t Indentation = options().indentationSize() +
1388e28b9357SCarlos Alberto Enciso                        lineNumberAsString().length() +
1389e28b9357SCarlos Alberto Enciso                        indentAsString(getLevel() + 1).length() + 3;
1390e28b9357SCarlos Alberto Enciso 
1391e28b9357SCarlos Alberto Enciso   enum class Option { Directory, File };
1392e28b9357SCarlos Alberto Enciso   auto PrintNames = [&](Option Action) {
1393e28b9357SCarlos Alberto Enciso     StringRef Kind = Action == Option::Directory ? "Directory" : "File";
1394e28b9357SCarlos Alberto Enciso     std::set<std::string> UniqueNames;
1395e28b9357SCarlos Alberto Enciso     for (size_t Index : Filenames) {
1396e28b9357SCarlos Alberto Enciso       // In the case of missing directory name in the .debug_line table,
1397e28b9357SCarlos Alberto Enciso       // the returned string has a leading '/'.
1398e28b9357SCarlos Alberto Enciso       StringRef Name = getStringPool().getString(Index);
1399e28b9357SCarlos Alberto Enciso       size_t Pos = Name.rfind('/');
1400e28b9357SCarlos Alberto Enciso       if (Pos != std::string::npos)
1401e28b9357SCarlos Alberto Enciso         Name = (Action == Option::File) ? Name.substr(Pos + 1)
1402e28b9357SCarlos Alberto Enciso                                         : Name.substr(0, Pos);
1403e28b9357SCarlos Alberto Enciso       // Collect only unique names.
1404e28b9357SCarlos Alberto Enciso       UniqueNames.insert(std::string(Name));
1405e28b9357SCarlos Alberto Enciso     }
1406e28b9357SCarlos Alberto Enciso     for (const std::string &Name : UniqueNames)
1407e28b9357SCarlos Alberto Enciso       OS << std::string(Indentation, ' ') << formattedKind(Kind) << " "
1408e28b9357SCarlos Alberto Enciso          << formattedName(Name) << "\n";
1409e28b9357SCarlos Alberto Enciso   };
1410e28b9357SCarlos Alberto Enciso 
1411e28b9357SCarlos Alberto Enciso   if (options().getAttributeDirectories())
1412e28b9357SCarlos Alberto Enciso     PrintNames(Option::Directory);
1413e28b9357SCarlos Alberto Enciso   if (options().getAttributeFiles())
1414e28b9357SCarlos Alberto Enciso     PrintNames(Option::File);
14154f06d46fSCarlos Alberto Enciso   if (options().getAttributePublics()) {
14164f06d46fSCarlos Alberto Enciso     StringRef Kind = "Public";
14174f06d46fSCarlos Alberto Enciso     // The public names are indexed by 'LVScope *'. We want to print
14184f06d46fSCarlos Alberto Enciso     // them by logical element address, to show the scopes layout.
14194f06d46fSCarlos Alberto Enciso     using OffsetSorted = std::map<LVAddress, LVPublicNames::const_iterator>;
14204f06d46fSCarlos Alberto Enciso     OffsetSorted SortedNames;
14214f06d46fSCarlos Alberto Enciso     for (LVPublicNames::const_iterator Iter = PublicNames.begin();
14224f06d46fSCarlos Alberto Enciso          Iter != PublicNames.end(); ++Iter)
14234f06d46fSCarlos Alberto Enciso       SortedNames.emplace(Iter->first->getOffset(), Iter);
14244f06d46fSCarlos Alberto Enciso 
14254f06d46fSCarlos Alberto Enciso     LVPublicNames::const_iterator Iter;
14264f06d46fSCarlos Alberto Enciso     for (OffsetSorted::reference Entry : SortedNames) {
14274f06d46fSCarlos Alberto Enciso       Iter = Entry.second;
14284f06d46fSCarlos Alberto Enciso       OS << std::string(Indentation, ' ') << formattedKind(Kind) << " "
14294f06d46fSCarlos Alberto Enciso          << formattedName((*Iter).first->getName());
14304f06d46fSCarlos Alberto Enciso       if (options().getAttributeOffset()) {
14314f06d46fSCarlos Alberto Enciso         LVAddress Address = (*Iter).second.first;
14324f06d46fSCarlos Alberto Enciso         size_t Size = (*Iter).second.second;
14334f06d46fSCarlos Alberto Enciso         OS << " [" << hexString(Address) << ":" << hexString(Address + Size)
14344f06d46fSCarlos Alberto Enciso            << "]";
14354f06d46fSCarlos Alberto Enciso       }
14364f06d46fSCarlos Alberto Enciso       OS << "\n";
14374f06d46fSCarlos Alberto Enciso     }
14384f06d46fSCarlos Alberto Enciso   }
1439e28b9357SCarlos Alberto Enciso }
1440e28b9357SCarlos Alberto Enciso 
printWarnings(raw_ostream & OS,bool Full) const14412c155d37SCarlos Alberto Enciso void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const {
14422c155d37SCarlos Alberto Enciso   auto PrintHeader = [&](const char *Header) { OS << "\n" << Header << ":\n"; };
14432c155d37SCarlos Alberto Enciso   auto PrintFooter = [&](auto &Set) {
14442c155d37SCarlos Alberto Enciso     if (Set.empty())
14452c155d37SCarlos Alberto Enciso       OS << "None\n";
14462c155d37SCarlos Alberto Enciso   };
14472c155d37SCarlos Alberto Enciso   auto PrintOffset = [&](unsigned &Count, LVOffset Offset) {
14482c155d37SCarlos Alberto Enciso     if (Count == 5) {
14492c155d37SCarlos Alberto Enciso       Count = 0;
14502c155d37SCarlos Alberto Enciso       OS << "\n";
14512c155d37SCarlos Alberto Enciso     }
14522c155d37SCarlos Alberto Enciso     ++Count;
14532c155d37SCarlos Alberto Enciso     OS << hexSquareString(Offset) << " ";
14542c155d37SCarlos Alberto Enciso   };
14552c155d37SCarlos Alberto Enciso   auto PrintElement = [&](const LVOffsetElementMap &Map, LVOffset Offset) {
14562c155d37SCarlos Alberto Enciso     LVOffsetElementMap::const_iterator Iter = Map.find(Offset);
14572c155d37SCarlos Alberto Enciso     LVElement *Element = Iter != Map.end() ? Iter->second : nullptr;
14582c155d37SCarlos Alberto Enciso     OS << "[" << hexString(Offset) << "]";
14592c155d37SCarlos Alberto Enciso     if (Element)
14602c155d37SCarlos Alberto Enciso       OS << " " << formattedKind(Element->kind()) << " "
14612c155d37SCarlos Alberto Enciso          << formattedName(Element->getName());
14622c155d37SCarlos Alberto Enciso     OS << "\n";
14632c155d37SCarlos Alberto Enciso   };
14642c155d37SCarlos Alberto Enciso   auto PrintInvalidLocations = [&](const LVOffsetLocationsMap &Map,
14652c155d37SCarlos Alberto Enciso                                    const char *Header) {
14662c155d37SCarlos Alberto Enciso     PrintHeader(Header);
14672c155d37SCarlos Alberto Enciso     for (LVOffsetLocationsMap::const_reference Entry : Map) {
14682c155d37SCarlos Alberto Enciso       PrintElement(WarningOffsets, Entry.first);
14697fbcc244SCarlos Alberto Enciso       for (const LVLocation *Location : Entry.second)
14702c155d37SCarlos Alberto Enciso         OS << hexSquareString(Location->getOffset()) << " "
14712c155d37SCarlos Alberto Enciso            << Location->getIntervalInfo() << "\n";
14722c155d37SCarlos Alberto Enciso     }
14732c155d37SCarlos Alberto Enciso     PrintFooter(Map);
14742c155d37SCarlos Alberto Enciso   };
14752c155d37SCarlos Alberto Enciso 
14762c155d37SCarlos Alberto Enciso   if (options().getInternalTag() && getReader().isBinaryTypeELF()) {
14772c155d37SCarlos Alberto Enciso     PrintHeader("Unsupported DWARF Tags");
14782c155d37SCarlos Alberto Enciso     for (LVTagOffsetsMap::const_reference Entry : DebugTags) {
14792c155d37SCarlos Alberto Enciso       OS << format("\n0x%02x", (unsigned)Entry.first) << ", "
14802c155d37SCarlos Alberto Enciso          << dwarf::TagString(Entry.first) << "\n";
14812c155d37SCarlos Alberto Enciso       unsigned Count = 0;
14827fbcc244SCarlos Alberto Enciso       for (const LVOffset &Offset : Entry.second)
14832c155d37SCarlos Alberto Enciso         PrintOffset(Count, Offset);
14842c155d37SCarlos Alberto Enciso       OS << "\n";
14852c155d37SCarlos Alberto Enciso     }
14862c155d37SCarlos Alberto Enciso     PrintFooter(DebugTags);
14872c155d37SCarlos Alberto Enciso   }
14882c155d37SCarlos Alberto Enciso 
14892c155d37SCarlos Alberto Enciso   if (options().getWarningCoverages()) {
14902c155d37SCarlos Alberto Enciso     PrintHeader("Symbols Invalid Coverages");
14912c155d37SCarlos Alberto Enciso     for (LVOffsetSymbolMap::const_reference Entry : InvalidCoverages) {
14922c155d37SCarlos Alberto Enciso       // Symbol basic information.
14932c155d37SCarlos Alberto Enciso       LVSymbol *Symbol = Entry.second;
14942c155d37SCarlos Alberto Enciso       OS << hexSquareString(Entry.first) << " {Coverage} "
14952c155d37SCarlos Alberto Enciso          << format("%.2f%%", Symbol->getCoveragePercentage()) << " "
14962c155d37SCarlos Alberto Enciso          << formattedKind(Symbol->kind()) << " "
14972c155d37SCarlos Alberto Enciso          << formattedName(Symbol->getName()) << "\n";
14982c155d37SCarlos Alberto Enciso     }
14992c155d37SCarlos Alberto Enciso     PrintFooter(InvalidCoverages);
15002c155d37SCarlos Alberto Enciso   }
15012c155d37SCarlos Alberto Enciso 
15022c155d37SCarlos Alberto Enciso   if (options().getWarningLines()) {
15032c155d37SCarlos Alberto Enciso     PrintHeader("Lines Zero References");
15042c155d37SCarlos Alberto Enciso     for (LVOffsetLinesMap::const_reference Entry : LinesZero) {
15052c155d37SCarlos Alberto Enciso       PrintElement(WarningOffsets, Entry.first);
15062c155d37SCarlos Alberto Enciso       unsigned Count = 0;
15077fbcc244SCarlos Alberto Enciso       for (const LVLine *Line : Entry.second)
15082c155d37SCarlos Alberto Enciso         PrintOffset(Count, Line->getOffset());
15092c155d37SCarlos Alberto Enciso       OS << "\n";
15102c155d37SCarlos Alberto Enciso     }
15112c155d37SCarlos Alberto Enciso     PrintFooter(LinesZero);
15122c155d37SCarlos Alberto Enciso   }
15132c155d37SCarlos Alberto Enciso 
15142c155d37SCarlos Alberto Enciso   if (options().getWarningLocations())
15152c155d37SCarlos Alberto Enciso     PrintInvalidLocations(InvalidLocations, "Invalid Location Ranges");
15162c155d37SCarlos Alberto Enciso 
15172c155d37SCarlos Alberto Enciso   if (options().getWarningRanges())
15182c155d37SCarlos Alberto Enciso     PrintInvalidLocations(InvalidRanges, "Invalid Code Ranges");
15192c155d37SCarlos Alberto Enciso }
15202c155d37SCarlos Alberto Enciso 
printTotals(raw_ostream & OS) const1521e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::printTotals(raw_ostream &OS) const {
1522e28b9357SCarlos Alberto Enciso   OS << "\nTotals by lexical level:\n";
1523e28b9357SCarlos Alberto Enciso   for (size_t Index = 1; Index <= MaxSeenLevel; ++Index)
1524e28b9357SCarlos Alberto Enciso     OS << format("[%03d]: %10d (%6.2f%%)\n", Index, Totals[Index].first,
1525e28b9357SCarlos Alberto Enciso                  Totals[Index].second);
1526e28b9357SCarlos Alberto Enciso }
1527e28b9357SCarlos Alberto Enciso 
printScopeSize(const LVScope * Scope,raw_ostream & OS)1528e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::printScopeSize(const LVScope *Scope, raw_ostream &OS) {
1529e28b9357SCarlos Alberto Enciso   LVSizesMap::const_iterator Iter = Sizes.find(Scope);
1530e28b9357SCarlos Alberto Enciso   if (Iter != Sizes.end()) {
1531e28b9357SCarlos Alberto Enciso     LVOffset Size = Iter->second;
1532e28b9357SCarlos Alberto Enciso     assert(CUContributionSize && "Invalid CU contribution size.");
1533e28b9357SCarlos Alberto Enciso     // Get a percentage rounded to two decimal digits. This avoids
1534e28b9357SCarlos Alberto Enciso     // implementation-defined rounding inside printing functions.
1535e28b9357SCarlos Alberto Enciso     float Percentage =
1536e28b9357SCarlos Alberto Enciso         rint((float(Size) / CUContributionSize) * 100.0 * 100.0) / 100.0;
15377292d051SMichał Górny     OS << format("%10" PRId64 " (%6.2f%%) : ", Size, Percentage);
1538e28b9357SCarlos Alberto Enciso     Scope->print(OS);
1539e28b9357SCarlos Alberto Enciso 
1540e28b9357SCarlos Alberto Enciso     // Keep record of the total sizes at each lexical level.
1541e28b9357SCarlos Alberto Enciso     LVLevel Level = Scope->getLevel();
1542e28b9357SCarlos Alberto Enciso     if (Level > MaxSeenLevel)
1543e28b9357SCarlos Alberto Enciso       MaxSeenLevel = Level;
1544e28b9357SCarlos Alberto Enciso     if (Level >= Totals.size())
1545e28b9357SCarlos Alberto Enciso       Totals.resize(2 * Level);
1546e28b9357SCarlos Alberto Enciso     Totals[Level].first += Size;
1547e28b9357SCarlos Alberto Enciso     Totals[Level].second += Percentage;
1548e28b9357SCarlos Alberto Enciso   }
1549e28b9357SCarlos Alberto Enciso }
1550e28b9357SCarlos Alberto Enciso 
printSizes(raw_ostream & OS) const1551e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::printSizes(raw_ostream &OS) const {
1552e28b9357SCarlos Alberto Enciso   // Recursively print the contributions for each scope.
1553e28b9357SCarlos Alberto Enciso   std::function<void(const LVScope *Scope)> PrintScope =
1554e28b9357SCarlos Alberto Enciso       [&](const LVScope *Scope) {
15550332a8e7SCarlos Alberto Enciso         // If we have selection criteria, then use only the selected scopes.
15560332a8e7SCarlos Alberto Enciso         if (options().getSelectExecute() && options().getReportAnyView()) {
15570332a8e7SCarlos Alberto Enciso           for (const LVScope *Scope : MatchedScopes)
15580332a8e7SCarlos Alberto Enciso             if (Scope->getLevel() < options().getOutputLevel())
15590332a8e7SCarlos Alberto Enciso               printScopeSize(Scope, OS);
15600332a8e7SCarlos Alberto Enciso           return;
15610332a8e7SCarlos Alberto Enciso         }
1562e28b9357SCarlos Alberto Enciso         if (Scope->getLevel() < options().getOutputLevel()) {
1563e28b9357SCarlos Alberto Enciso           if (const LVScopes *Scopes = Scope->getScopes())
1564e28b9357SCarlos Alberto Enciso             for (const LVScope *Scope : *Scopes) {
1565e28b9357SCarlos Alberto Enciso               printScopeSize(Scope, OS);
1566e28b9357SCarlos Alberto Enciso               PrintScope(Scope);
1567e28b9357SCarlos Alberto Enciso             }
1568e28b9357SCarlos Alberto Enciso         }
1569e28b9357SCarlos Alberto Enciso       };
1570e28b9357SCarlos Alberto Enciso 
1571e28b9357SCarlos Alberto Enciso   bool PrintScopes = options().getPrintScopes();
1572e28b9357SCarlos Alberto Enciso   if (!PrintScopes)
1573e28b9357SCarlos Alberto Enciso     options().setPrintScopes();
1574e28b9357SCarlos Alberto Enciso   getReader().setCompileUnit(const_cast<LVScopeCompileUnit *>(this));
1575e28b9357SCarlos Alberto Enciso 
1576e28b9357SCarlos Alberto Enciso   OS << "\nScope Sizes:\n";
1577e28b9357SCarlos Alberto Enciso   options().resetPrintFormatting();
1578e28b9357SCarlos Alberto Enciso   options().setPrintOffset();
1579e28b9357SCarlos Alberto Enciso 
1580e28b9357SCarlos Alberto Enciso   // Print the scopes regardless if the user has requested any scopes
1581e28b9357SCarlos Alberto Enciso   // printing. Set the option just to allow printing the contributions.
1582e28b9357SCarlos Alberto Enciso   printScopeSize(this, OS);
1583e28b9357SCarlos Alberto Enciso   PrintScope(this);
1584e28b9357SCarlos Alberto Enciso 
1585e28b9357SCarlos Alberto Enciso   // Print total scope sizes by level.
1586e28b9357SCarlos Alberto Enciso   printTotals(OS);
1587e28b9357SCarlos Alberto Enciso 
1588e28b9357SCarlos Alberto Enciso   options().resetPrintOffset();
1589e28b9357SCarlos Alberto Enciso   options().setPrintFormatting();
1590e28b9357SCarlos Alberto Enciso 
1591e28b9357SCarlos Alberto Enciso   if (!PrintScopes)
1592e28b9357SCarlos Alberto Enciso     options().resetPrintScopes();
1593e28b9357SCarlos Alberto Enciso }
1594e28b9357SCarlos Alberto Enciso 
printSummary(raw_ostream & OS) const1595e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::printSummary(raw_ostream &OS) const {
15960332a8e7SCarlos Alberto Enciso   printSummary(OS, options().getSelectExecute() ? Found : Printed, "Printed");
1597e28b9357SCarlos Alberto Enciso }
1598e28b9357SCarlos Alberto Enciso 
1599e28b9357SCarlos Alberto Enciso // Print summary details for the scopes tree.
printSummary(raw_ostream & OS,const LVCounter & Counter,const char * Header) const1600e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::printSummary(raw_ostream &OS, const LVCounter &Counter,
1601e28b9357SCarlos Alberto Enciso                                       const char *Header) const {
1602e28b9357SCarlos Alberto Enciso   std::string Separator = std::string(29, '-');
1603e28b9357SCarlos Alberto Enciso   auto PrintSeparator = [&]() { OS << Separator << "\n"; };
1604e28b9357SCarlos Alberto Enciso   auto PrintHeadingRow = [&](const char *T, const char *U, const char *V) {
1605e28b9357SCarlos Alberto Enciso     OS << format("%-9s%9s  %9s\n", T, U, V);
1606e28b9357SCarlos Alberto Enciso   };
1607e28b9357SCarlos Alberto Enciso   auto PrintDataRow = [&](const char *T, unsigned U, unsigned V) {
1608e28b9357SCarlos Alberto Enciso     OS << format("%-9s%9d  %9d\n", T, U, V);
1609e28b9357SCarlos Alberto Enciso   };
1610e28b9357SCarlos Alberto Enciso 
1611e28b9357SCarlos Alberto Enciso   OS << "\n";
1612e28b9357SCarlos Alberto Enciso   PrintSeparator();
1613e28b9357SCarlos Alberto Enciso   PrintHeadingRow("Element", "Total", Header);
1614e28b9357SCarlos Alberto Enciso   PrintSeparator();
1615e28b9357SCarlos Alberto Enciso   PrintDataRow("Scopes", Allocated.Scopes, Counter.Scopes);
1616e28b9357SCarlos Alberto Enciso   PrintDataRow("Symbols", Allocated.Symbols, Counter.Symbols);
1617e28b9357SCarlos Alberto Enciso   PrintDataRow("Types", Allocated.Types, Counter.Types);
1618e28b9357SCarlos Alberto Enciso   PrintDataRow("Lines", Allocated.Lines, Counter.Lines);
1619e28b9357SCarlos Alberto Enciso   PrintSeparator();
1620e28b9357SCarlos Alberto Enciso   PrintDataRow(
1621e28b9357SCarlos Alberto Enciso       "Total",
1622e28b9357SCarlos Alberto Enciso       Allocated.Scopes + Allocated.Symbols + Allocated.Lines + Allocated.Types,
1623e28b9357SCarlos Alberto Enciso       Counter.Scopes + Counter.Symbols + Counter.Lines + Counter.Types);
1624e28b9357SCarlos Alberto Enciso }
1625e28b9357SCarlos Alberto Enciso 
printMatchedElements(raw_ostream & OS,bool UseMatchedElements)1626e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::printMatchedElements(raw_ostream &OS,
1627e28b9357SCarlos Alberto Enciso                                               bool UseMatchedElements) {
1628e28b9357SCarlos Alberto Enciso   LVSortFunction SortFunction = getSortFunction();
1629e28b9357SCarlos Alberto Enciso   if (SortFunction)
1630e28b9357SCarlos Alberto Enciso     std::stable_sort(MatchedElements.begin(), MatchedElements.end(),
1631e28b9357SCarlos Alberto Enciso                      SortFunction);
1632e28b9357SCarlos Alberto Enciso 
1633e28b9357SCarlos Alberto Enciso   // Check the type of elements required to be printed. 'MatchedElements'
1634e28b9357SCarlos Alberto Enciso   // contains generic elements (lines, scopes, symbols, types). If we have a
1635e28b9357SCarlos Alberto Enciso   // request to print any generic element, then allow the normal printing.
1636e28b9357SCarlos Alberto Enciso   if (options().getPrintAnyElement()) {
1637e28b9357SCarlos Alberto Enciso     if (UseMatchedElements)
1638e28b9357SCarlos Alberto Enciso       OS << "\n";
1639e28b9357SCarlos Alberto Enciso     print(OS);
1640e28b9357SCarlos Alberto Enciso 
1641e28b9357SCarlos Alberto Enciso     if (UseMatchedElements) {
1642e28b9357SCarlos Alberto Enciso       // Print the details for the matched elements.
1643e28b9357SCarlos Alberto Enciso       for (const LVElement *Element : MatchedElements)
1644e28b9357SCarlos Alberto Enciso         Element->print(OS);
1645e28b9357SCarlos Alberto Enciso     } else {
1646e28b9357SCarlos Alberto Enciso       // Print the view for the matched scopes.
1647e28b9357SCarlos Alberto Enciso       for (const LVScope *Scope : MatchedScopes) {
1648e28b9357SCarlos Alberto Enciso         Scope->print(OS);
1649e28b9357SCarlos Alberto Enciso         if (const LVElements *Elements = Scope->getChildren())
1650e28b9357SCarlos Alberto Enciso           for (LVElement *Element : *Elements)
1651e28b9357SCarlos Alberto Enciso             Element->print(OS);
1652e28b9357SCarlos Alberto Enciso       }
1653e28b9357SCarlos Alberto Enciso     }
1654e28b9357SCarlos Alberto Enciso 
1655e28b9357SCarlos Alberto Enciso     // Print any requested summary.
1656e28b9357SCarlos Alberto Enciso     if (options().getPrintSummary()) {
1657e28b9357SCarlos Alberto Enciso       // In the case of '--report=details' the matched elements are
1658e28b9357SCarlos Alberto Enciso       // already counted; just proceed to print any requested summary.
1659e28b9357SCarlos Alberto Enciso       // Otherwise, count them and print the summary.
1660e28b9357SCarlos Alberto Enciso       if (!options().getReportList()) {
1661e28b9357SCarlos Alberto Enciso         for (LVElement *Element : MatchedElements) {
1662e28b9357SCarlos Alberto Enciso           if (!Element->getIncludeInPrint())
1663e28b9357SCarlos Alberto Enciso             continue;
1664e28b9357SCarlos Alberto Enciso           if (Element->getIsType())
1665e28b9357SCarlos Alberto Enciso             ++Found.Types;
1666e28b9357SCarlos Alberto Enciso           else if (Element->getIsSymbol())
1667e28b9357SCarlos Alberto Enciso             ++Found.Symbols;
1668e28b9357SCarlos Alberto Enciso           else if (Element->getIsScope())
1669e28b9357SCarlos Alberto Enciso             ++Found.Scopes;
1670e28b9357SCarlos Alberto Enciso           else if (Element->getIsLine())
1671e28b9357SCarlos Alberto Enciso             ++Found.Lines;
1672e28b9357SCarlos Alberto Enciso           else
1673e28b9357SCarlos Alberto Enciso             assert(Element && "Invalid element.");
1674e28b9357SCarlos Alberto Enciso         }
1675e28b9357SCarlos Alberto Enciso       }
1676e28b9357SCarlos Alberto Enciso       printSummary(OS, Found, "Printed");
1677e28b9357SCarlos Alberto Enciso     }
1678e28b9357SCarlos Alberto Enciso   }
1679e28b9357SCarlos Alberto Enciso 
1680e28b9357SCarlos Alberto Enciso   // Check if we have a request to print sizes for the matched elements
1681e28b9357SCarlos Alberto Enciso   // that are scopes.
1682e28b9357SCarlos Alberto Enciso   if (options().getPrintSizes()) {
1683e28b9357SCarlos Alberto Enciso     OS << "\n";
1684e28b9357SCarlos Alberto Enciso     print(OS);
1685e28b9357SCarlos Alberto Enciso 
1686e28b9357SCarlos Alberto Enciso     OS << "\nScope Sizes:\n";
1687e28b9357SCarlos Alberto Enciso     printScopeSize(this, OS);
1688e28b9357SCarlos Alberto Enciso     for (LVElement *Element : MatchedElements)
1689e28b9357SCarlos Alberto Enciso       if (Element->getIsScope())
1690e28b9357SCarlos Alberto Enciso         // Print sizes only for scopes.
1691e28b9357SCarlos Alberto Enciso         printScopeSize(static_cast<LVScope *>(Element), OS);
1692e28b9357SCarlos Alberto Enciso 
1693e28b9357SCarlos Alberto Enciso     printTotals(OS);
1694e28b9357SCarlos Alberto Enciso   }
1695e28b9357SCarlos Alberto Enciso }
1696e28b9357SCarlos Alberto Enciso 
print(raw_ostream & OS,bool Full) const1697e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::print(raw_ostream &OS, bool Full) const {
1698e28b9357SCarlos Alberto Enciso   // Reset counters for printed and found elements.
1699e28b9357SCarlos Alberto Enciso   const_cast<LVScopeCompileUnit *>(this)->Found.reset();
1700e28b9357SCarlos Alberto Enciso   const_cast<LVScopeCompileUnit *>(this)->Printed.reset();
1701e28b9357SCarlos Alberto Enciso 
1702e28b9357SCarlos Alberto Enciso   if (getReader().doPrintScope(this) && options().getPrintFormatting())
1703e28b9357SCarlos Alberto Enciso     OS << "\n";
1704e28b9357SCarlos Alberto Enciso 
1705e28b9357SCarlos Alberto Enciso   LVScope::print(OS, Full);
1706e28b9357SCarlos Alberto Enciso }
1707e28b9357SCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1708e28b9357SCarlos Alberto Enciso void LVScopeCompileUnit::printExtra(raw_ostream &OS, bool Full) const {
1709e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind()) << " '" << getName() << "'\n";
1710e28b9357SCarlos Alberto Enciso   if (options().getPrintFormatting() && options().getAttributeProducer())
1711e28b9357SCarlos Alberto Enciso     printAttributes(OS, Full, "{Producer} ",
1712e28b9357SCarlos Alberto Enciso                     const_cast<LVScopeCompileUnit *>(this), getProducer(),
1713e28b9357SCarlos Alberto Enciso                     /*UseQuotes=*/true,
1714e28b9357SCarlos Alberto Enciso                     /*PrintRef=*/false);
1715e28b9357SCarlos Alberto Enciso 
1716e28b9357SCarlos Alberto Enciso   // Reset file index, to allow its children to print the correct filename.
1717e28b9357SCarlos Alberto Enciso   options().resetFilenameIndex();
1718e28b9357SCarlos Alberto Enciso 
17193c397c90SCarlos Alberto Enciso   // Print any files, directories, public names and active ranges.
1720e28b9357SCarlos Alberto Enciso   if (Full) {
1721e28b9357SCarlos Alberto Enciso     printLocalNames(OS, Full);
17223c397c90SCarlos Alberto Enciso     printActiveRanges(OS, Full);
1723e28b9357SCarlos Alberto Enciso   }
1724e28b9357SCarlos Alberto Enciso }
1725e28b9357SCarlos Alberto Enciso 
1726e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1727e28b9357SCarlos Alberto Enciso // DWARF enumeration (DW_TAG_enumeration_type).
1728e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1729e98a4c5aSCarlos Alberto Enciso bool LVScopeEnumeration::equals(const LVScope *Scope) const {
1730e98a4c5aSCarlos Alberto Enciso   if (!LVScope::equals(Scope))
1731e98a4c5aSCarlos Alberto Enciso     return false;
1732e98a4c5aSCarlos Alberto Enciso   return equalNumberOfChildren(Scope);
1733e98a4c5aSCarlos Alberto Enciso }
1734e98a4c5aSCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1735e28b9357SCarlos Alberto Enciso void LVScopeEnumeration::printExtra(raw_ostream &OS, bool Full) const {
1736e28b9357SCarlos Alberto Enciso   // Print the full type name.
1737e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind()) << " " << (getIsEnumClass() ? "class " : "")
1738e28b9357SCarlos Alberto Enciso      << formattedName(getName());
1739e28b9357SCarlos Alberto Enciso   if (getHasType())
1740e28b9357SCarlos Alberto Enciso     OS << " -> " << typeOffsetAsString()
1741e28b9357SCarlos Alberto Enciso        << formattedNames(getTypeQualifiedName(), typeAsString());
1742e28b9357SCarlos Alberto Enciso   OS << "\n";
1743e28b9357SCarlos Alberto Enciso }
1744e28b9357SCarlos Alberto Enciso 
1745e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1746e28b9357SCarlos Alberto Enciso // DWARF formal parameter pack (DW_TAG_GNU_formal_parameter_pack).
1747e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1748e98a4c5aSCarlos Alberto Enciso bool LVScopeFormalPack::equals(const LVScope *Scope) const {
1749e98a4c5aSCarlos Alberto Enciso   if (!LVScope::equals(Scope))
1750e98a4c5aSCarlos Alberto Enciso     return false;
1751e98a4c5aSCarlos Alberto Enciso   return equalNumberOfChildren(Scope);
1752e98a4c5aSCarlos Alberto Enciso }
1753e98a4c5aSCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1754e28b9357SCarlos Alberto Enciso void LVScopeFormalPack::printExtra(raw_ostream &OS, bool Full) const {
1755e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
1756e28b9357SCarlos Alberto Enciso }
1757e28b9357SCarlos Alberto Enciso 
1758e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1759e28b9357SCarlos Alberto Enciso // DWARF function.
1760e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
resolveReferences()1761e28b9357SCarlos Alberto Enciso void LVScopeFunction::resolveReferences() {
1762e28b9357SCarlos Alberto Enciso   // Before we resolve any references to other elements, check if we have
1763e28b9357SCarlos Alberto Enciso   // to insert missing elements, that have been stripped, which will help
1764e28b9357SCarlos Alberto Enciso   // the logical view comparison.
1765e28b9357SCarlos Alberto Enciso   if (options().getAttributeInserted() && getHasReferenceAbstract() &&
1766e28b9357SCarlos Alberto Enciso       !getAddedMissing()) {
1767e28b9357SCarlos Alberto Enciso     // Add missing elements at the function scope.
1768e28b9357SCarlos Alberto Enciso     addMissingElements(getReference());
1769e28b9357SCarlos Alberto Enciso     if (Scopes)
1770e28b9357SCarlos Alberto Enciso       for (LVScope *Scope : *Scopes)
1771e28b9357SCarlos Alberto Enciso         if (Scope->getHasReferenceAbstract() && !Scope->getAddedMissing())
1772e28b9357SCarlos Alberto Enciso           Scope->addMissingElements(Scope->getReference());
1773e28b9357SCarlos Alberto Enciso   }
1774e28b9357SCarlos Alberto Enciso 
1775e28b9357SCarlos Alberto Enciso   LVScope::resolveReferences();
1776e28b9357SCarlos Alberto Enciso 
1777e28b9357SCarlos Alberto Enciso   // The DWARF 'extern' attribute is generated at the class level.
1778e28b9357SCarlos Alberto Enciso   // 0000003f DW_TAG_class_type "CLASS"
1779e28b9357SCarlos Alberto Enciso   //   00000048 DW_TAG_subprogram "bar"
1780e28b9357SCarlos Alberto Enciso   //	            DW_AT_external DW_FORM_flag_present
1781e28b9357SCarlos Alberto Enciso   // 00000070 DW_TAG_subprogram "bar"
1782e28b9357SCarlos Alberto Enciso   //   DW_AT_specification DW_FORM_ref4 0x00000048
1783e7950fceSCarlos Alberto Enciso   // CodeView does not include any information at the class level to
1784e7950fceSCarlos Alberto Enciso   // mark the member function as external.
1785e28b9357SCarlos Alberto Enciso   // If there is a reference linking the declaration and definition, mark
1786e28b9357SCarlos Alberto Enciso   // the definition as extern, to facilitate the logical view comparison.
1787e28b9357SCarlos Alberto Enciso   if (getHasReferenceSpecification()) {
1788e28b9357SCarlos Alberto Enciso     LVScope *Reference = getReference();
1789e28b9357SCarlos Alberto Enciso     if (Reference && Reference->getIsExternal()) {
1790e28b9357SCarlos Alberto Enciso       Reference->resetIsExternal();
1791e28b9357SCarlos Alberto Enciso       setIsExternal();
1792e28b9357SCarlos Alberto Enciso     }
1793e28b9357SCarlos Alberto Enciso   }
1794e28b9357SCarlos Alberto Enciso 
1795e28b9357SCarlos Alberto Enciso   // Resolve the function associated type.
1796e28b9357SCarlos Alberto Enciso   if (!getType())
1797e28b9357SCarlos Alberto Enciso     if (LVScope *Reference = getReference())
1798e28b9357SCarlos Alberto Enciso       setType(Reference->getType());
1799e28b9357SCarlos Alberto Enciso }
1800e28b9357SCarlos Alberto Enciso 
setName(StringRef ObjectName)1801e28b9357SCarlos Alberto Enciso void LVScopeFunction::setName(StringRef ObjectName) {
1802e28b9357SCarlos Alberto Enciso   LVScope::setName(ObjectName);
1803e28b9357SCarlos Alberto Enciso   // Check for system generated functions.
1804e28b9357SCarlos Alberto Enciso   getReader().isSystemEntry(this, ObjectName);
1805e28b9357SCarlos Alberto Enciso }
1806e28b9357SCarlos Alberto Enciso 
resolveExtra()1807e28b9357SCarlos Alberto Enciso void LVScopeFunction::resolveExtra() {
1808e28b9357SCarlos Alberto Enciso   // Check if we need to encode the template arguments.
1809e28b9357SCarlos Alberto Enciso   if (getIsTemplate())
1810e28b9357SCarlos Alberto Enciso     resolveTemplate();
1811e28b9357SCarlos Alberto Enciso }
1812e28b9357SCarlos Alberto Enciso 
equals(const LVScope * Scope) const1813e98a4c5aSCarlos Alberto Enciso bool LVScopeFunction::equals(const LVScope *Scope) const {
1814e98a4c5aSCarlos Alberto Enciso   if (!LVScope::equals(Scope))
1815e98a4c5aSCarlos Alberto Enciso     return false;
1816e98a4c5aSCarlos Alberto Enciso 
1817e98a4c5aSCarlos Alberto Enciso   // When comparing logical elements, ignore any difference in the children.
1818e98a4c5aSCarlos Alberto Enciso   if (options().getCompareContext() && !equalNumberOfChildren(Scope))
1819e98a4c5aSCarlos Alberto Enciso     return false;
1820e98a4c5aSCarlos Alberto Enciso 
1821e98a4c5aSCarlos Alberto Enciso   // Check if the linkage name matches.
1822e98a4c5aSCarlos Alberto Enciso   if (getLinkageNameIndex() != Scope->getLinkageNameIndex())
1823e98a4c5aSCarlos Alberto Enciso     return false;
1824e98a4c5aSCarlos Alberto Enciso 
1825e98a4c5aSCarlos Alberto Enciso   // Check if the parameters match in the case of templates.
1826e98a4c5aSCarlos Alberto Enciso   if (!LVType::parametersMatch(getTypes(), Scope->getTypes()))
1827e98a4c5aSCarlos Alberto Enciso     return false;
1828e98a4c5aSCarlos Alberto Enciso 
1829e98a4c5aSCarlos Alberto Enciso   // Check if the arguments match.
1830e98a4c5aSCarlos Alberto Enciso   if (!LVSymbol::parametersMatch(getSymbols(), Scope->getSymbols()))
1831e98a4c5aSCarlos Alberto Enciso     return false;
1832e98a4c5aSCarlos Alberto Enciso 
1833e98a4c5aSCarlos Alberto Enciso   // Check if the lines match.
1834e98a4c5aSCarlos Alberto Enciso   if (options().getCompareLines() &&
1835e98a4c5aSCarlos Alberto Enciso       !LVLine::equals(getLines(), Scope->getLines()))
1836e98a4c5aSCarlos Alberto Enciso     return false;
1837e98a4c5aSCarlos Alberto Enciso 
1838e98a4c5aSCarlos Alberto Enciso   // Check if any reference is the same.
1839e98a4c5aSCarlos Alberto Enciso   if (!referenceMatch(Scope))
1840e98a4c5aSCarlos Alberto Enciso     return false;
1841e98a4c5aSCarlos Alberto Enciso 
1842e98a4c5aSCarlos Alberto Enciso   if (getReference() && !getReference()->equals(Scope->getReference()))
1843e98a4c5aSCarlos Alberto Enciso     return false;
1844e98a4c5aSCarlos Alberto Enciso 
1845e98a4c5aSCarlos Alberto Enciso   return true;
1846e98a4c5aSCarlos Alberto Enciso }
1847e98a4c5aSCarlos Alberto Enciso 
findEqualScope(const LVScopes * Scopes) const1848e98a4c5aSCarlos Alberto Enciso LVScope *LVScopeFunction::findEqualScope(const LVScopes *Scopes) const {
1849e98a4c5aSCarlos Alberto Enciso   assert(Scopes && "Scopes must not be nullptr");
1850e98a4c5aSCarlos Alberto Enciso   // Go through candidates and try to find a best match.
1851e98a4c5aSCarlos Alberto Enciso   for (LVScope *Scope : *Scopes)
1852e98a4c5aSCarlos Alberto Enciso     // Match arguments, children, lines, references.
1853e98a4c5aSCarlos Alberto Enciso     if (equals(Scope))
1854e98a4c5aSCarlos Alberto Enciso       return Scope;
1855e98a4c5aSCarlos Alberto Enciso   return nullptr;
1856e98a4c5aSCarlos Alberto Enciso }
1857e98a4c5aSCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1858e28b9357SCarlos Alberto Enciso void LVScopeFunction::printExtra(raw_ostream &OS, bool Full) const {
1859e28b9357SCarlos Alberto Enciso   LVScope *Reference = getReference();
1860e28b9357SCarlos Alberto Enciso 
1861e28b9357SCarlos Alberto Enciso   // Inline attributes based on the reference element.
1862e28b9357SCarlos Alberto Enciso   uint32_t InlineCode =
1863e28b9357SCarlos Alberto Enciso       Reference ? Reference->getInlineCode() : getInlineCode();
1864e28b9357SCarlos Alberto Enciso 
1865e28b9357SCarlos Alberto Enciso   // Accessibility depends on the parent (class, structure).
1866e28b9357SCarlos Alberto Enciso   uint32_t AccessCode = 0;
1867e28b9357SCarlos Alberto Enciso   if (getIsMember())
1868e28b9357SCarlos Alberto Enciso     AccessCode = getParentScope()->getIsClass() ? dwarf::DW_ACCESS_private
1869e28b9357SCarlos Alberto Enciso                                                 : dwarf::DW_ACCESS_public;
1870e28b9357SCarlos Alberto Enciso 
1871e28b9357SCarlos Alberto Enciso   std::string Attributes =
1872e28b9357SCarlos Alberto Enciso       getIsCallSite()
1873e28b9357SCarlos Alberto Enciso           ? ""
1874e28b9357SCarlos Alberto Enciso           : formatAttributes(externalString(), accessibilityString(AccessCode),
1875e28b9357SCarlos Alberto Enciso                              inlineCodeString(InlineCode), virtualityString());
1876e28b9357SCarlos Alberto Enciso 
1877e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind()) << " " << Attributes << formattedName(getName())
1878e28b9357SCarlos Alberto Enciso      << discriminatorAsString() << " -> " << typeOffsetAsString()
1879e28b9357SCarlos Alberto Enciso      << formattedNames(getTypeQualifiedName(), typeAsString()) << "\n";
1880e28b9357SCarlos Alberto Enciso 
1881e28b9357SCarlos Alberto Enciso   // Print any active ranges.
1882e28b9357SCarlos Alberto Enciso   if (Full) {
1883e28b9357SCarlos Alberto Enciso     if (getIsTemplateResolved())
1884e28b9357SCarlos Alberto Enciso       printEncodedArgs(OS, Full);
18853c397c90SCarlos Alberto Enciso     printActiveRanges(OS, Full);
18864f06d46fSCarlos Alberto Enciso     if (getLinkageNameIndex())
18874f06d46fSCarlos Alberto Enciso       printLinkageName(OS, Full, const_cast<LVScopeFunction *>(this),
18884f06d46fSCarlos Alberto Enciso                        const_cast<LVScopeFunction *>(this));
1889e28b9357SCarlos Alberto Enciso     if (Reference)
1890e28b9357SCarlos Alberto Enciso       Reference->printReference(OS, Full, const_cast<LVScopeFunction *>(this));
1891e28b9357SCarlos Alberto Enciso   }
1892e28b9357SCarlos Alberto Enciso }
1893e28b9357SCarlos Alberto Enciso 
1894e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1895e28b9357SCarlos Alberto Enciso // DWARF inlined function (DW_TAG_inlined_function).
1896e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
resolveExtra()1897e28b9357SCarlos Alberto Enciso void LVScopeFunctionInlined::resolveExtra() {
1898e28b9357SCarlos Alberto Enciso   // Check if we need to encode the template arguments.
1899e28b9357SCarlos Alberto Enciso   if (getIsTemplate())
1900e28b9357SCarlos Alberto Enciso     resolveTemplate();
1901e28b9357SCarlos Alberto Enciso }
1902e28b9357SCarlos Alberto Enciso 
equals(const LVScope * Scope) const1903e98a4c5aSCarlos Alberto Enciso bool LVScopeFunctionInlined::equals(const LVScope *Scope) const {
1904e98a4c5aSCarlos Alberto Enciso   if (!LVScopeFunction::equals(Scope))
1905e98a4c5aSCarlos Alberto Enciso     return false;
1906e98a4c5aSCarlos Alberto Enciso 
1907e98a4c5aSCarlos Alberto Enciso   // Check if any reference is the same.
1908e98a4c5aSCarlos Alberto Enciso   if (getHasDiscriminator() && Scope->getHasDiscriminator())
1909e98a4c5aSCarlos Alberto Enciso     if (getDiscriminator() != Scope->getDiscriminator())
1910e98a4c5aSCarlos Alberto Enciso       return false;
1911e98a4c5aSCarlos Alberto Enciso 
1912e98a4c5aSCarlos Alberto Enciso   // Check the call site information.
1913e98a4c5aSCarlos Alberto Enciso   if (getCallFilenameIndex() != Scope->getCallFilenameIndex() ||
1914e98a4c5aSCarlos Alberto Enciso       getCallLineNumber() != Scope->getCallLineNumber())
1915e98a4c5aSCarlos Alberto Enciso     return false;
1916e98a4c5aSCarlos Alberto Enciso 
1917e98a4c5aSCarlos Alberto Enciso   return true;
1918e98a4c5aSCarlos Alberto Enciso }
1919e98a4c5aSCarlos Alberto Enciso 
findEqualScope(const LVScopes * Scopes) const1920e98a4c5aSCarlos Alberto Enciso LVScope *LVScopeFunctionInlined::findEqualScope(const LVScopes *Scopes) const {
1921e98a4c5aSCarlos Alberto Enciso   return LVScopeFunction::findEqualScope(Scopes);
1922e98a4c5aSCarlos Alberto Enciso }
1923e98a4c5aSCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1924e28b9357SCarlos Alberto Enciso void LVScopeFunctionInlined::printExtra(raw_ostream &OS, bool Full) const {
1925e28b9357SCarlos Alberto Enciso   LVScopeFunction::printExtra(OS, Full);
1926e28b9357SCarlos Alberto Enciso }
1927e28b9357SCarlos Alberto Enciso 
1928e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1929e28b9357SCarlos Alberto Enciso // DWARF subroutine type.
1930e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1931e28b9357SCarlos Alberto Enciso // Resolve a Subroutine Type (Callback).
resolveExtra()1932e28b9357SCarlos Alberto Enciso void LVScopeFunctionType::resolveExtra() {
1933e28b9357SCarlos Alberto Enciso   if (getIsMemberPointerResolved())
1934e28b9357SCarlos Alberto Enciso     return;
1935e28b9357SCarlos Alberto Enciso   setIsMemberPointerResolved();
1936e28b9357SCarlos Alberto Enciso 
1937e28b9357SCarlos Alberto Enciso   // The encoded string has the return type and the formal parameters type.
1938e28b9357SCarlos Alberto Enciso   std::string Name(typeAsString());
1939e28b9357SCarlos Alberto Enciso   Name.append(" (*)");
1940e28b9357SCarlos Alberto Enciso   Name.append("(");
1941e28b9357SCarlos Alberto Enciso 
1942e28b9357SCarlos Alberto Enciso   // Traverse the scope symbols, looking for those which are parameters.
1943e28b9357SCarlos Alberto Enciso   if (const LVSymbols *Symbols = getSymbols()) {
1944e28b9357SCarlos Alberto Enciso     bool AddComma = false;
1945e28b9357SCarlos Alberto Enciso     for (LVSymbol *Symbol : *Symbols)
1946e28b9357SCarlos Alberto Enciso       if (Symbol->getIsParameter()) {
1947e28b9357SCarlos Alberto Enciso         Symbol->resolve();
1948e28b9357SCarlos Alberto Enciso         if (LVElement *Type = Symbol->getType())
1949e28b9357SCarlos Alberto Enciso           Type->resolveName();
1950e28b9357SCarlos Alberto Enciso         if (AddComma)
1951e28b9357SCarlos Alberto Enciso           Name.append(", ");
1952e28b9357SCarlos Alberto Enciso         Name.append(std::string(Symbol->getTypeName()));
1953e28b9357SCarlos Alberto Enciso         AddComma = true;
1954e28b9357SCarlos Alberto Enciso       }
1955e28b9357SCarlos Alberto Enciso   }
1956e28b9357SCarlos Alberto Enciso 
1957e28b9357SCarlos Alberto Enciso   Name.append(")");
1958e28b9357SCarlos Alberto Enciso 
1959e28b9357SCarlos Alberto Enciso   // Update the scope name, to reflect the encoded parameters.
1960d22f050eSGregory Alfonso   setName(Name);
1961e28b9357SCarlos Alberto Enciso }
1962e28b9357SCarlos Alberto Enciso 
1963e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
1964e28b9357SCarlos Alberto Enciso // DWARF namespace (DW_TAG_namespace).
1965e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const1966e98a4c5aSCarlos Alberto Enciso bool LVScopeNamespace::equals(const LVScope *Scope) const {
1967e98a4c5aSCarlos Alberto Enciso   if (!LVScope::equals(Scope))
1968e98a4c5aSCarlos Alberto Enciso     return false;
1969e98a4c5aSCarlos Alberto Enciso 
1970e98a4c5aSCarlos Alberto Enciso   if (!equalNumberOfChildren(Scope))
1971e98a4c5aSCarlos Alberto Enciso     return false;
1972e98a4c5aSCarlos Alberto Enciso 
1973e98a4c5aSCarlos Alberto Enciso   // Check if any reference is the same.
1974e98a4c5aSCarlos Alberto Enciso   if (!referenceMatch(Scope))
1975e98a4c5aSCarlos Alberto Enciso     return false;
1976e98a4c5aSCarlos Alberto Enciso 
1977e98a4c5aSCarlos Alberto Enciso   if (getReference() && !getReference()->equals(Scope->getReference()))
1978e98a4c5aSCarlos Alberto Enciso     return false;
1979e98a4c5aSCarlos Alberto Enciso 
1980e98a4c5aSCarlos Alberto Enciso   return true;
1981e98a4c5aSCarlos Alberto Enciso }
1982e98a4c5aSCarlos Alberto Enciso 
findEqualScope(const LVScopes * Scopes) const1983e98a4c5aSCarlos Alberto Enciso LVScope *LVScopeNamespace::findEqualScope(const LVScopes *Scopes) const {
1984e98a4c5aSCarlos Alberto Enciso   assert(Scopes && "Scopes must not be nullptr");
1985e98a4c5aSCarlos Alberto Enciso   // Go through candidates and try to find a best match.
1986e98a4c5aSCarlos Alberto Enciso   for (LVScope *Scope : *Scopes)
1987e98a4c5aSCarlos Alberto Enciso     if (equals(Scope))
1988e98a4c5aSCarlos Alberto Enciso       return Scope;
1989e98a4c5aSCarlos Alberto Enciso   return nullptr;
1990e98a4c5aSCarlos Alberto Enciso }
1991e98a4c5aSCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const1992e28b9357SCarlos Alberto Enciso void LVScopeNamespace::printExtra(raw_ostream &OS, bool Full) const {
1993e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
1994e28b9357SCarlos Alberto Enciso 
19953c397c90SCarlos Alberto Enciso   // Print any active ranges.
1996e28b9357SCarlos Alberto Enciso   if (Full) {
19973c397c90SCarlos Alberto Enciso     printActiveRanges(OS, Full);
19983c397c90SCarlos Alberto Enciso 
1999e28b9357SCarlos Alberto Enciso     if (LVScope *Reference = getReference())
2000e28b9357SCarlos Alberto Enciso       Reference->printReference(OS, Full, const_cast<LVScopeNamespace *>(this));
2001e28b9357SCarlos Alberto Enciso   }
2002e28b9357SCarlos Alberto Enciso }
2003e28b9357SCarlos Alberto Enciso 
20043c397c90SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
20053c397c90SCarlos Alberto Enciso // An object file (single or multiple CUs).
20063c397c90SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
processRangeInformation()20073c397c90SCarlos Alberto Enciso void LVScopeRoot::processRangeInformation() {
20083c397c90SCarlos Alberto Enciso   if (!options().getAttributeAnyLocation())
20093c397c90SCarlos Alberto Enciso     return;
20103c397c90SCarlos Alberto Enciso 
20113c397c90SCarlos Alberto Enciso   if (Scopes)
20123c397c90SCarlos Alberto Enciso     for (LVScope *Scope : *Scopes) {
20133c397c90SCarlos Alberto Enciso       LVScopeCompileUnit *CompileUnit =
20143c397c90SCarlos Alberto Enciso           static_cast<LVScopeCompileUnit *>(Scope);
20153c397c90SCarlos Alberto Enciso       getReader().setCompileUnit(CompileUnit);
20163c397c90SCarlos Alberto Enciso       CompileUnit->processRangeLocationCoverage();
20173c397c90SCarlos Alberto Enciso     }
20183c397c90SCarlos Alberto Enciso }
20193c397c90SCarlos Alberto Enciso 
transformScopedName()2020e7950fceSCarlos Alberto Enciso void LVScopeRoot::transformScopedName() {
2021e7950fceSCarlos Alberto Enciso   // Recursively transform all names.
2022e7950fceSCarlos Alberto Enciso   std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
2023e7950fceSCarlos Alberto Enciso     auto Traverse = [&](const auto *Set) {
2024e7950fceSCarlos Alberto Enciso       if (Set)
2025e7950fceSCarlos Alberto Enciso         for (const auto &Entry : *Set)
2026e7950fceSCarlos Alberto Enciso           Entry->setInnerComponent();
2027e7950fceSCarlos Alberto Enciso     };
2028e7950fceSCarlos Alberto Enciso     if (const LVScopes *Scopes = Parent->getScopes())
2029e7950fceSCarlos Alberto Enciso       for (LVScope *Scope : *Scopes) {
2030e7950fceSCarlos Alberto Enciso         Scope->setInnerComponent();
2031e7950fceSCarlos Alberto Enciso         TraverseScope(Scope);
2032e7950fceSCarlos Alberto Enciso       }
2033e7950fceSCarlos Alberto Enciso     Traverse(Parent->getSymbols());
2034e7950fceSCarlos Alberto Enciso     Traverse(Parent->getTypes());
2035e7950fceSCarlos Alberto Enciso     Traverse(Parent->getLines());
2036e7950fceSCarlos Alberto Enciso   };
2037e7950fceSCarlos Alberto Enciso 
2038e7950fceSCarlos Alberto Enciso   // Start traversing the scopes root and transform the element name.
2039e7950fceSCarlos Alberto Enciso   TraverseScope(this);
2040e7950fceSCarlos Alberto Enciso }
2041e7950fceSCarlos Alberto Enciso 
equals(const LVScope * Scope) const2042e98a4c5aSCarlos Alberto Enciso bool LVScopeRoot::equals(const LVScope *Scope) const {
2043e98a4c5aSCarlos Alberto Enciso   return LVScope::equals(Scope);
2044e98a4c5aSCarlos Alberto Enciso }
2045e98a4c5aSCarlos Alberto Enciso 
print(raw_ostream & OS,bool Full) const2046e28b9357SCarlos Alberto Enciso void LVScopeRoot::print(raw_ostream &OS, bool Full) const {
2047e28b9357SCarlos Alberto Enciso   OS << "\nLogical View:\n";
2048e28b9357SCarlos Alberto Enciso   LVScope::print(OS, Full);
2049e28b9357SCarlos Alberto Enciso }
2050e28b9357SCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const2051e28b9357SCarlos Alberto Enciso void LVScopeRoot::printExtra(raw_ostream &OS, bool Full) const {
2052e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind()) << " " << formattedName(getName()) << "";
2053e28b9357SCarlos Alberto Enciso   if (options().getAttributeFormat())
2054e28b9357SCarlos Alberto Enciso     OS << " -> " << getFileFormatName();
2055e28b9357SCarlos Alberto Enciso   OS << "\n";
2056e28b9357SCarlos Alberto Enciso }
2057e28b9357SCarlos Alberto Enciso 
doPrintMatches(bool Split,raw_ostream & OS,bool UseMatchedElements) const2058e28b9357SCarlos Alberto Enciso Error LVScopeRoot::doPrintMatches(bool Split, raw_ostream &OS,
2059e28b9357SCarlos Alberto Enciso                                   bool UseMatchedElements) const {
2060e28b9357SCarlos Alberto Enciso   // During a view output splitting, use the output stream created by the
2061e28b9357SCarlos Alberto Enciso   // split context, then switch to the reader output stream.
2062e28b9357SCarlos Alberto Enciso   static raw_ostream *StreamSplit = &OS;
2063e28b9357SCarlos Alberto Enciso 
2064e28b9357SCarlos Alberto Enciso   if (Scopes) {
2065e28b9357SCarlos Alberto Enciso     if (UseMatchedElements)
2066e28b9357SCarlos Alberto Enciso       options().resetPrintFormatting();
2067e28b9357SCarlos Alberto Enciso     print(OS);
2068e28b9357SCarlos Alberto Enciso 
2069e28b9357SCarlos Alberto Enciso     for (LVScope *Scope : *Scopes) {
2070e28b9357SCarlos Alberto Enciso       getReader().setCompileUnit(const_cast<LVScope *>(Scope));
2071e28b9357SCarlos Alberto Enciso 
2072e28b9357SCarlos Alberto Enciso       // If 'Split', we use the scope name (CU name) as the ouput file; the
2073e28b9357SCarlos Alberto Enciso       // delimiters in the pathname, must be replaced by a normal character.
2074e28b9357SCarlos Alberto Enciso       if (Split) {
2075e28b9357SCarlos Alberto Enciso         std::string ScopeName(Scope->getName());
2076e28b9357SCarlos Alberto Enciso         if (std::error_code EC =
2077e28b9357SCarlos Alberto Enciso                 getReaderSplitContext().open(ScopeName, ".txt", OS))
2078e28b9357SCarlos Alberto Enciso           return createStringError(EC, "Unable to create split output file %s",
2079e28b9357SCarlos Alberto Enciso                                    ScopeName.c_str());
2080e28b9357SCarlos Alberto Enciso         StreamSplit = static_cast<raw_ostream *>(&getReaderSplitContext().os());
2081e28b9357SCarlos Alberto Enciso       }
2082e28b9357SCarlos Alberto Enciso 
2083e28b9357SCarlos Alberto Enciso       Scope->printMatchedElements(*StreamSplit, UseMatchedElements);
2084e28b9357SCarlos Alberto Enciso 
2085e28b9357SCarlos Alberto Enciso       // Done printing the compile unit. Restore the original output context.
2086e28b9357SCarlos Alberto Enciso       if (Split) {
2087e28b9357SCarlos Alberto Enciso         getReaderSplitContext().close();
2088e28b9357SCarlos Alberto Enciso         StreamSplit = &getReader().outputStream();
2089e28b9357SCarlos Alberto Enciso       }
2090e28b9357SCarlos Alberto Enciso     }
2091e28b9357SCarlos Alberto Enciso     if (UseMatchedElements)
2092e28b9357SCarlos Alberto Enciso       options().setPrintFormatting();
2093e28b9357SCarlos Alberto Enciso   }
2094e28b9357SCarlos Alberto Enciso 
2095e28b9357SCarlos Alberto Enciso   return Error::success();
2096e28b9357SCarlos Alberto Enciso }
2097e28b9357SCarlos Alberto Enciso 
2098e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
2099e28b9357SCarlos Alberto Enciso // DWARF template parameter pack (DW_TAG_GNU_template_parameter_pack).
2100e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===//
equals(const LVScope * Scope) const2101e98a4c5aSCarlos Alberto Enciso bool LVScopeTemplatePack::equals(const LVScope *Scope) const {
2102e98a4c5aSCarlos Alberto Enciso   if (!LVScope::equals(Scope))
2103e98a4c5aSCarlos Alberto Enciso     return false;
2104e98a4c5aSCarlos Alberto Enciso   return equalNumberOfChildren(Scope);
2105e98a4c5aSCarlos Alberto Enciso }
2106e98a4c5aSCarlos Alberto Enciso 
printExtra(raw_ostream & OS,bool Full) const2107e28b9357SCarlos Alberto Enciso void LVScopeTemplatePack::printExtra(raw_ostream &OS, bool Full) const {
2108e28b9357SCarlos Alberto Enciso   OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
2109e28b9357SCarlos Alberto Enciso }
2110