Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:48

0001 //===------------------------- MicrosoftDemangle.h --------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
0010 #define LLVM_DEMANGLE_MICROSOFTDEMANGLE_H
0011 
0012 #include "llvm/Demangle/Demangle.h"
0013 #include "llvm/Demangle/MicrosoftDemangleNodes.h"
0014 
0015 #include <cassert>
0016 #include <string_view>
0017 #include <utility>
0018 
0019 namespace llvm {
0020 namespace ms_demangle {
0021 // This memory allocator is extremely fast, but it doesn't call dtors
0022 // for allocated objects. That means you can't use STL containers
0023 // (such as std::vector) with this allocator. But it pays off --
0024 // the demangler is 3x faster with this allocator compared to one with
0025 // STL containers.
0026 constexpr size_t AllocUnit = 4096;
0027 
0028 class ArenaAllocator {
0029   struct AllocatorNode {
0030     uint8_t *Buf = nullptr;
0031     size_t Used = 0;
0032     size_t Capacity = 0;
0033     AllocatorNode *Next = nullptr;
0034   };
0035 
0036   void addNode(size_t Capacity) {
0037     AllocatorNode *NewHead = new AllocatorNode;
0038     NewHead->Buf = new uint8_t[Capacity];
0039     NewHead->Next = Head;
0040     NewHead->Capacity = Capacity;
0041     Head = NewHead;
0042     NewHead->Used = 0;
0043   }
0044 
0045 public:
0046   ArenaAllocator() { addNode(AllocUnit); }
0047 
0048   ~ArenaAllocator() {
0049     while (Head) {
0050       assert(Head->Buf);
0051       delete[] Head->Buf;
0052       AllocatorNode *Next = Head->Next;
0053       delete Head;
0054       Head = Next;
0055     }
0056   }
0057 
0058   // Delete the copy constructor and the copy assignment operator.
0059   ArenaAllocator(const ArenaAllocator &) = delete;
0060   ArenaAllocator &operator=(const ArenaAllocator &) = delete;
0061 
0062   char *allocUnalignedBuffer(size_t Size) {
0063     assert(Head && Head->Buf);
0064 
0065     uint8_t *P = Head->Buf + Head->Used;
0066 
0067     Head->Used += Size;
0068     if (Head->Used <= Head->Capacity)
0069       return reinterpret_cast<char *>(P);
0070 
0071     addNode(std::max(AllocUnit, Size));
0072     Head->Used = Size;
0073     return reinterpret_cast<char *>(Head->Buf);
0074   }
0075 
0076   template <typename T, typename... Args> T *allocArray(size_t Count) {
0077     size_t Size = Count * sizeof(T);
0078     assert(Head && Head->Buf);
0079 
0080     size_t P = (size_t)Head->Buf + Head->Used;
0081     uintptr_t AlignedP =
0082         (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
0083     uint8_t *PP = (uint8_t *)AlignedP;
0084     size_t Adjustment = AlignedP - P;
0085 
0086     Head->Used += Size + Adjustment;
0087     if (Head->Used <= Head->Capacity)
0088       return new (PP) T[Count]();
0089 
0090     addNode(std::max(AllocUnit, Size));
0091     Head->Used = Size;
0092     return new (Head->Buf) T[Count]();
0093   }
0094 
0095   template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) {
0096     constexpr size_t Size = sizeof(T);
0097     assert(Head && Head->Buf);
0098 
0099     size_t P = (size_t)Head->Buf + Head->Used;
0100     uintptr_t AlignedP =
0101         (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));
0102     uint8_t *PP = (uint8_t *)AlignedP;
0103     size_t Adjustment = AlignedP - P;
0104 
0105     Head->Used += Size + Adjustment;
0106     if (Head->Used <= Head->Capacity)
0107       return new (PP) T(std::forward<Args>(ConstructorArgs)...);
0108 
0109     static_assert(Size < AllocUnit);
0110     addNode(AllocUnit);
0111     Head->Used = Size;
0112     return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);
0113   }
0114 
0115 private:
0116   AllocatorNode *Head = nullptr;
0117 };
0118 
0119 struct BackrefContext {
0120   static constexpr size_t Max = 10;
0121 
0122   TypeNode *FunctionParams[Max];
0123   size_t FunctionParamCount = 0;
0124 
0125   // The first 10 BackReferences in a mangled name can be back-referenced by
0126   // special name @[0-9]. This is a storage for the first 10 BackReferences.
0127   NamedIdentifierNode *Names[Max];
0128   size_t NamesCount = 0;
0129 };
0130 
0131 enum class QualifierMangleMode { Drop, Mangle, Result };
0132 
0133 enum NameBackrefBehavior : uint8_t {
0134   NBB_None = 0,          // don't save any names as backrefs.
0135   NBB_Template = 1 << 0, // save template instanations.
0136   NBB_Simple = 1 << 1,   // save simple names.
0137 };
0138 
0139 enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder };
0140 
0141 // Demangler class takes the main role in demangling symbols.
0142 // It has a set of functions to parse mangled symbols into Type instances.
0143 // It also has a set of functions to convert Type instances to strings.
0144 class Demangler {
0145   friend std::optional<size_t>
0146   llvm::getArm64ECInsertionPointInMangledName(std::string_view MangledName);
0147 
0148 public:
0149   Demangler() = default;
0150   virtual ~Demangler() = default;
0151 
0152   // You are supposed to call parse() first and then check if error is true.  If
0153   // it is false, call output() to write the formatted name to the given stream.
0154   SymbolNode *parse(std::string_view &MangledName);
0155 
0156   TagTypeNode *parseTagUniqueName(std::string_view &MangledName);
0157 
0158   // True if an error occurred.
0159   bool Error = false;
0160 
0161   void dumpBackReferences();
0162 
0163 private:
0164   SymbolNode *demangleEncodedSymbol(std::string_view &MangledName,
0165                                     QualifiedNameNode *QN);
0166   SymbolNode *demangleDeclarator(std::string_view &MangledName);
0167   SymbolNode *demangleMD5Name(std::string_view &MangledName);
0168   SymbolNode *demangleTypeinfoName(std::string_view &MangledName);
0169 
0170   VariableSymbolNode *demangleVariableEncoding(std::string_view &MangledName,
0171                                                StorageClass SC);
0172   FunctionSymbolNode *demangleFunctionEncoding(std::string_view &MangledName);
0173 
0174   Qualifiers demanglePointerExtQualifiers(std::string_view &MangledName);
0175 
0176   // Parser functions. This is a recursive-descent parser.
0177   TypeNode *demangleType(std::string_view &MangledName,
0178                          QualifierMangleMode QMM);
0179   PrimitiveTypeNode *demanglePrimitiveType(std::string_view &MangledName);
0180   CustomTypeNode *demangleCustomType(std::string_view &MangledName);
0181   TagTypeNode *demangleClassType(std::string_view &MangledName);
0182   PointerTypeNode *demanglePointerType(std::string_view &MangledName);
0183   PointerTypeNode *demangleMemberPointerType(std::string_view &MangledName);
0184   FunctionSignatureNode *demangleFunctionType(std::string_view &MangledName,
0185                                               bool HasThisQuals);
0186 
0187   ArrayTypeNode *demangleArrayType(std::string_view &MangledName);
0188 
0189   NodeArrayNode *demangleFunctionParameterList(std::string_view &MangledName,
0190                                                bool &IsVariadic);
0191   NodeArrayNode *demangleTemplateParameterList(std::string_view &MangledName);
0192 
0193   std::pair<uint64_t, bool> demangleNumber(std::string_view &MangledName);
0194   uint64_t demangleUnsigned(std::string_view &MangledName);
0195   int64_t demangleSigned(std::string_view &MangledName);
0196 
0197   void memorizeString(std::string_view s);
0198   void memorizeIdentifier(IdentifierNode *Identifier);
0199 
0200   /// Allocate a copy of \p Borrowed into memory that we own.
0201   std::string_view copyString(std::string_view Borrowed);
0202 
0203   QualifiedNameNode *
0204   demangleFullyQualifiedTypeName(std::string_view &MangledName);
0205   QualifiedNameNode *
0206   demangleFullyQualifiedSymbolName(std::string_view &MangledName);
0207 
0208   IdentifierNode *demangleUnqualifiedTypeName(std::string_view &MangledName,
0209                                               bool Memorize);
0210   IdentifierNode *demangleUnqualifiedSymbolName(std::string_view &MangledName,
0211                                                 NameBackrefBehavior NBB);
0212 
0213   QualifiedNameNode *demangleNameScopeChain(std::string_view &MangledName,
0214                                             IdentifierNode *UnqualifiedName);
0215   IdentifierNode *demangleNameScopePiece(std::string_view &MangledName);
0216 
0217   NamedIdentifierNode *demangleBackRefName(std::string_view &MangledName);
0218   IdentifierNode *
0219   demangleTemplateInstantiationName(std::string_view &MangledName,
0220                                     NameBackrefBehavior NBB);
0221   IntrinsicFunctionKind
0222   translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group);
0223   IdentifierNode *demangleFunctionIdentifierCode(std::string_view &MangledName);
0224   IdentifierNode *
0225   demangleFunctionIdentifierCode(std::string_view &MangledName,
0226                                  FunctionIdentifierCodeGroup Group);
0227   StructorIdentifierNode *
0228   demangleStructorIdentifier(std::string_view &MangledName, bool IsDestructor);
0229   ConversionOperatorIdentifierNode *
0230   demangleConversionOperatorIdentifier(std::string_view &MangledName);
0231   LiteralOperatorIdentifierNode *
0232   demangleLiteralOperatorIdentifier(std::string_view &MangledName);
0233 
0234   SymbolNode *demangleSpecialIntrinsic(std::string_view &MangledName);
0235   SpecialTableSymbolNode *
0236   demangleSpecialTableSymbolNode(std::string_view &MangledName,
0237                                  SpecialIntrinsicKind SIK);
0238   LocalStaticGuardVariableNode *
0239   demangleLocalStaticGuard(std::string_view &MangledName, bool IsThread);
0240   VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,
0241                                               std::string_view &MangledName,
0242                                               std::string_view VariableName);
0243   VariableSymbolNode *
0244   demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
0245                                       std::string_view &MangledName);
0246   FunctionSymbolNode *demangleInitFiniStub(std::string_view &MangledName,
0247                                            bool IsDestructor);
0248 
0249   NamedIdentifierNode *demangleSimpleName(std::string_view &MangledName,
0250                                           bool Memorize);
0251   NamedIdentifierNode *
0252   demangleAnonymousNamespaceName(std::string_view &MangledName);
0253   NamedIdentifierNode *
0254   demangleLocallyScopedNamePiece(std::string_view &MangledName);
0255   EncodedStringLiteralNode *
0256   demangleStringLiteral(std::string_view &MangledName);
0257   FunctionSymbolNode *demangleVcallThunkNode(std::string_view &MangledName);
0258 
0259   std::string_view demangleSimpleString(std::string_view &MangledName,
0260                                         bool Memorize);
0261 
0262   FuncClass demangleFunctionClass(std::string_view &MangledName);
0263   CallingConv demangleCallingConvention(std::string_view &MangledName);
0264   StorageClass demangleVariableStorageClass(std::string_view &MangledName);
0265   bool demangleThrowSpecification(std::string_view &MangledName);
0266   wchar_t demangleWcharLiteral(std::string_view &MangledName);
0267   uint8_t demangleCharLiteral(std::string_view &MangledName);
0268 
0269   std::pair<Qualifiers, bool> demangleQualifiers(std::string_view &MangledName);
0270 
0271   // Memory allocator.
0272   ArenaAllocator Arena;
0273 
0274   // A single type uses one global back-ref table for all function params.
0275   // This means back-refs can even go "into" other types.  Examples:
0276   //
0277   //  // Second int* is a back-ref to first.
0278   //  void foo(int *, int*);
0279   //
0280   //  // Second int* is not a back-ref to first (first is not a function param).
0281   //  int* foo(int*);
0282   //
0283   //  // Second int* is a back-ref to first (ALL function types share the same
0284   //  // back-ref map.
0285   //  using F = void(*)(int*);
0286   //  F G(int *);
0287   BackrefContext Backrefs;
0288 };
0289 
0290 } // namespace ms_demangle
0291 } // namespace llvm
0292 
0293 #endif // LLVM_DEMANGLE_MICROSOFTDEMANGLE_H