Revert " [LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)"
[llvm-project.git] / llvm / lib / DWARFLinker / Parallel / TypePool.h
blob547532977262b15fe8a667141911ec46c51aaebd
1 //===- TypePool.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 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_DWARFLINKER_PARALLEL_TYPEPOOL_H
10 #define LLVM_DWARFLINKER_PARALLEL_TYPEPOOL_H
12 #include "ArrayList.h"
13 #include "llvm/ADT/ConcurrentHashtable.h"
14 #include "llvm/ADT/StringMap.h"
15 #include "llvm/CodeGen/DIE.h"
16 #include "llvm/Support/Allocator.h"
17 #include <atomic>
19 namespace llvm {
20 namespace dwarf_linker {
21 namespace parallel {
23 class TypePool;
24 class CompileUnit;
25 class TypeEntryBody;
27 using TypeEntry = StringMapEntry<std::atomic<TypeEntryBody *>>;
29 /// Keeps cloned data for the type DIE.
30 class TypeEntryBody {
31 public:
32 /// Returns copy of type DIE which should be emitted into resulting file.
33 DIE &getFinalDie() const {
34 if (Die)
35 return *Die;
37 assert(DeclarationDie);
38 return *DeclarationDie;
41 /// Returns true if type die entry has only declaration die.
42 bool hasOnlyDeclaration() const { return Die == nullptr; }
44 /// Creates type DIE for the specified name.
45 static TypeEntryBody *
46 create(llvm::parallel::PerThreadBumpPtrAllocator &Allocator) {
47 TypeEntryBody *Result = Allocator.Allocate<TypeEntryBody>();
48 new (Result) TypeEntryBody(Allocator);
49 return Result;
52 /// TypeEntryBody keeps partially cloned DIEs corresponding to this type.
53 /// The two kinds of DIE can be kept: declaration and definition.
54 /// If definition DIE was met while parsing input DWARF then this DIE would
55 /// be used as a final DIE for this type. If definition DIE is not met then
56 /// declaration DIE would be used as a final DIE.
58 // Keeps definition die.
59 std::atomic<DIE *> Die = {nullptr};
61 // Keeps declaration die.
62 std::atomic<DIE *> DeclarationDie = {nullptr};
64 // True if parent type die is declaration.
65 std::atomic<bool> ParentIsDeclaration = {true};
67 /// Children for current type.
68 ArrayList<TypeEntry *, 5> Children;
70 protected:
71 TypeEntryBody() = delete;
72 TypeEntryBody(const TypeEntryBody &RHS) = delete;
73 TypeEntryBody(TypeEntryBody &&RHS) = delete;
74 TypeEntryBody &operator=(const TypeEntryBody &RHS) = delete;
75 TypeEntryBody &operator=(const TypeEntryBody &&RHS) = delete;
77 TypeEntryBody(llvm::parallel::PerThreadBumpPtrAllocator &Allocator)
78 : Children(&Allocator) {}
81 class TypeEntryInfo {
82 public:
83 /// \returns Hash value for the specified \p Key.
84 static inline uint64_t getHashValue(const StringRef &Key) {
85 return xxh3_64bits(Key);
88 /// \returns true if both \p LHS and \p RHS are equal.
89 static inline bool isEqual(const StringRef &LHS, const StringRef &RHS) {
90 return LHS == RHS;
93 /// \returns key for the specified \p KeyData.
94 static inline StringRef getKey(const TypeEntry &KeyData) {
95 return KeyData.getKey();
98 /// \returns newly created object of KeyDataTy type.
99 static inline TypeEntry *
100 create(const StringRef &Key,
101 llvm::parallel::PerThreadBumpPtrAllocator &Allocator) {
102 return TypeEntry::create(Key, Allocator);
106 /// TypePool keeps type descriptors which contain partially cloned DIE
107 /// correspinding to each type. Types are identified by names.
108 class TypePool
109 : ConcurrentHashTableByPtr<StringRef, TypeEntry,
110 llvm::parallel::PerThreadBumpPtrAllocator,
111 TypeEntryInfo> {
112 public:
113 TypePool()
114 : ConcurrentHashTableByPtr<StringRef, TypeEntry,
115 llvm::parallel::PerThreadBumpPtrAllocator,
116 TypeEntryInfo>(Allocator) {
117 Root = TypeEntry::create("", Allocator);
118 Root->getValue().store(TypeEntryBody::create(Allocator));
121 TypeEntry *insert(StringRef Name) {
122 return ConcurrentHashTableByPtr<StringRef, TypeEntry,
123 llvm::parallel::PerThreadBumpPtrAllocator,
124 TypeEntryInfo>::insert(Name)
125 .first;
128 /// Create or return existing type entry body for the specified \p Entry.
129 /// Link that entry as child for the specified \p ParentEntry.
130 /// \returns The existing or created type entry body.
131 TypeEntryBody *getOrCreateTypeEntryBody(TypeEntry *Entry,
132 TypeEntry *ParentEntry) {
133 TypeEntryBody *DIE = Entry->getValue().load();
134 if (DIE)
135 return DIE;
137 TypeEntryBody *NewDIE = TypeEntryBody::create(Allocator);
138 if (Entry->getValue().compare_exchange_weak(DIE, NewDIE)) {
139 ParentEntry->getValue().load()->Children.add(Entry);
140 return NewDIE;
143 return DIE;
146 /// Sort children for each kept type entry.
147 void sortTypes() {
148 std::function<void(TypeEntry * Entry)> SortChildrenRec =
149 [&](TypeEntry *Entry) {
150 Entry->getValue().load()->Children.sort(TypesComparator);
151 Entry->getValue().load()->Children.forEach(SortChildrenRec);
154 SortChildrenRec(getRoot());
157 /// Return root for all type entries.
158 TypeEntry *getRoot() const { return Root; }
160 /// Return thread local allocator used by pool.
161 BumpPtrAllocator &getThreadLocalAllocator() {
162 return Allocator.getThreadLocalAllocator();
165 protected:
166 std::function<bool(const TypeEntry *LHS, const TypeEntry *RHS)>
167 TypesComparator = [](const TypeEntry *LHS, const TypeEntry *RHS) -> bool {
168 return LHS->getKey() < RHS->getKey();
171 // Root of all type entries.
172 TypeEntry *Root = nullptr;
174 private:
175 llvm::parallel::PerThreadBumpPtrAllocator Allocator;
178 } // end of namespace parallel
179 } // end of namespace dwarf_linker
180 } // end of namespace llvm
182 #endif // LLVM_DWARFLINKER_PARALLEL_TYPEPOOL_H