17using llvm::itanium_demangle::ForwardTemplateReference;
18using llvm::itanium_demangle::Node;
19using llvm::itanium_demangle::NodeKind;
22struct FoldingSetNodeIDBuilder {
23 llvm::FoldingSetNodeID &ID;
24 void operator()(
const Node *
P) { ID.AddPointer(
P); }
25 void operator()(std::string_view Str) {
29 ID.AddString(llvm::StringRef(&*Str.begin(), Str.size()));
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());
37 for (
const Node *
N :
A)
42template<
typename ...
T>
44 FoldingSetNodeIDBuilder Builder = {
ID};
46 int VisitInOrder[] = {
54template<
typename NodeT>
struct ProfileSpecificNode {
56 template<
typename ...T>
void operator()(
T ...V) {
57 profileCtor(ID, NodeKind<NodeT>::Kind,
V...);
63 template<
typename NodeT>
void operator()(
const NodeT *
N) {
64 N->match(ProfileSpecificNode<NodeT>{ID});
72void profileNode(llvm::FoldingSetNodeID &
ID,
const Node *
N) {
73 N->visit(ProfileNode{
ID});
76class FoldingNodeAllocator {
80 itanium_demangle::Node *
getNode() {
81 return reinterpret_cast<itanium_demangle::Node *
>(
this + 1);
87 llvm::FoldingSet<NodeHeader> Nodes;
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)...),
105 llvm::FoldingSetNodeID
ID;
106 profileCtor(
ID, NodeKind<T>::Kind, 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 void *allocateNodeArray(
size_t sz) {
126 return RawAlloc.Allocate(
sizeof(Node *) * sz,
alignof(Node *));
130class CanonicalizerAllocator :
public FoldingNodeAllocator {
131 Node *MostRecentlyCreated =
nullptr;
132 Node *TrackedNode =
nullptr;
133 bool TrackedNodeIsUsed =
false;
134 bool CreateNewNodes =
true;
135 llvm::SmallDenseMap<Node*, Node*, 32> Remappings;
137 template<
typename T,
typename ...Args>
Node *makeNodeSimple(Args &&...As) {
138 std::pair<Node *, bool>
Result =
139 getOrCreateNode<T>(CreateNewNodes, std::forward<Args>(As)...);
142 MostRecentlyCreated =
Result.first;
143 }
else if (
Result.first) {
148 "should never need multiple remap steps");
150 if (
Result.first == TrackedNode)
151 TrackedNodeIsUsed =
true;
157 template<
typename T>
struct MakeNodeImpl {
158 CanonicalizerAllocator &Self;
159 template<
typename ...Args>
Node *make(Args &&...As) {
160 return Self.makeNodeSimple<
T>(std::forward<Args>(As)...);
165 template<
typename T,
typename ...Args>
Node *makeNode(Args &&...As) {
166 return MakeNodeImpl<T>{*
this}.make(std::forward<Args>(As)...);
169 void reset() { MostRecentlyCreated =
nullptr; }
171 void setCreateNewNodes(
bool CNN) { CreateNewNodes = CNN; }
173 void addRemapping(Node *
A, Node *
B) {
176 Remappings.
insert(std::make_pair(
A,
B));
179 bool isMostRecentlyCreated(Node *
N)
const {
return MostRecentlyCreated ==
N; }
181 void trackUsesOf(Node *
N) {
183 TrackedNodeIsUsed =
false;
185 bool trackedNodeIsUsed()
const {
return TrackedNodeIsUsed; }
190using CanonicalizingDemangler =
191 itanium_demangle::ManglingParser<CanonicalizerAllocator>;
204 auto &
Alloc = P->Demangler.ASTAllocator;
205 Alloc.setCreateNewNodes(
true);
208 P->Demangler.reset(Str.begin(), Str.end());
217 if (Str.size() == 2 && P->Demangler.consumeIf(
"St"))
218 N = P->Demangler.make<itanium_demangle::NameType>(
"std");
223 else if (Str.starts_with(
"S"))
225 N = P->Demangler.parseType();
227 N = P->Demangler.parseName();
232 N = P->Demangler.parseType();
237 N = P->Demangler.parseEncoding();
242 if (P->Demangler.numLeft() != 0)
247 return std::make_pair(
N,
Alloc.isMostRecentlyCreated(
N));
250 Node *FirstNode, *SecondNode;
251 bool FirstIsNew, SecondIsNew;
253 std::tie(FirstNode, FirstIsNew) = Parse(
First);
257 Alloc.trackUsesOf(FirstNode);
258 std::tie(SecondNode, SecondIsNew) = Parse(Second);
263 if (FirstNode == SecondNode)
266 if (FirstIsNew && !
Alloc.trackedNodeIsUsed())
267 Alloc.addRemapping(FirstNode, SecondNode);
268 else if (SecondIsNew)
269 Alloc.addRemapping(SecondNode, FirstNode);
278 bool CreateNewNodes) {
279 Demangler.ASTAllocator.setCreateNewNodes(CreateNewNodes);
280 Demangler.reset(Mangling.
begin(), Mangling.
end());
289 N = Demangler.parse();
291 N = Demangler.make<itanium_demangle::NameType>(
292 std::string_view(Mangling.
data(), Mangling.
size()));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
This file defines a hash set that can be used to remove duplication of nodes in a graph.
static ItaniumManglingCanonicalizer::Key parseMaybeMangledName(CanonicalizingDemangler &Demangler, StringRef Mangling, bool CreateNewNodes)
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
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)
void InsertNode(T *N, void *InsertPos)
Insert the specified node into the folding set, knowing that it is not already in the folding set.
T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)
Look up the node specified by ID.
This class is used to gather all the unique data bits of a node.
@ 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>.
LLVM_ABI Key lookup(StringRef Mangling)
Find a canonical key for the specified mangling, if one has already been formed.
LLVM_ABI Key canonicalize(StringRef Mangling)
Form a canonical key for the specified mangling.
LLVM_ABI 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...
LLVM_ABI EquivalenceError addEquivalence(FragmentKind Kind, StringRef First, StringRef Second)
Add an equivalence between First and Second.
LLVM_ABI ~ItaniumManglingCanonicalizer()
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
Get the string size.
constexpr const char * data() const
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.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
FoldingSetBase::Node FoldingSetNode
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
A forward-reference to a template argument that was not known at the point where the template paramet...
CanonicalizingDemangler Demangler