diff options
Diffstat (limited to 'lib/AST/MicrosoftMangle.cpp')
-rw-r--r-- | lib/AST/MicrosoftMangle.cpp | 174 |
1 files changed, 83 insertions, 91 deletions
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index e6a6d09..72f90f6 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -27,7 +27,6 @@ #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" #include "llvm/Support/MathExtras.h" using namespace clang; @@ -161,7 +160,7 @@ public: unsigned &discriminator = Uniquifier[ND]; if (!discriminator) discriminator = ++Discriminator[std::make_pair(DC, ND->getIdentifier())]; - disc = discriminator; + disc = discriminator + 1; return true; } @@ -191,8 +190,8 @@ class MicrosoftCXXNameMangler { const NamedDecl *Structor; unsigned StructorType; - typedef llvm::StringMap<unsigned> BackRefMap; - BackRefMap NameBackReferences; + typedef llvm::SmallVector<std::string, 10> BackRefVec; + BackRefVec NameBackReferences; typedef llvm::DenseMap<void *, unsigned> ArgBackRefMap; ArgBackRefMap TypeBackReferences; @@ -234,7 +233,7 @@ public: QualifierMangleMode QMM = QMM_Mangle); void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = nullptr, - bool ForceInstMethod = false); + bool ForceThisQuals = false); void mangleNestedName(const NamedDecl *ND); private: @@ -279,7 +278,8 @@ private: void mangleTemplateArgs(const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs); - void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA); + void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA, + const NamedDecl *Parm); }; } @@ -338,9 +338,7 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { bool MicrosoftMangleContextImpl::shouldMangleStringLiteral(const StringLiteral *SL) { - return SL->isAscii() || SL->isWide(); - // TODO: This needs to be updated when MSVC gains support for Unicode - // literals. + return true; } void MicrosoftCXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) { @@ -441,7 +439,7 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { mangleQualifiers(Ty.getQualifiers(), false); } else { mangleType(Ty, SR, QMM_Drop); - mangleQualifiers(Ty.getLocalQualifiers(), false); + mangleQualifiers(Ty.getQualifiers(), false); } } @@ -801,10 +799,7 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) { // <postfix> ::= <unqualified-name> [<postfix>] // ::= <substitution> [<postfix>] - if (isLambda(ND)) - return; - - const DeclContext *DC = ND->getDeclContext(); + const DeclContext *DC = getEffectiveDeclContext(ND); while (!DC->isTranslationUnit()) { if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) { @@ -856,6 +851,8 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) { // <operator-name> ::= ?_E # vector deleting destructor // FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need // it. + case Dtor_Comdat: + llvm_unreachable("not expecting a COMDAT"); } llvm_unreachable("Unsupported dtor type?"); } @@ -994,22 +991,14 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, void MicrosoftCXXNameMangler::mangleSourceName(StringRef Name) { // <source name> ::= <identifier> @ - BackRefMap::iterator Found; - if (NameBackReferences.size() < 10) { - size_t Size = NameBackReferences.size(); - bool Inserted; - std::tie(Found, Inserted) = - NameBackReferences.insert(std::make_pair(Name, Size)); - if (Inserted) - Found = NameBackReferences.end(); - } else { - Found = NameBackReferences.find(Name); - } - + BackRefVec::iterator Found = + std::find(NameBackReferences.begin(), NameBackReferences.end(), Name); if (Found == NameBackReferences.end()) { + if (NameBackReferences.size() < 10) + NameBackReferences.push_back(Name); Out << Name << '@'; } else { - Out << Found->second; + Out << (Found - NameBackReferences.begin()); } } @@ -1025,7 +1014,7 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( // Templates have their own context for back references. ArgBackRefMap OuterArgsContext; - BackRefMap OuterTemplateContext; + BackRefVec OuterTemplateContext; NameBackReferences.swap(OuterTemplateContext); TypeBackReferences.swap(OuterArgsContext); @@ -1051,8 +1040,10 @@ void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, // Make sure booleans are encoded as 0/1. if (IsBoolean && Value.getBoolValue()) mangleNumber(1); - else + else if (Value.isSigned()) mangleNumber(Value.getSExtValue()); + else + mangleNumber(Value.getZExtValue()); } void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { @@ -1104,12 +1095,18 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { void MicrosoftCXXNameMangler::mangleTemplateArgs( const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs) { // <template-args> ::= <template-arg>+ + const TemplateParameterList *TPL = TD->getTemplateParameters(); + assert(TPL->size() == TemplateArgs.size() && + "size mismatch between args and parms!"); + + unsigned Idx = 0; for (const TemplateArgument &TA : TemplateArgs.asArray()) - mangleTemplateArg(TD, TA); + mangleTemplateArg(TD, TA, TPL->getParam(Idx++)); } void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, - const TemplateArgument &TA) { + const TemplateArgument &TA, + const NamedDecl *Parm) { // <template-arg> ::= <type> // ::= <integer-literal> // ::= <member-data-pointer> @@ -1142,7 +1139,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, else mangle(FD, "$1?"); } else { - mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?"); + mangle(ND, TA.getParamTypeForDecl()->isReferenceType() ? "$E?" : "$1?"); } break; } @@ -1172,18 +1169,33 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD, case TemplateArgument::Pack: { ArrayRef<TemplateArgument> TemplateArgs = TA.getPackAsArray(); if (TemplateArgs.empty()) { - Out << "$S"; + if (isa<TemplateTypeParmDecl>(Parm) || + isa<TemplateTemplateParmDecl>(Parm)) + Out << "$$V"; + else if (isa<NonTypeTemplateParmDecl>(Parm)) + Out << "$S"; + else + llvm_unreachable("unexpected template parameter decl!"); } else { for (const TemplateArgument &PA : TemplateArgs) - mangleTemplateArg(TD, PA); + mangleTemplateArg(TD, PA, Parm); } break; } - case TemplateArgument::Template: - mangleType(cast<TagDecl>( - TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl())); + case TemplateArgument::Template: { + const NamedDecl *ND = + TA.getAsTemplate().getAsTemplateDecl()->getTemplatedDecl(); + if (const auto *TD = dyn_cast<TagDecl>(ND)) { + mangleType(TD); + } else if (isa<TypeAliasDecl>(ND)) { + Out << "$$Y"; + mangleName(ND); + } else { + llvm_unreachable("unexpected template template NamedDecl!"); + } break; } + } } void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, @@ -1473,6 +1485,8 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, case BuiltinType::Int128: Out << "_L"; break; case BuiltinType::UInt128: Out << "_M"; break; case BuiltinType::Bool: Out << "_N"; break; + case BuiltinType::Char16: Out << "_S"; break; + case BuiltinType::Char32: Out << "_U"; break; case BuiltinType::WChar_S: case BuiltinType::WChar_U: Out << "_W"; break; @@ -1498,8 +1512,6 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, case BuiltinType::NullPtr: Out << "$$T"; break; - case BuiltinType::Char16: - case BuiltinType::Char32: case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -1518,8 +1530,13 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, // Structors only appear in decls, so at this point we know it's not a // structor type. // FIXME: This may not be lambda-friendly. - Out << "$$A6"; - mangleFunctionType(T); + if (T->getTypeQuals() || T->getRefQualifier() != RQ_None) { + Out << "$$A8@@"; + mangleFunctionType(T, /*D=*/nullptr, /*ForceThisQuals=*/true); + } else { + Out << "$$A6"; + mangleFunctionType(T); + } } void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, SourceRange) { @@ -1528,7 +1545,7 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, const FunctionDecl *D, - bool ForceInstMethod) { + bool ForceThisQuals) { // <function-type> ::= <this-cvr-qualifiers> <calling-convention> // <return-type> <argument-list> <throw-spec> const FunctionProtoType *Proto = cast<FunctionProtoType>(T); @@ -1536,21 +1553,21 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, SourceRange Range; if (D) Range = D->getSourceRange(); - bool IsStructor = false, IsInstMethod = ForceInstMethod; + bool IsStructor = false, HasThisQuals = ForceThisQuals; if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) { if (MD->isInstance()) - IsInstMethod = true; + HasThisQuals = true; if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) IsStructor = true; } // If this is a C++ instance method, mangle the CVR qualifiers for the // this pointer. - if (IsInstMethod) { + if (HasThisQuals) { Qualifiers Quals = Qualifiers::fromCVRMask(Proto->getTypeQuals()); - manglePointerExtQualifiers(Quals, nullptr); + manglePointerExtQualifiers(Quals, /*PointeeType=*/nullptr); mangleRefQualifier(Proto->getRefQualifier()); - mangleQualifiers(Quals, false); + mangleQualifiers(Quals, /*IsMember=*/false); } mangleCallingConvention(T); @@ -1670,6 +1687,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { // ::= H # __export __stdcall // ::= I # __fastcall // ::= J # __export __fastcall + // ::= Q # __vectorcall // The 'export' calling conventions are from a bygone era // (*cough*Win16*cough*) when functions were declared for export with // that keyword. (It didn't actually export them, it just made them so @@ -1686,6 +1704,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) { case CC_X86ThisCall: Out << 'E'; break; case CC_X86StdCall: Out << 'G'; break; case CC_X86FastCall: Out << 'I'; break; + case CC_X86VectorCall: Out << 'Q'; break; } } void MicrosoftCXXNameMangler::mangleThrowSpecification( @@ -2331,7 +2350,7 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD, void MicrosoftMangleContextImpl::mangleStaticGuardVariable(const VarDecl *VD, raw_ostream &Out) { - // TODO: This is not correct, especially with respect to MSVC2013. MSVC2013 + // TODO: This is not correct, especially with respect to VS "14". VS "14" // utilizes thread local variables to implement thread safe, re-entrant // initialization for statics. They no longer differentiate between an // externally visible and non-externally visible static with respect to @@ -2420,14 +2439,10 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, Mangler.getStream() << "\01??_C@_"; // <char-type>: The "kind" of string literal is encoded into the mangled name. - // TODO: This needs to be updated when MSVC gains support for unicode - // literals. - if (SL->isAscii()) - Mangler.getStream() << '0'; - else if (SL->isWide()) + if (SL->isWide()) Mangler.getStream() << '1'; else - llvm_unreachable("unexpected string literal kind!"); + Mangler.getStream() << '0'; // <literal-length>: The next part of the mangled name consists of the length // of the string. @@ -2506,42 +2521,16 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, } else if (isLetter(Byte & 0x7f)) { Mangler.getStream() << '?' << static_cast<char>(Byte & 0x7f); } else { - switch (Byte) { - case ',': - Mangler.getStream() << "?0"; - break; - case '/': - Mangler.getStream() << "?1"; - break; - case '\\': - Mangler.getStream() << "?2"; - break; - case ':': - Mangler.getStream() << "?3"; - break; - case '.': - Mangler.getStream() << "?4"; - break; - case ' ': - Mangler.getStream() << "?5"; - break; - case '\n': - Mangler.getStream() << "?6"; - break; - case '\t': - Mangler.getStream() << "?7"; - break; - case '\'': - Mangler.getStream() << "?8"; - break; - case '-': - Mangler.getStream() << "?9"; - break; - default: - Mangler.getStream() << "?$"; - Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf)); - Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf)); - break; + const char SpecialChars[] = {',', '/', '\\', ':', '.', + ' ', '\n', '\t', '\'', '-'}; + const char *Pos = + std::find(std::begin(SpecialChars), std::end(SpecialChars), Byte); + if (Pos != std::end(SpecialChars)) { + Mangler.getStream() << '?' << (Pos - std::begin(SpecialChars)); + } else { + Mangler.getStream() << "?$"; + Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf)); + Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf)); } } }; @@ -2550,7 +2539,10 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, unsigned NumCharsToMangle = std::min(32U, SL->getLength()); for (unsigned I = 0, E = NumCharsToMangle * SL->getCharByteWidth(); I != E; ++I) - MangleByte(GetBigEndianByte(I)); + if (SL->isWide()) + MangleByte(GetBigEndianByte(I)); + else + MangleByte(GetLittleEndianByte(I)); // Encode the NUL terminator if there is room. if (NumCharsToMangle < 32) |