forked from OSchip/llvm-project
msabi: Fix exponential mangling time for even more contrived inputs
This is a follow-up to r362293 which fixed exponential time needed for mangling certain templates. This fixes the same issue if that template pattern happens in template arguments > 10: The first ten template arguments can use back references, and r362293 added caching for back references. For latter arguments, we have to add a cache for the mangling itself instead. Fixes PR42091 even more. Differential Revision: https://reviews.llvm.org/D62780 llvm-svn: 362560
This commit is contained in:
parent
5e312be0fa
commit
487077698c
|
@ -31,6 +31,7 @@
|
|||
#include "llvm/Support/xxhash.h"
|
||||
#include "llvm/Support/MD5.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
|
@ -268,6 +269,11 @@ class MicrosoftCXXNameMangler {
|
|||
ArgBackRefMap FunArgBackReferences;
|
||||
ArgBackRefMap TemplateArgBackReferences;
|
||||
|
||||
typedef llvm::DenseMap<const void *, StringRef> TemplateArgStringMap;
|
||||
TemplateArgStringMap TemplateArgStrings;
|
||||
llvm::StringSaver TemplateArgStringStorage;
|
||||
llvm::BumpPtrAllocator TemplateArgStringStorageAlloc;
|
||||
|
||||
typedef std::set<std::pair<int, bool>> PassObjectSizeArgsSet;
|
||||
PassObjectSizeArgsSet PassObjectSizeArgs;
|
||||
|
||||
|
@ -282,18 +288,21 @@ public:
|
|||
|
||||
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_)
|
||||
: Context(C), Out(Out_), Structor(nullptr), StructorType(-1),
|
||||
TemplateArgStringStorage(TemplateArgStringStorageAlloc),
|
||||
PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
|
||||
64) {}
|
||||
|
||||
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
|
||||
const CXXConstructorDecl *D, CXXCtorType Type)
|
||||
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
|
||||
TemplateArgStringStorage(TemplateArgStringStorageAlloc),
|
||||
PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
|
||||
64) {}
|
||||
|
||||
MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
|
||||
const CXXDestructorDecl *D, CXXDtorType Type)
|
||||
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
|
||||
TemplateArgStringStorage(TemplateArgStringStorageAlloc),
|
||||
PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
|
||||
64) {}
|
||||
|
||||
|
@ -809,24 +818,34 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
|
|||
// TD / TemplateArg pairs.
|
||||
ArgBackRefMap::iterator Found = TemplateArgBackReferences.find(ND);
|
||||
if (Found == TemplateArgBackReferences.end()) {
|
||||
// Mangle full template name into temporary buffer.
|
||||
llvm::SmallString<64> TemplateMangling;
|
||||
llvm::raw_svector_ostream Stream(TemplateMangling);
|
||||
MicrosoftCXXNameMangler Extra(Context, Stream);
|
||||
Extra.mangleTemplateInstantiationName(TD, *TemplateArgs);
|
||||
|
||||
// Use the string backref vector to possibly get a back reference.
|
||||
mangleSourceName(TemplateMangling);
|
||||
TemplateArgStringMap::iterator Found = TemplateArgStrings.find(ND);
|
||||
if (Found == TemplateArgStrings.end()) {
|
||||
// Mangle full template name into temporary buffer.
|
||||
llvm::SmallString<64> TemplateMangling;
|
||||
llvm::raw_svector_ostream Stream(TemplateMangling);
|
||||
MicrosoftCXXNameMangler Extra(Context, Stream);
|
||||
Extra.mangleTemplateInstantiationName(TD, *TemplateArgs);
|
||||
|
||||
// Memoize back reference for this type.
|
||||
BackRefVec::iterator StringFound =
|
||||
llvm::find(NameBackReferences, TemplateMangling);
|
||||
if (StringFound != NameBackReferences.end()) {
|
||||
TemplateArgBackReferences[ND] =
|
||||
StringFound - NameBackReferences.begin();
|
||||
// Use the string backref vector to possibly get a back reference.
|
||||
mangleSourceName(TemplateMangling);
|
||||
|
||||
// Memoize back reference for this type if one exist, else memoize
|
||||
// the mangling itself.
|
||||
BackRefVec::iterator StringFound =
|
||||
llvm::find(NameBackReferences, TemplateMangling);
|
||||
if (StringFound != NameBackReferences.end()) {
|
||||
TemplateArgBackReferences[ND] =
|
||||
StringFound - NameBackReferences.begin();
|
||||
} else {
|
||||
TemplateArgStrings[ND] =
|
||||
TemplateArgStringStorage.save(TemplateMangling.str());
|
||||
}
|
||||
} else {
|
||||
Out << Found->second; // Outputs a StringRef.
|
||||
}
|
||||
} else {
|
||||
Out << Found->second;
|
||||
Out << Found->second; // Outputs a back reference (an int).
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -232,3 +232,25 @@ using B6 = Food<B5, B4, B3, B2, B1, B0, B0, B0, B0, B0, B5, B5, B5, B5, B5, B5,
|
|||
void f(B6 a) {}
|
||||
|
||||
// CHECK: "?f@@YAXU?$Food@U?$Food@U?$Food@U?$Food@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U3@U3@U3@U3@U3@U3@U3@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U4@U4@U4@U4@U4@U4@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U3@U3@U3@U3@U3@U3@U3@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U5@U5@U5@U5@U5@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U3@U3@U3@U3@U3@U3@U3@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U4@U4@U4@U4@U4@U4@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U3@U3@U3@U3@U3@U3@U3@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U2@U2@U2@U2@U2@U2@U2@U2@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@U?$Food@HHHHHHHHHHHHHHHHHHHH@@U6@U6@U6@U6@U1@U1@U1@U1@U1@U1@U1@U1@U1@U1@@@@Z"
|
||||
|
||||
|
||||
// Similar to the previous case, except that the later arguments aren't
|
||||
// present in the earlier ones and hence aren't in the backref cache.
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7,
|
||||
class T8, class T9, class T10, class T11, class T12, class T13,
|
||||
class T14, class T15, class T16, class T17, class T18, class T19,
|
||||
class T20>
|
||||
struct Fooe {};
|
||||
|
||||
using C0 = Fooe<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>;
|
||||
using C1 = Fooe<C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0>;
|
||||
using C2 = Fooe<C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1>;
|
||||
using C3 = Fooe<C1, C1, C0, C0, C0, C0, C0, C0, C0, C0, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2>;
|
||||
using C4 = Fooe<C2, C2, C1, C0, C0, C0, C0, C0, C0, C0, C3, C3, C3, C3, C3, C3, C3, C3, C3, C3>;
|
||||
using C5 = Fooe<C3, C3, C2, C1, C0, C0, C0, C0, C0, C0, C4, C4, C4, C4, C4, C4, C4, C4, C4, C4>;
|
||||
using C6 = Fooe<C4, C4, C3, C2, C1, C0, C0, C0, C0, C0, C5, C5, C5, C5, C5, C5, C5, C5, C5, C5>;
|
||||
using C7 = Fooe<C5, C4, C3, C2, C1, C0, C0, C0, C0, C0, C6, C6, C6, C6, C6, C6, C6, C6, C6, C6>;
|
||||
|
||||
// This too should take milliseconds, not minutes.
|
||||
void f(C7 a) {}
|
||||
// CHECK: "??@f23afdfb44276eaa53a5575352cf0ebc@"
|
||||
|
|
Loading…
Reference in New Issue