LLVM 24.0.0git
TypePool.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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#include "TypePool.h"
11#include <cstring>
12
13using namespace llvm;
14using namespace dwarf_linker;
15using namespace dwarf_linker::parallel;
16
17void TypeKey::appendRef(const TypeEntry *Entry) {
18 assert(Entry && "null reference");
19 Bytes.push_back(RefMarker);
20 const char *EntryBytes = reinterpret_cast<const char *>(&Entry);
21 Bytes.append(EntryBytes, EntryBytes + sizeof(Entry));
22}
23
25 assert(!Key.empty() && "no part to take");
26 if (Key.front() != RefMarker) {
27 StringRef Text = Key.take_front(Key.find(RefMarker));
28 Key = Key.drop_front(Text.size());
29 return Text;
30 }
31 assert(Key.size() >= RefSize && "truncated reference");
32 const TypeEntry *Ref;
33 std::memcpy(&Ref, Key.data() + 1, sizeof(Ref));
34 Key = Key.drop_front(RefSize);
35 return Ref;
36}
37
38namespace {
39/// Walks a type key as if every reference were replaced by its key.
40class ExpandedKeyCursor {
41public:
42 ExpandedKeyCursor(StringRef Key) { Pending.push_back(Key); }
43
44 bool atEnd() {
45 if (const auto *Text = std::get_if<StringRef>(&Head);
46 !Text || !Text->empty())
47 return false;
48 while (!Pending.empty() && Pending.back().empty())
49 Pending.pop_back();
50 if (Pending.empty())
51 return true;
52 Head = TypeKey::takePart(Pending.back());
53 return false;
54 }
55
56 /// \pre !atEnd()
57 const TypeKey::Part &peek() const { return Head; }
58
59 /// \pre peek() is text of at least \p N bytes.
60 void consumeText(size_t N) {
61 StringRef &Text = std::get<StringRef>(Head);
62 Text = Text.drop_front(N);
63 }
64
65 /// \pre peek() is a reference.
66 void skipRef() { Head = {}; }
67
68 /// Replace the reference at the cursor by the key it refers to.
69 /// \pre peek() is a reference.
70 void enterRef() {
71 Pending.push_back(std::get<const TypeEntry *>(Head)->getKey());
72 Head = {};
73 }
74
75private:
76 /// The undecoded rest of each key being expanded, innermost last.
78 /// Decoded once, so consuming it piecemeal does not rescan it. Empty text
79 /// until the next part is decoded.
80 TypeKey::Part Head;
81};
82} // namespace
83
84/// Order keys by their text runs and references, recursively. Unlike
85/// expansion this is a total order on distinct keys.
87 while (!LHS.empty() && !RHS.empty()) {
90 if (L.index() != R.index())
91 return std::holds_alternative<const TypeEntry *>(L) ? -1 : 1;
92 if (L == R)
93 continue;
94 if (const auto *LText = std::get_if<StringRef>(&L))
95 return LText->compare(std::get<StringRef>(R));
96 if (int Cmp =
97 compareTypeKeyStructure(std::get<const TypeEntry *>(L)->getKey(),
98 std::get<const TypeEntry *>(R)->getKey()))
99 return Cmp;
100 }
101 return LHS.empty() == RHS.empty() ? 0 : (LHS.empty() ? -1 : 1);
102}
103
105 ExpandedKeyCursor L(LHS), R(RHS);
106 while (true) {
107 bool LEnd = L.atEnd();
108 bool REnd = R.atEnd();
109 // Distinct keys expand equally if a name contains key syntax. Break the
110 // tie without depending on pointer values.
111 if (LEnd && REnd)
112 return LHS == RHS ? 0 : compareTypeKeyStructure(LHS, RHS);
113 if (LEnd || REnd)
114 return LEnd ? -1 : 1;
115
116 const TypeKey::Part &LPart = L.peek();
117 const TypeKey::Part &RPart = R.peek();
118 bool LRef = std::holds_alternative<const TypeEntry *>(LPart);
119 bool RRef = std::holds_alternative<const TypeEntry *>(RPart);
120 // Equal references refer to equal keys, so they need no expanding.
121 if (LRef && LPart == RPart) {
122 L.skipRef();
123 R.skipRef();
124 continue;
125 }
126 if (LRef || RRef) {
127 if (LRef)
128 L.enterRef();
129 if (RRef)
130 R.enterRef();
131 continue;
132 }
133
134 StringRef LText = std::get<StringRef>(LPart);
135 StringRef RText = std::get<StringRef>(RPart);
136 size_t N = std::min(LText.size(), RText.size());
137 if (int Cmp = LText.take_front(N).compare(RText.take_front(N)))
138 return Cmp;
139 L.consumeText(N);
140 R.consumeText(N);
141 }
142}
143
145 std::string Result;
146 ExpandedKeyCursor Cursor(Key);
147 while (!Cursor.atEnd()) {
148 const auto *Text = std::get_if<StringRef>(&Cursor.peek());
149 if (!Text) {
150 Cursor.enterRef();
151 continue;
152 }
153 Result += *Text;
154 Cursor.consumeText(Text->size());
155 }
156 return Result;
157}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the SmallVector class.
static int compareTypeKeyStructure(StringRef LHS, StringRef RHS)
Order keys by their text runs and references, recursively.
Definition TypePool.cpp:86
static bool peek(struct InternalInstruction *insn, uint8_t &byte)
Value * RHS
Value * LHS
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition StringRef.h:606
int compare(StringRef RHS) const
Compare two strings; the result is negative, zero, or positive if this string is lexicographically le...
Definition StringRef.h:177
void appendRef(const TypeEntry *Entry)
Definition TypePool.cpp:17
static Part takePart(StringRef &Key)
Remove the first part of the non-empty key Key and return it.
Definition TypePool.cpp:24
static std::string expand(StringRef Key)
Definition TypePool.cpp:144
std::variant< StringRef, const TypeEntry * > Part
A maximal run of text, or a reference.
Definition TypePool.h:39
static int compare(StringRef LHS, StringRef RHS)
Compare LHS and RHS as if every reference were replaced by the key it refers to, so the result does n...
Definition TypePool.cpp:104
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:31
This is an optimization pass for GlobalISel generic memory operations.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
#define N