1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00
llvm-mirror/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h
Alexey Lapshin 00fd3c3bb2 [dsymutil][DWARFLinker][NFC] Refactor usages of UniquingStringPool.
That refactoring is helpful since it reduces data inter-dependencies.
Which is good for current implementation and even more good for
fully multi-thread implementation. The idea of the refactoring
is to delete UniquingStringPool from the global DWARFLinker level.
It is used to unique type names while ODR deduplication is done.
Thus we move UniquingStringPool into the DeclContextTree which
matched to UniquingStringPool usage scope.

golden-dsymutil/dsymutil 23787992
clang MD5: 7d9873ff94f0246b6ab1ec3e8d0f3f06

build-Release/bin/dsymutil 23921272
clang MD5: 7d9873ff94f0246b6ab1ec3e8d0f3f06

Differential Revision: https://reviews.llvm.org/D93460
2021-01-03 14:44:51 +03:00

184 lines
7.0 KiB
C++

//===- DWARFLinkerDeclContext.h ---------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
#define LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/NonRelocatableStringpool.h"
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
namespace llvm {
struct DeclMapInfo;
/// Small helper that resolves and caches file paths. This helps reduce the
/// number of calls to realpath which is expensive. We assume the input are
/// files, and cache the realpath of their parent. This way we can quickly
/// resolve different files under the same path.
class CachedPathResolver {
public:
/// Resolve a path by calling realpath and cache its result. The returned
/// StringRef is interned in the given \p StringPool.
StringRef resolve(const std::string &Path,
NonRelocatableStringpool &StringPool) {
StringRef FileName = sys::path::filename(Path);
StringRef ParentPath = sys::path::parent_path(Path);
// If the ParentPath has not yet been resolved, resolve and cache it for
// future look-ups.
if (!ResolvedPaths.count(ParentPath)) {
SmallString<256> RealPath;
sys::fs::real_path(ParentPath, RealPath);
ResolvedPaths.insert(
{ParentPath, std::string(RealPath.c_str(), RealPath.size())});
}
// Join the file name again with the resolved path.
SmallString<256> ResolvedPath(ResolvedPaths[ParentPath]);
sys::path::append(ResolvedPath, FileName);
return StringPool.internString(ResolvedPath);
}
private:
StringMap<std::string> ResolvedPaths;
};
/// A DeclContext is a named program scope that is used for ODR uniquing of
/// types.
///
/// The set of DeclContext for the ODR-subject parts of a Dwarf link is
/// expanded (and uniqued) with each new object file processed. We need to
/// determine the context of each DIE in an linked object file to see if the
/// corresponding type has already been emitted.
///
/// The contexts are conceptually organized as a tree (eg. a function scope is
/// contained in a namespace scope that contains other scopes), but
/// storing/accessing them in an actual tree is too inefficient: we need to be
/// able to very quickly query a context for a given child context by name.
/// Storing a StringMap in each DeclContext would be too space inefficient.
///
/// The solution here is to give each DeclContext a link to its parent (this
/// allows to walk up the tree), but to query the existence of a specific
/// DeclContext using a separate DenseMap keyed on the hash of the fully
/// qualified name of the context.
class DeclContext {
public:
using Map = DenseSet<DeclContext *, DeclMapInfo>;
DeclContext() : DefinedInClangModule(0), Parent(*this) {}
DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag,
StringRef Name, StringRef File, const DeclContext &Parent,
DWARFDie LastSeenDIE = DWARFDie(), unsigned CUId = 0)
: QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag),
DefinedInClangModule(0), Name(Name), File(File), Parent(Parent),
LastSeenDIE(LastSeenDIE), LastSeenCompileUnitID(CUId) {}
uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
bool setLastSeenDIE(CompileUnit &U, const DWARFDie &Die);
uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; }
bool isDefinedInClangModule() const { return DefinedInClangModule; }
void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; }
uint16_t getTag() const { return Tag; }
private:
friend DeclMapInfo;
unsigned QualifiedNameHash = 0;
uint32_t Line = 0;
uint32_t ByteSize = 0;
uint16_t Tag = dwarf::DW_TAG_compile_unit;
unsigned DefinedInClangModule : 1;
StringRef Name;
StringRef File;
const DeclContext &Parent;
DWARFDie LastSeenDIE;
uint32_t LastSeenCompileUnitID = 0;
uint32_t CanonicalDIEOffset = 0;
};
/// This class gives a tree-like API to the DenseMap that stores the
/// DeclContext objects. It holds the BumpPtrAllocator where these objects will
/// be allocated.
class DeclContextTree {
public:
/// Get the child of \a Context described by \a DIE in \a Unit. The
/// required strings will be interned in \a StringPool.
/// \returns The child DeclContext along with one bit that is set if
/// this context is invalid.
///
/// An invalid context means it shouldn't be considered for uniquing, but its
/// not returning null, because some children of that context might be
/// uniquing candidates.
///
/// FIXME: The invalid bit along the return value is to emulate some
/// dsymutil-classic functionality.
PointerIntPair<DeclContext *, 1> getChildDeclContext(DeclContext &Context,
const DWARFDie &DIE,
CompileUnit &Unit,
bool InClangModule);
DeclContext &getRoot() { return Root; }
private:
BumpPtrAllocator Allocator;
DeclContext Root;
DeclContext::Map Contexts;
/// Cached resolved paths from the line table.
/// The key is <UniqueUnitID, FileIdx>.
using ResolvedPathsMap = DenseMap<std::pair<unsigned, unsigned>, StringRef>;
ResolvedPathsMap ResolvedPaths;
/// Helper that resolves and caches fragments of file paths.
CachedPathResolver PathResolver;
/// String pool keeping real path bodies.
NonRelocatableStringpool StringPool;
StringRef getResolvedPath(CompileUnit &CU, unsigned FileNum,
const DWARFDebugLine::LineTable &LineTable);
};
/// Info type for the DenseMap storing the DeclContext pointers.
struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
using DenseMapInfo<DeclContext *>::getEmptyKey;
using DenseMapInfo<DeclContext *>::getTombstoneKey;
static unsigned getHashValue(const DeclContext *Ctxt) {
return Ctxt->QualifiedNameHash;
}
static bool isEqual(const DeclContext *LHS, const DeclContext *RHS) {
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
return RHS == LHS;
return LHS->QualifiedNameHash == RHS->QualifiedNameHash &&
LHS->Line == RHS->Line && LHS->ByteSize == RHS->ByteSize &&
LHS->Name.data() == RHS->Name.data() &&
LHS->File.data() == RHS->File.data() &&
LHS->Parent.QualifiedNameHash == RHS->Parent.QualifiedNameHash;
}
};
} // end namespace llvm
#endif // LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H