From 5f177620c3a5fe5626d55d0189a5fc7352e78ad6 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 30 Dec 2015 05:13:03 +0000 Subject: [PATCH] [MS ABI] Improve our mangling of pass_object_size We didn't add the artificial pass_object_size arguments to the backreference map which bloated the size of manglings which involved pass_object_size with duplicate types. This lets us go from: ?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@0W4__pass_object_size1@3@@Z to: ?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@01@Z llvm-svn: 256622 --- clang/lib/AST/MicrosoftMangle.cpp | 34 +++++++++++++++++++++++++---- clang/test/CodeGenCXX/mangle-ms.cpp | 4 ++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index ba8ff2702793..87d088cc11aa 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -224,6 +224,9 @@ class MicrosoftCXXNameMangler { typedef llvm::DenseMap ArgBackRefMap; ArgBackRefMap TypeBackReferences; + typedef std::set PassObjectSizeArgsSet; + PassObjectSizeArgsSet PassObjectSizeArgs; + ASTContext &getASTContext() const { return Context.getASTContext(); } // FIXME: If we add support for __ptr32/64 qualifiers, then we should push @@ -293,6 +296,7 @@ private: void mangleObjCMethodName(const ObjCMethodDecl *MD); void mangleArgumentType(QualType T, SourceRange Range); + void manglePassObjectSizeArg(const PassObjectSizeAttr *POSA); // Declare manglers for every type class. #define ABSTRACT_TYPE(CLASS, PARENT) @@ -1083,8 +1087,10 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( // Templates have their own context for back references. ArgBackRefMap OuterArgsContext; BackRefVec OuterTemplateContext; + PassObjectSizeArgsSet OuterPassObjectSizeArgs; NameBackReferences.swap(OuterTemplateContext); TypeBackReferences.swap(OuterArgsContext); + PassObjectSizeArgs.swap(OuterPassObjectSizeArgs); mangleUnscopedTemplateName(TD); mangleTemplateArgs(TD, TemplateArgs); @@ -1092,6 +1098,7 @@ void MicrosoftCXXNameMangler::mangleTemplateInstantiationName( // Restore the previous back reference contexts. NameBackReferences.swap(OuterTemplateContext); TypeBackReferences.swap(OuterArgsContext); + PassObjectSizeArgs.swap(OuterPassObjectSizeArgs); } void @@ -1477,6 +1484,27 @@ void MicrosoftCXXNameMangler::mangleArgumentType(QualType T, } } +void MicrosoftCXXNameMangler::manglePassObjectSizeArg( + const PassObjectSizeAttr *POSA) { + int Type = POSA->getType(); + + auto Iter = PassObjectSizeArgs.insert(Type).first; + void *TypePtr = (void *)&*Iter; + ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr); + + if (Found == TypeBackReferences.end()) { + mangleArtificalTagType(TTK_Enum, "__pass_object_size" + llvm::utostr(Type), + {"__clang"}); + + if (TypeBackReferences.size() < 10) { + size_t Size = TypeBackReferences.size(); + TypeBackReferences[TypePtr] = Size; + } + } else { + Out << Found->second; + } +} + void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, QualifierMangleMode QMM) { // Don't use the canonical types. MSVC includes things like 'const' on @@ -1879,10 +1907,8 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // necessary to just cross our fingers and hope this type+namespace // combination doesn't conflict with anything? if (D) - if (auto *P = D->getParamDecl(I)->getAttr()) - mangleArtificalTagType(TTK_Enum, "__pass_object_size" + - llvm::utostr(P->getType()), - {"__clang"}); + if (const auto *P = D->getParamDecl(I)->getAttr()) + manglePassObjectSizeArg(P); } // ::= Z # ellipsis if (Proto->isVariadic()) diff --git a/clang/test/CodeGenCXX/mangle-ms.cpp b/clang/test/CodeGenCXX/mangle-ms.cpp index d95f781f1204..c2a311423a9d 100644 --- a/clang/test/CodeGenCXX/mangle-ms.cpp +++ b/clang/test/CodeGenCXX/mangle-ms.cpp @@ -440,6 +440,10 @@ namespace PassObjectSize { int foo(int *const i __attribute__((pass_object_size(0)))) { return 0; } // CHECK-DAG: define i32 @"\01?bar@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@@Z" int bar(int *const i __attribute__((pass_object_size(1)))) { return 0; } +// CHECK-DAG: define i32 @"\01?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@0W4__pass_object_size0@3@@Z" +int qux(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(0)))) { return 0; } +// CHECK-DAG: define i32 @"\01?zot@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@01@Z" +int zot(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(1)))) { return 0; } } namespace Atomic {