Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- DWARFLinkerDeclContext.h ---------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
 
9
#ifndef LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
10
#define LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
11
 
12
#include "llvm/ADT/DenseMap.h"
13
#include "llvm/ADT/DenseMapInfo.h"
14
#include "llvm/ADT/DenseSet.h"
15
#include "llvm/ADT/StringRef.h"
16
#include "llvm/CodeGen/NonRelocatableStringpool.h"
17
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
18
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
19
#include "llvm/Support/FileSystem.h"
20
#include "llvm/Support/Path.h"
21
#include <atomic>
22
 
23
namespace llvm {
24
 
25
class CompileUnit;
26
struct DeclMapInfo;
27
 
28
/// Small helper that resolves and caches file paths. This helps reduce the
29
/// number of calls to realpath which is expensive. We assume the input are
30
/// files, and cache the realpath of their parent. This way we can quickly
31
/// resolve different files under the same path.
32
class CachedPathResolver {
33
public:
34
  /// Resolve a path by calling realpath and cache its result. The returned
35
  /// StringRef is interned in the given \p StringPool.
36
  StringRef resolve(const std::string &Path,
37
                    NonRelocatableStringpool &StringPool) {
38
    StringRef FileName = sys::path::filename(Path);
39
    StringRef ParentPath = sys::path::parent_path(Path);
40
 
41
    // If the ParentPath has not yet been resolved, resolve and cache it for
42
    // future look-ups.
43
    if (!ResolvedPaths.count(ParentPath)) {
44
      SmallString<256> RealPath;
45
      sys::fs::real_path(ParentPath, RealPath);
46
      ResolvedPaths.insert(
47
          {ParentPath, std::string(RealPath.c_str(), RealPath.size())});
48
    }
49
 
50
    // Join the file name again with the resolved path.
51
    SmallString<256> ResolvedPath(ResolvedPaths[ParentPath]);
52
    sys::path::append(ResolvedPath, FileName);
53
    return StringPool.internString(ResolvedPath);
54
  }
55
 
56
private:
57
  StringMap<std::string> ResolvedPaths;
58
};
59
 
60
/// A DeclContext is a named program scope that is used for ODR uniquing of
61
/// types.
62
///
63
/// The set of DeclContext for the ODR-subject parts of a Dwarf link is
64
/// expanded (and uniqued) with each new object file processed. We need to
65
/// determine the context of each DIE in an linked object file to see if the
66
/// corresponding type has already been emitted.
67
///
68
/// The contexts are conceptually organized as a tree (eg. a function scope is
69
/// contained in a namespace scope that contains other scopes), but
70
/// storing/accessing them in an actual tree is too inefficient: we need to be
71
/// able to very quickly query a context for a given child context by name.
72
/// Storing a StringMap in each DeclContext would be too space inefficient.
73
///
74
/// The solution here is to give each DeclContext a link to its parent (this
75
/// allows to walk up the tree), but to query the existence of a specific
76
/// DeclContext using a separate DenseMap keyed on the hash of the fully
77
/// qualified name of the context.
78
class DeclContext {
79
public:
80
  using Map = DenseSet<DeclContext *, DeclMapInfo>;
81
 
82
  DeclContext() : DefinedInClangModule(0), Parent(*this) {}
83
 
84
  DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag,
85
              StringRef Name, StringRef File, const DeclContext &Parent,
86
              DWARFDie LastSeenDIE = DWARFDie(), unsigned CUId = 0)
87
      : QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag),
88
        DefinedInClangModule(0), Name(Name), File(File), Parent(Parent),
89
        LastSeenDIE(LastSeenDIE), LastSeenCompileUnitID(CUId) {}
90
 
91
  uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
92
 
93
  bool setLastSeenDIE(CompileUnit &U, const DWARFDie &Die);
94
 
95
  void setHasCanonicalDIE() { HasCanonicalDIE = true; }
96
 
