17using llvm::itanium_demangle::ForwardTemplateReference;
18using llvm::itanium_demangle::Node;
19using llvm::itanium_demangle::NodeKind;
22struct FoldingSetNodeIDBuilder {
24 void operator()(
const Node *
P) {
ID.AddPointer(
P); }
25 void operator()(std::string_view Str) {
32 std::enable_if_t<std::is_integral_v<T> || std::is_enum_v<T>> operator()(
T V) {
33 ID.AddInteger((
unsigned long long)V);
35 void operator()(itanium_demangle::NodeArray
A) {
36 ID.AddInteger(
A.size());
42template<
typename ...T>
44 FoldingSetNodeIDBuilder Builder = {
ID};
46 int VisitInOrder[] = {
54template<
typename NodeT>
struct ProfileSpecificNode {
56 template<
typename ...T>
void operator()(
T ...V) {
63 template<
typename NodeT>
void operator()(
const NodeT *
N) {
64 N->match(ProfileSpecificNode<NodeT>{
ID});
73 N->visit(ProfileNode{
ID});
76class FoldingNodeAllocator {
80 itanium_demangle::Node *
getNode() {
81 return reinterpret_cast<itanium_demangle::Node *
>(
this + 1);
92 template <
typename T,
typename...
Args>
93 std::pair<Node *, bool> getOrCreateNode(
bool CreateNewNodes, Args &&... As) {
97 if (std::is_same<T, ForwardTemplateReference>::value) {
100 return {
new (RawAlloc.
Allocate(
sizeof(
T),
alignof(
T)))
101 T(std::forward<Args>(As)...),
110 return {
static_cast<T*
>(Existing->getNode()),
false};
113 return {
nullptr,
true};
115 static_assert(
alignof(
T) <=
alignof(NodeHeader),
116 "underaligned node header for specific node kind");
118 RawAlloc.
Allocate(
sizeof(NodeHeader) +
sizeof(
T),
alignof(NodeHeader));
119 NodeHeader *
New =
new (Storage) NodeHeader;
120 T *
Result =
new (
New->getNode())
T(std::forward<Args>(As)...);
125 template<
typename T,
typename...
Args>
126 Node *makeNode(Args &&...As) {
127 return getOrCreateNode<T>(
true, std::forward<Args>(As)...).first;
130 void *allocateNodeArray(
size_t sz) {
135class CanonicalizerAllocator :
public FoldingNodeAllocator {
136 Node *MostRecentlyCreated =
nullptr;
137 Node *TrackedNode =
nullptr;
138 bool TrackedNodeIsUsed =
false;
139 bool CreateNewNodes =
true;
142 template<
typename T,
typename ...Args>
Node *makeNodeSimple(Args &&...As) {
143 std::pair<Node *, bool>
Result =
144 getOrCreateNode<T>(CreateNewNodes, std::forward<Args>(As)...);
147 MostRecentlyCreated =
Result.first;
148 }
else if (
Result.first) {
153 "should never need multiple remap steps");
155 if (
Result.first == TrackedNode)
156 TrackedNodeIsUsed =
true;
162 template<
typename T>
struct MakeNodeImpl {
163 CanonicalizerAllocator &Self;
164 template<
typename ...Args>
Node *
make(Args &&...As) {
165 return Self.makeNodeSimple<
T>(std::forward<Args>(As)...);
170 template<
typename T,
typename ...Args>
Node *makeNode(Args &&...As) {
171 return MakeNodeImpl<T>{*
this}.make(std::forward<Args>(As)...);
174 void reset() { MostRecentlyCreated =
nullptr; }
176 void setCreateNewNodes(
bool CNN) { CreateNewNodes = CNN; }
181 Remappings.
insert(std::make_pair(
A,
B));
184 bool isMostRecentlyCreated(
Node *
N)
const {
return MostRecentlyCreated ==
N; }
186 void trackUsesOf(
Node *
N) {
188 TrackedNodeIsUsed =
false;
190 bool trackedNodeIsUsed()
const {
return TrackedNodeIsUsed; }
195using CanonicalizingDemangler =
196 itanium_demangle::ManglingParser<CanonicalizerAllocator>;
209 auto &
Alloc =
P->Demangler.ASTAllocator;
210 Alloc.setCreateNewNodes(
true);
213 P->Demangler.reset(Str.begin(), Str.end());
222 if (Str.size() == 2 &&
P->Demangler.consumeIf(
"St"))
223 N =
P->Demangler.make<itanium_demangle::NameType>(
"std");
228 else if (Str.starts_with(
"S"))
230 N =
P->Demangler.parseType();
232 N =
P->Demangler.parseName();
237 N =
P->Demangler.parseType();
242 N =
P->Demangler.parseEncoding();
247 if (
P->Demangler.numLeft() != 0)
252 return std::make_pair(
N,
Alloc.isMostRecentlyCreated(
N));
255 Node *FirstNode, *SecondNode;
256 bool FirstIsNew, SecondIsNew;
258 std::tie(FirstNode, FirstIsNew) = Parse(
First);
262 Alloc.trackUsesOf(FirstNode);
263 std::tie(SecondNode, SecondIsNew) = Parse(Second);
268 if (FirstNode == SecondNode)
271 if (FirstIsNew && !
Alloc.trackedNodeIsUsed())
272 Alloc.addRemapping(FirstNode, SecondNode);
273 else if (SecondIsNew)
274 Alloc.addRemapping(SecondNode, FirstNode);
283 bool CreateNewNodes) {
284 Demangler.ASTAllocator.setCreateNewNodes(CreateNewNodes);
296 N =
Demangler.make<itanium_demangle::NameType>(
297 std::string_view(Mangling.
data(), Mangling.
size()));
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file defines the DenseMap class.
This file defines a hash set that can be used to remove duplication of nodes in a graph.
itanium_demangle::ManglingParser< DefaultAllocator > Demangler
static ItaniumManglingCanonicalizer::Key parseMaybeMangledName(CanonicalizingDemangler &Demangler, StringRef Mangling, bool CreateNewNodes)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Allocate memory in an ever growing pool, as if by bump-pointer.
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Node - This class is used to maintain the singly linked bucket list in a folding set.
void InsertNode(T *N, void *InsertPos)
InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
FindNodeOrInsertPos - Look up the node specified by ID.
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
FoldingSet - This template class is used to instantiate a specialized implementation of the folding s...
@ Encoding
The mangling fragment is an <encoding>.
@ Name
The mangling fragment is a <name> (or a predefined <substitution>).
@ Type
The mangling fragment is a <type>.
Key lookup(StringRef Mangling)
Find a canonical key for the specified mangling, if one has already been formed.
Key canonicalize(StringRef Mangling)
Form a canonical key for the specified mangling.
ItaniumManglingCanonicalizer()
@ InvalidFirstMangling
The first equivalent mangling is invalid.
@ InvalidSecondMangling
The second equivalent mangling is invalid.
@ ManglingAlreadyUsed
Both the equivalent manglings have already been used as components of some other mangling we've looke...
EquivalenceError addEquivalence(FragmentKind Kind, StringRef First, StringRef Second)
Add an equivalence between First and Second.
~ItaniumManglingCanonicalizer()
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
A forward-reference to a template argument that was not known at the point where the template paramet...
CanonicalizingDemangler Demangler
Determine the kind of a node from its type.