diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2025-03-05 13:38:11 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2025-03-05 13:49:53 +0300 |
commit | 9eed360f02de773a5ed2de5d2a3e81fc7f06acfa (patch) | |
tree | 744a4054e64eb443073c7c6ad36b29cedcf9c2e6 /contrib/libs/llvm14/lib/Support/ItaniumManglingCanonicalizer.cpp | |
parent | c141a5c40bda2eed1a68b0626ffdae5fd19359a6 (diff) | |
download | ydb-9eed360f02de773a5ed2de5d2a3e81fc7f06acfa.tar.gz |
Intermediate changes
commit_hash:2ec2671384dd8e604d41bc5c52c2f7858e4afea6
Diffstat (limited to 'contrib/libs/llvm14/lib/Support/ItaniumManglingCanonicalizer.cpp')
-rw-r--r-- | contrib/libs/llvm14/lib/Support/ItaniumManglingCanonicalizer.cpp | 322 |
1 files changed, 0 insertions, 322 deletions
diff --git a/contrib/libs/llvm14/lib/Support/ItaniumManglingCanonicalizer.cpp b/contrib/libs/llvm14/lib/Support/ItaniumManglingCanonicalizer.cpp deleted file mode 100644 index e6cba26cfcf..00000000000 --- a/contrib/libs/llvm14/lib/Support/ItaniumManglingCanonicalizer.cpp +++ /dev/null @@ -1,322 +0,0 @@ -//===----------------- ItaniumManglingCanonicalizer.cpp -------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/ItaniumManglingCanonicalizer.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Demangle/ItaniumDemangle.h" -#include "llvm/Support/Allocator.h" - -using namespace llvm; -using llvm::itanium_demangle::ForwardTemplateReference; -using llvm::itanium_demangle::Node; -using llvm::itanium_demangle::NodeKind; -using llvm::itanium_demangle::StringView; - -namespace { -struct FoldingSetNodeIDBuilder { - llvm::FoldingSetNodeID &ID; - void operator()(const Node *P) { ID.AddPointer(P); } - void operator()(StringView Str) { - ID.AddString(llvm::StringRef(Str.begin(), Str.size())); - } - template <typename T> - std::enable_if_t<std::is_integral<T>::value || std::is_enum<T>::value> - operator()(T V) { - ID.AddInteger((unsigned long long)V); - } - void operator()(itanium_demangle::NodeArray A) { - ID.AddInteger(A.size()); - for (const Node *N : A) - (*this)(N); - } -}; - -template<typename ...T> -void profileCtor(llvm::FoldingSetNodeID &ID, Node::Kind K, T ...V) { - FoldingSetNodeIDBuilder Builder = {ID}; - Builder(K); - int VisitInOrder[] = { - (Builder(V), 0) ..., - 0 // Avoid empty array if there are no arguments. - }; - (void)VisitInOrder; -} - -// FIXME: Convert this to a generic lambda when possible. -template<typename NodeT> struct ProfileSpecificNode { - FoldingSetNodeID &ID; - template<typename ...T> void operator()(T ...V) { - profileCtor(ID, NodeKind<NodeT>::Kind, V...); - } -}; - -struct ProfileNode { - FoldingSetNodeID &ID; - template<typename NodeT> void operator()(const NodeT *N) { - N->match(ProfileSpecificNode<NodeT>{ID}); - } -}; - -template<> void ProfileNode::operator()(const ForwardTemplateReference *N) { - llvm_unreachable("should never canonicalize a ForwardTemplateReference"); -} - -void profileNode(llvm::FoldingSetNodeID &ID, const Node *N) { - N->visit(ProfileNode{ID}); -} - -class FoldingNodeAllocator { - class alignas(alignof(Node *)) NodeHeader : public llvm::FoldingSetNode { - public: - // 'Node' in this context names the injected-class-name of the base class. - itanium_demangle::Node *getNode() { - return reinterpret_cast<itanium_demangle::Node *>(this + 1); - } - void Profile(llvm::FoldingSetNodeID &ID) { profileNode(ID, getNode()); } - }; - - BumpPtrAllocator RawAlloc; - llvm::FoldingSet<NodeHeader> Nodes; - -public: - void reset() {} - - template <typename T, typename... Args> - std::pair<Node *, bool> getOrCreateNode(bool CreateNewNodes, Args &&... As) { - // FIXME: Don't canonicalize forward template references for now, because - // they contain state (the resolved template node) that's not known at their - // point of creation. - if (std::is_same<T, ForwardTemplateReference>::value) { - // Note that we don't use if-constexpr here and so we must still write - // this code in a generic form. - return {new (RawAlloc.Allocate(sizeof(T), alignof(T))) - T(std::forward<Args>(As)...), - true}; - } - - llvm::FoldingSetNodeID ID; - profileCtor(ID, NodeKind<T>::Kind, As...); - - void *InsertPos; - if (NodeHeader *Existing = Nodes.FindNodeOrInsertPos(ID, InsertPos)) - return {static_cast<T*>(Existing->getNode()), false}; - - if (!CreateNewNodes) - return {nullptr, true}; - - static_assert(alignof(T) <= alignof(NodeHeader), - "underaligned node header for specific node kind"); - void *Storage = - RawAlloc.Allocate(sizeof(NodeHeader) + sizeof(T), alignof(NodeHeader)); - NodeHeader *New = new (Storage) NodeHeader; - T *Result = new (New->getNode()) T(std::forward<Args>(As)...); - Nodes.InsertNode(New, InsertPos); - return {Result, true}; - } - - template<typename T, typename... Args> - Node *makeNode(Args &&...As) { - return getOrCreateNode<T>(true, std::forward<Args>(As)...).first; - } - - void *allocateNodeArray(size_t sz) { - return RawAlloc.Allocate(sizeof(Node *) * sz, alignof(Node *)); - } -}; - -class CanonicalizerAllocator : public FoldingNodeAllocator { - Node *MostRecentlyCreated = nullptr; - Node *TrackedNode = nullptr; - bool TrackedNodeIsUsed = false; - bool CreateNewNodes = true; - llvm::SmallDenseMap<Node*, Node*, 32> Remappings; - - template<typename T, typename ...Args> Node *makeNodeSimple(Args &&...As) { - std::pair<Node *, bool> Result = - getOrCreateNode<T>(CreateNewNodes, std::forward<Args>(As)...); - if (Result.second) { - // Node is new. Make a note of that. - MostRecentlyCreated = Result.first; - } else if (Result.first) { - // Node is pre-existing; check if it's in our remapping table. - if (auto *N = Remappings.lookup(Result.first)) { - Result.first = N; - assert(Remappings.find(Result.first) == Remappings.end() && - "should never need multiple remap steps"); - } - if (Result.first == TrackedNode) - TrackedNodeIsUsed = true; - } - return Result.first; - } - - /// Helper to allow makeNode to be partially-specialized on T. - template<typename T> struct MakeNodeImpl { - CanonicalizerAllocator &Self; - template<typename ...Args> Node *make(Args &&...As) { - return Self.makeNodeSimple<T>(std::forward<Args>(As)...); - } - }; - -public: - template<typename T, typename ...Args> Node *makeNode(Args &&...As) { - return MakeNodeImpl<T>{*this}.make(std::forward<Args>(As)...); - } - - void reset() { MostRecentlyCreated = nullptr; } - - void setCreateNewNodes(bool CNN) { CreateNewNodes = CNN; } - - void addRemapping(Node *A, Node *B) { - // Note, we don't need to check whether B is also remapped, because if it - // was we would have already remapped it when building it. - Remappings.insert(std::make_pair(A, B)); - } - - bool isMostRecentlyCreated(Node *N) const { return MostRecentlyCreated == N; } - - void trackUsesOf(Node *N) { - TrackedNode = N; - TrackedNodeIsUsed = false; - } - bool trackedNodeIsUsed() const { return TrackedNodeIsUsed; } -}; - -/// Convert St3foo to NSt3fooE so that equivalences naming one also affect the -/// other. -template<> -struct CanonicalizerAllocator::MakeNodeImpl< - itanium_demangle::StdQualifiedName> { - CanonicalizerAllocator &Self; - Node *make(Node *Child) { - Node *StdNamespace = Self.makeNode<itanium_demangle::NameType>("std"); - if (!StdNamespace) - return nullptr; - return Self.makeNode<itanium_demangle::NestedName>(StdNamespace, Child); - } -}; - -// FIXME: Also expand built-in substitutions? - -using CanonicalizingDemangler = - itanium_demangle::ManglingParser<CanonicalizerAllocator>; -} // namespace - -struct ItaniumManglingCanonicalizer::Impl { - CanonicalizingDemangler Demangler = {nullptr, nullptr}; -}; - -ItaniumManglingCanonicalizer::ItaniumManglingCanonicalizer() : P(new Impl) {} -ItaniumManglingCanonicalizer::~ItaniumManglingCanonicalizer() { delete P; } - -ItaniumManglingCanonicalizer::EquivalenceError -ItaniumManglingCanonicalizer::addEquivalence(FragmentKind Kind, StringRef First, - StringRef Second) { - auto &Alloc = P->Demangler.ASTAllocator; - Alloc.setCreateNewNodes(true); - - auto Parse = [&](StringRef Str) { - P->Demangler.reset(Str.begin(), Str.end()); - Node *N = nullptr; - switch (Kind) { - // A <name>, with minor extensions to allow arbitrary namespace and - // template names that can't easily be written as <name>s. - case FragmentKind::Name: - // Very special case: allow "St" as a shorthand for "3std". It's not - // valid as a <name> mangling, but is nonetheless the most natural - // way to name the 'std' namespace. - if (Str.size() == 2 && P->Demangler.consumeIf("St")) - N = P->Demangler.make<itanium_demangle::NameType>("std"); - // We permit substitutions to name templates without their template - // arguments. This mostly just falls out, as almost all template names - // are valid as <name>s, but we also want to parse <substitution>s as - // <name>s, even though they're not. - else if (Str.startswith("S")) - // Parse the substitution and optional following template arguments. - N = P->Demangler.parseType(); - else - N = P->Demangler.parseName(); - break; - - // A <type>. - case FragmentKind::Type: - N = P->Demangler.parseType(); - break; - - // An <encoding>. - case FragmentKind::Encoding: - N = P->Demangler.parseEncoding(); - break; - } - - // If we have trailing junk, the mangling is invalid. - if (P->Demangler.numLeft() != 0) - N = nullptr; - - // If any node was created after N, then we cannot safely remap it because - // it might already be in use by another node. - return std::make_pair(N, Alloc.isMostRecentlyCreated(N)); - }; - - Node *FirstNode, *SecondNode; - bool FirstIsNew, SecondIsNew; - - std::tie(FirstNode, FirstIsNew) = Parse(First); - if (!FirstNode) - return EquivalenceError::InvalidFirstMangling; - - Alloc.trackUsesOf(FirstNode); - std::tie(SecondNode, SecondIsNew) = Parse(Second); - if (!SecondNode) - return EquivalenceError::InvalidSecondMangling; - - // If they're already equivalent, there's nothing to do. - if (FirstNode == SecondNode) - return EquivalenceError::Success; - - if (FirstIsNew && !Alloc.trackedNodeIsUsed()) - Alloc.addRemapping(FirstNode, SecondNode); - else if (SecondIsNew) - Alloc.addRemapping(SecondNode, FirstNode); - else - return EquivalenceError::ManglingAlreadyUsed; - - return EquivalenceError::Success; -} - -static ItaniumManglingCanonicalizer::Key -parseMaybeMangledName(CanonicalizingDemangler &Demangler, StringRef Mangling, - bool CreateNewNodes) { - Demangler.ASTAllocator.setCreateNewNodes(CreateNewNodes); - Demangler.reset(Mangling.begin(), Mangling.end()); - // Attempt demangling only for names that look like C++ mangled names. - // Otherwise, treat them as extern "C" names. We permit the latter to - // be remapped by (eg) - // encoding 6memcpy 7memmove - // consistent with how they are encoded as local-names inside a C++ mangling. - Node *N; - if (Mangling.startswith("_Z") || Mangling.startswith("__Z") || - Mangling.startswith("___Z") || Mangling.startswith("____Z")) - N = Demangler.parse(); - else - N = Demangler.make<itanium_demangle::NameType>( - StringView(Mangling.data(), Mangling.size())); - return reinterpret_cast<ItaniumManglingCanonicalizer::Key>(N); -} - -ItaniumManglingCanonicalizer::Key -ItaniumManglingCanonicalizer::canonicalize(StringRef Mangling) { - return parseMaybeMangledName(P->Demangler, Mangling, true); -} - -ItaniumManglingCanonicalizer::Key -ItaniumManglingCanonicalizer::lookup(StringRef Mangling) { - return parseMaybeMangledName(P->Demangler, Mangling, false); -} |