97
  bool hasCanonicalDIE() const { return HasCanonicalDIE; }
98
 
99
  uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
100
  void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; }
101
 
102
  bool isDefinedInClangModule() const { return DefinedInClangModule; }
103
  void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; }
104
 
105
  uint16_t getTag() const { return Tag; }
106
 
107
private:
108
  friend DeclMapInfo;
109
 
110
  unsigned QualifiedNameHash = 0;
111
  uint32_t Line = 0;
112
  uint32_t ByteSize = 0;
113
  uint16_t Tag = dwarf::DW_TAG_compile_unit;
114
  unsigned DefinedInClangModule : 1;
115
  StringRef Name;
116
  StringRef File;
117
  const DeclContext &Parent;
118
  DWARFDie LastSeenDIE;
119
  uint32_t LastSeenCompileUnitID = 0;
120
  std::atomic<uint32_t> CanonicalDIEOffset = {0};
121
  bool HasCanonicalDIE = false;
122
};
123
 
124
/// This class gives a tree-like API to the DenseMap that stores the
125
/// DeclContext objects. It holds the BumpPtrAllocator where these objects will
126
/// be allocated.
127
class DeclContextTree {
128
public:
129
  /// Get the child of \a Context described by \a DIE in \a Unit. The
130
  /// required strings will be interned in \a StringPool.
131
  /// \returns The child DeclContext along with one bit that is set if
132
  /// this context is invalid.
133
  ///
134
  /// An invalid context means it shouldn't be considered for uniquing, but its
135
  /// not returning null, because some children of that context might be
136
  /// uniquing candidates.
137
  ///
138
  /// FIXME: The invalid bit along the return value is to emulate some
139
  /// dsymutil-classic functionality.
140
  PointerIntPair<DeclContext *, 1> getChildDeclContext(DeclContext &Context,
141
                                                       const DWARFDie &DIE,
142
                                                       CompileUnit &Unit,
143
                                                       bool InClangModule);
144
 
145
  DeclContext &getRoot() { return Root; }
146
 
147
private:
148
  BumpPtrAllocator Allocator;
149
  DeclContext Root;
150
  DeclContext::Map Contexts;
151
 
152
  /// Cached resolved paths from the line table.
153
  /// The key is <UniqueUnitID, FileIdx>.
154
  using ResolvedPathsMap = DenseMap<std::pair<unsigned, unsigned>, StringRef>;
155
  ResolvedPathsMap ResolvedPaths;
156
 
157
  /// Helper that resolves and caches fragments of file paths.
158
  CachedPathResolver PathResolver;
159
 
160
  /// String pool keeping real path bodies.
161
  NonRelocatableStringpool StringPool;
162
 
163
  StringRef getResolvedPath(CompileUnit &CU, unsigned FileNum,
164
                            const DWARFDebugLine::LineTable &LineTable);
165
};
166
 
167
/// Info type for the DenseMap storing the DeclContext pointers.
168
struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
169
  using DenseMapInfo<DeclContext *>::getEmptyKey;
170
  using DenseMapInfo<DeclContext *>::getTombstoneKey;
171
 
172
  static unsigned getHashValue(const DeclContext *Ctxt) {
173
    return Ctxt->QualifiedNameHash;
174
  }
175
 
176
  static bool isEqual(const DeclContext *LHS, const DeclContext *RHS) {
177
    if (RHS == getEmptyKey() || RHS == getTombstoneKey())
178
      return RHS == LHS;
179
    return LHS->QualifiedNameHash == RHS->QualifiedNameHash &&
180
           LHS->Line == RHS->Line && LHS->ByteSize == RHS->ByteSize &&
181
           LHS->Name.data() == RHS->Name.data() &&
182
           LHS->File.data() == RHS->File.data() &&
183
           LHS->Parent.QualifiedNameHash == RHS->Parent.QualifiedNameHash;
184
  }
185
};
186
 
187
} // end namespace llvm
188
 
189
#endif // LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H