1292236Sjhb//===-- LVSymbol.cpp ------------------------------------------------------===//
2292236Sjhb//
3292236Sjhb// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4292236Sjhb// See https://llvm.org/LICENSE.txt for license information.
5298107Sgjb// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6292236Sjhb//
7292236Sjhb//===----------------------------------------------------------------------===//
8311999Sjhb//
9292236Sjhb// This implements the LVSymbol class.
10292236Sjhb//
11311999Sjhb//===----------------------------------------------------------------------===//
12313538Sngie
13313538Sngie#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
14294849Sjhb#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
15311999Sjhb#include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
16295931Sjhb#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
17311999Sjhb#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
18332247Stuexen
19311999Sjhbusing namespace llvm;
20311999Sjhbusing namespace llvm::logicalview;
21328454Sjhb
22292622Sjhb#define DEBUG_TYPE "Symbol"
23311999Sjhb
24311999Sjhbnamespace {
25332244Stuexenconst char *const KindCallSiteParameter = "CallSiteParameter";
26311999Sjhbconst char *const KindConstant = "Constant";
27311999Sjhbconst char *const KindInherits = "Inherits";
28319417Stuexenconst char *const KindMember = "Member";
29294849Sjhbconst char *const KindParameter = "Parameter";
30292236Sjhbconst char *const KindUndefined = "Undefined";
31311999Sjhbconst char *const KindUnspecified = "Unspecified";
32311999Sjhbconst char *const KindVariable = "Variable";
33311999Sjhb} // end anonymous namespace
34311999Sjhb
35311999Sjhb// Return a string representation for the symbol kind.
36311999Sjhbconst char *LVSymbol::kind() const {
37311999Sjhb  const char *Kind = KindUndefined;
38326044Sjhb  if (getIsCallSiteParameter())
39311999Sjhb    Kind = KindCallSiteParameter;
40311999Sjhb  else if (getIsConstant())
41311999Sjhb    Kind = KindConstant;
42311999Sjhb  else if (getIsInheritance())
43311999Sjhb    Kind = KindInherits;
44311999Sjhb  else if (getIsMember())
45311999Sjhb    Kind = KindMember;
46311999Sjhb  else if (getIsParameter())
47311999Sjhb    Kind = KindParameter;
48326044Sjhb  else if (getIsUnspecified())
49311999Sjhb    Kind = KindUnspecified;
50311999Sjhb  else if (getIsVariable())
51311999Sjhb    Kind = KindVariable;
52311999Sjhb  return Kind;
53311999Sjhb}
54311999Sjhb
55332243StuexenLVSymbolDispatch LVSymbol::Dispatch = {
56311999Sjhb    {LVSymbolKind::IsCallSiteParameter, &LVSymbol::getIsCallSiteParameter},
57311999Sjhb    {LVSymbolKind::IsConstant, &LVSymbol::getIsConstant},
58311999Sjhb    {LVSymbolKind::IsInheritance, &LVSymbol::getIsInheritance},
59311999Sjhb    {LVSymbolKind::IsMember, &LVSymbol::getIsMember},
60311999Sjhb    {LVSymbolKind::IsParameter, &LVSymbol::getIsParameter},
61311999Sjhb    {LVSymbolKind::IsUnspecified, &LVSymbol::getIsUnspecified},
62311999Sjhb    {LVSymbolKind::IsVariable, &LVSymbol::getIsVariable}};
63311999Sjhb
64311999Sjhb// Add a Location Entry.
65311999Sjhbvoid LVSymbol::addLocation(dwarf::Attribute Attr, LVAddress LowPC,
66311999Sjhb                           LVAddress HighPC, LVUnsigned SectionOffset,
67311999Sjhb                           uint64_t LocDescOffset, bool CallSiteLocation) {
68311999Sjhb  if (!Locations)
69311999Sjhb    Locations = std::make_unique<LVLocations>();
70311999Sjhb
71326044Sjhb  // Create the location entry.
72311999Sjhb  CurrentLocation = getReader().createLocationSymbol();
73311999Sjhb  CurrentLocation->setParent(this);
74311999Sjhb  CurrentLocation->setAttr(Attr);
75311999Sjhb  if (CallSiteLocation)
76328454Sjhb    CurrentLocation->setIsCallSite();
77328454Sjhb  CurrentLocation->addObject(LowPC, HighPC, SectionOffset, LocDescOffset);
78328454Sjhb  Locations->push_back(CurrentLocation);
79311999Sjhb
80326044Sjhb  // Mark the symbol as having location information.
81311999Sjhb  setHasLocation();
82311999Sjhb}
83311999Sjhb
84311999Sjhb// Add a Location Record.
85311999Sjhbvoid LVSymbol::addLocationOperands(LVSmall Opcode,
86311999Sjhb                                   ArrayRef<uint64_t> Operands) {
87311999Sjhb  if (CurrentLocation)
88311999Sjhb    CurrentLocation->addObject(Opcode, Operands);
89311999Sjhb}
90311999Sjhb
91311999Sjhb// Add a Location Entry.
92311999Sjhbvoid LVSymbol::addLocationConstant(dwarf::Attribute Attr, LVUnsigned Constant,
93311999Sjhb                                   uint64_t LocDescOffset) {
94311999Sjhb  // Create a Location Entry, with the global information.
95311999Sjhb  addLocation(Attr,
96311999Sjhb              /*LowPC=*/0, /*HighPC=*/-1,
97311999Sjhb              /*SectionOffset=*/0, LocDescOffset);
98311999Sjhb
99332248Stuexen  // Add records to Location Entry.
100332248Stuexen  addLocationOperands(/*Opcode=*/LVLocationMemberOffset, {Constant});
101332248Stuexen}
102311999Sjhb
103311999SjhbLVLocations::iterator LVSymbol::addLocationGap(LVLocations::iterator Pos,
104311999Sjhb                                               LVAddress LowPC,
105311999Sjhb                                               LVAddress HighPC) {
106311999Sjhb  // Create a location entry for the gap.
107311999Sjhb  LVLocation *Gap = getReader().createLocationSymbol();
108311999Sjhb  Gap->setParent(this);
109292236Sjhb  Gap->setAttr(dwarf::DW_AT_location);
110351891Sbdrewery  Gap->addObject(LowPC, HighPC,
111292622Sjhb                 /*section_offset=*/0,
112292622Sjhb                 /*locdesc_offset=*/0);
113292622Sjhb
114292622Sjhb  LVLocations::iterator Iter = Locations->insert(Pos, Gap);
115292622Sjhb
116292622Sjhb  // Add gap to Location Entry.
117292622Sjhb  Gap->addObject(dwarf::DW_OP_hi_user, {});
118292622Sjhb
119292622Sjhb  // Mark the entry as a gap.
120292622Sjhb  Gap->setIsGapEntry();
121292622Sjhb
122294849Sjhb  return Iter;
123294849Sjhb}
124294849Sjhb
125294849Sjhbvoid LVSymbol::fillLocationGaps() {
126361020Sjhb  // The symbol has locations records. Fill gaps in the location list.
127361020Sjhb  if (!getHasLocation() || !getFillGaps())
128361020Sjhb    return;
129361020Sjhb
130361020Sjhb  // Get the parent range information and add dummy location entries.
131361020Sjhb  const LVLocations *Ranges = getParentScope()->getRanges();
132361020Sjhb  if (!Ranges)
133292622Sjhb    return;
134292622Sjhb
135311999Sjhb  for (const LVLocation *Entry : *Ranges) {
136311999Sjhb    LVAddress ParentLowPC = Entry->getLowerAddress();
137311999Sjhb    LVAddress ParentHighPC = Entry->getUpperAddress();
138311999Sjhb
139311999Sjhb    // Traverse the symbol locations and for each location contained in
140311999Sjhb    // the current parent range, insert locations for any existing gap.
141311999Sjhb    LVLocation *Location;
142311999Sjhb    LVAddress LowPC = 0;
143311999Sjhb    LVAddress Marker = ParentLowPC;
144311999Sjhb    for (LVLocations::iterator Iter = Locations->begin();
145321687Skp         Iter != Locations->end(); ++Iter) {
146292622Sjhb      Location = *Iter;
147292622Sjhb      LowPC = Location->getLowerAddress();
148311999Sjhb      if (LowPC != Marker) {
149292622Sjhb        // We have a gap at [Marker,LowPC - 1].
150292236Sjhb        Iter = addLocationGap(Iter, Marker, LowPC - 1);
151        ++Iter;
152      }
153
154      // Move to the next item in the location list.
155      Marker = Location->getUpperAddress() + 1;
156    }
157
158    // Check any gap at the end.
159    if (Marker < ParentHighPC)
160      // We have a gap at [Marker,ParentHighPC].
161      addLocationGap(Locations->end(), Marker, ParentHighPC);
162  }
163}
164
165// Get all the locations based on the valid function.
166void LVSymbol::getLocations(LVLocations &LocationList,
167                            LVValidLocation ValidLocation, bool RecordInvalid) {
168  if (!Locations)
169    return;
170
171  for (LVLocation *Location : *Locations) {
172    // Add the invalid location object.
173    if (!(Location->*ValidLocation)() && RecordInvalid)
174      LocationList.push_back(Location);
175  }
176
177  // Calculate coverage factor.
178  calculateCoverage();
179}
180
181void LVSymbol::getLocations(LVLocations &LocationList) const {
182  if (!Locations)
183    return;
184
185  for (LVLocation *Location : *Locations)
186    LocationList.push_back(Location);
187}
188
189// Calculate coverage factor.
190void LVSymbol::calculateCoverage() {
191  if (!LVLocation::calculateCoverage(Locations.get(), CoverageFactor,
192                                     CoveragePercentage)) {
193    LVScope *Parent = getParentScope();
194    if (Parent->getIsInlinedFunction()) {
195      // For symbols representing the inlined function parameters and its
196      // variables, get the outer most parent that contains their location
197      // lower address.
198      // The symbol can have a set of non-contiguous locations. We are using
199      // only the first location entry to get the outermost parent.
200      // If no scope contains the location, assume its enclosing parent.
201      LVScope *Scope =
202          Parent->outermostParent(Locations->front()->getLowerAddress());
203      if (Scope)
204        Parent = Scope;
205    }
206    unsigned CoverageParent = Parent->getCoverageFactor();
207    // Get a percentage rounded to two decimal digits. This avoids
208    // implementation-defined rounding inside printing functions.
209    CoveragePercentage =
210        CoverageParent
211            ? rint((double(CoverageFactor) / CoverageParent) * 100.0 * 100.0) /
212                  100.0
213            : 0;
214    // Record invalid coverage entry.
215    if (options().getWarningCoverages() && CoveragePercentage > 100)
216      getReaderCompileUnit()->addInvalidCoverage(this);
217  }
218}
219
220void LVSymbol::resolveName() {
221  if (getIsResolvedName())
222    return;
223  setIsResolvedName();
224
225  LVElement::resolveName();
226
227  // Resolve any given pattern.
228  patterns().resolvePatternMatch(this);
229}
230
231void LVSymbol::resolveReferences() {
232  // The symbols can have the following references to other elements:
233  //   A Type:
234  //     DW_AT_type             ->  Type or Scope
235  //     DW_AT_import           ->  Type
236  //   A Reference:
237  //     DW_AT_specification    ->  Symbol
238  //     DW_AT_abstract_origin  ->  Symbol
239  //     DW_AT_extension        ->  Symbol
240
241  // Resolve any referenced symbol.
242  LVSymbol *Reference = getReference();
243  if (Reference) {
244    Reference->resolve();
245    // Recursively resolve the symbol names.
246    resolveReferencesChain();
247  }
248
249  // Set the file/line information using the Debug Information entry.
250  setFile(Reference);
251
252  // Resolve symbol type.
253  if (LVElement *Element = getType()) {
254    Element->resolve();
255
256    // In the case of demoted typedefs, use the underlying type.
257    if (Element->getIsTypedefReduced()) {
258      Element = Element->getType();
259      Element->resolve();
260    }
261
262    // If the type is a template parameter, get its type, which can
263    // point to a type or scope, depending on the argument instance.
264    setGenericType(Element);
265  }
266
267  // Resolve the variable associated type.
268  if (!getType() && Reference)
269    setType(Reference->getType());
270}
271
272StringRef LVSymbol::resolveReferencesChain() {
273  // If the symbol have a DW_AT_specification or DW_AT_abstract_origin,
274  // follow the chain to resolve the name from those references.
275  if (getHasReference() && !isNamed())
276    setName(getReference()->resolveReferencesChain());
277
278  return getName();
279}
280
281void LVSymbol::markMissingParents(const LVSymbols *References,
282                                  const LVSymbols *Targets) {
283  if (!(References && Targets))
284    return;
285
286  LLVM_DEBUG({
287    dbgs() << "\n[LVSymbol::markMissingParents]\n";
288    for (const LVSymbol *Reference : *References)
289      dbgs() << "References: "
290             << "Kind = " << formattedKind(Reference->kind()) << ", "
291             << "Name = " << formattedName(Reference->getName()) << "\n";
292    for (const LVSymbol *Target : *Targets)
293      dbgs() << "Targets   : "
294             << "Kind = " << formattedKind(Target->kind()) << ", "
295             << "Name = " << formattedName(Target->getName()) << "\n";
296  });
297
298  for (LVSymbol *Reference : *References) {
299    LLVM_DEBUG({
300      dbgs() << "Search Reference: Name = "
301             << formattedName(Reference->getName()) << "\n";
302    });
303    if (!Reference->findIn(Targets))
304      Reference->markBranchAsMissing();
305  }
306}
307
308LVSymbol *LVSymbol::findIn(const LVSymbols *Targets) const {
309  if (!Targets)
310    return nullptr;
311
312  LLVM_DEBUG({
313    dbgs() << "\n[LVSymbol::findIn]\n"
314           << "Reference: "
315           << "Level = " << getLevel() << ", "
316           << "Kind = " << formattedKind(kind()) << ", "
317           << "Name = " << formattedName(getName()) << "\n";
318    for (const LVSymbol *Target : *Targets)
319      dbgs() << "Target   : "
320             << "Level = " << Target->getLevel() << ", "
321             << "Kind = " << formattedKind(Target->kind()) << ", "
322             << "Name = " << formattedName(Target->getName()) << "\n";
323  });
324
325  for (LVSymbol *Target : *Targets)
326    if (equals(Target))
327      return Target;
328
329  return nullptr;
330}
331
332// Check for a match on the arguments of a function.
333bool LVSymbol::parametersMatch(const LVSymbols *References,
334                               const LVSymbols *Targets) {
335  if (!References && !Targets)
336    return true;
337  if (References && Targets) {
338    LVSymbols ReferenceParams;
339    getParameters(References, &ReferenceParams);
340    LVSymbols TargetParams;
341    getParameters(Targets, &TargetParams);
342    return LVSymbol::equals(&ReferenceParams, &TargetParams);
343  }
344  return false;
345}
346
347// Return the symbols which are parameters.
348void LVSymbol::getParameters(const LVSymbols *Symbols, LVSymbols *Parameters) {
349  if (Symbols)
350    for (LVSymbol *Symbol : *Symbols)
351      if (Symbol->getIsParameter())
352        Parameters->push_back(Symbol);
353}
354
355bool LVSymbol::equals(const LVSymbol *Symbol) const {
356  if (!LVElement::equals(Symbol))
357    return false;
358
359  // Check if any reference is the same.
360  if (!referenceMatch(Symbol))
361    return false;
362
363  if (getReference() && !getReference()->equals(Symbol->getReference()))
364    return false;
365
366  return true;
367}
368
369bool LVSymbol::equals(const LVSymbols *References, const LVSymbols *Targets) {
370  if (!References && !Targets)
371    return true;
372  if (References && Targets && References->size() == Targets->size()) {
373    for (const LVSymbol *Reference : *References)
374      if (!Reference->findIn(Targets))
375        return false;
376    return true;
377  }
378  return false;
379}
380
381void LVSymbol::report(LVComparePass Pass) {
382  getComparator().printItem(this, Pass);
383}
384
385void LVSymbol::printLocations(raw_ostream &OS, bool Full) const {
386  if (Locations)
387    for (const LVLocation *Location : *Locations)
388      Location->printRaw(OS, Full);
389}
390
391void LVSymbol::print(raw_ostream &OS, bool Full) const {
392  if (getIncludeInPrint() && getReader().doPrintSymbol(this)) {
393    getReaderCompileUnit()->incrementPrintedSymbols();
394    LVElement::print(OS, Full);
395    printExtra(OS, Full);
396  }
397}
398
399void LVSymbol::printExtra(raw_ostream &OS, bool Full) const {
400  // Accessibility depends on the parent (class, structure).
401  uint32_t AccessCode = 0;
402  if (getIsMember() || getIsInheritance())
403    AccessCode = getParentScope()->getIsClass() ? dwarf::DW_ACCESS_private
404                                                : dwarf::DW_ACCESS_public;
405
406  const LVSymbol *Symbol = getIsInlined() ? Reference : this;
407  std::string Attributes =
408      Symbol->getIsCallSiteParameter()
409          ? ""
410          : formatAttributes(Symbol->externalString(),
411                             Symbol->accessibilityString(AccessCode),
412                             virtualityString());
413
414  OS << formattedKind(Symbol->kind()) << " " << Attributes;
415  if (Symbol->getIsUnspecified())
416    OS << formattedName(Symbol->getName());
417  else {
418    if (Symbol->getIsInheritance())
419      OS << Symbol->typeOffsetAsString()
420         << formattedNames(Symbol->getTypeQualifiedName(),
421                           Symbol->typeAsString());
422    else {
423      OS << formattedName(Symbol->getName());
424      // Print any bitfield information.
425      if (uint32_t Size = getBitSize())
426        OS << ":" << Size;
427      OS << " -> " << Symbol->typeOffsetAsString()
428         << formattedNames(Symbol->getTypeQualifiedName(),
429                           Symbol->typeAsString());
430    }
431  }
432
433  // Print any initial value if any.
434  if (ValueIndex)
435    OS << " = " << formattedName(getValue());
436  OS << "\n";
437
438  if (Full && options().getPrintFormatting()) {
439    if (getLinkageNameIndex())
440      printLinkageName(OS, Full, const_cast<LVSymbol *>(this));
441    if (LVSymbol *Reference = getReference())
442      Reference->printReference(OS, Full, const_cast<LVSymbol *>(this));
443
444    // Print location information.
445    LVLocation::print(Locations.get(), OS, Full);
446  }
447}
448