From: Charles Davis Date: Wed, 30 Jun 2010 08:09:57 +0000 (+0000) Subject: Mangle arrays in the Microsoft C++ Mangler. It's not quite finished (it X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0b8fe8c68eb503b9955f13c0c27b18b1f8321158;p=clang Mangle arrays in the Microsoft C++ Mangler. It's not quite finished (it doesn't mangle array parameters right), but I think that should be fixed in Sema (Doug, John, what do you think?). Also, stub out the remaining mangleType() routines. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107264 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 18e648787e..1360d522ce 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -70,6 +70,8 @@ private: void mangleType(const TagType*); void mangleType(const FunctionType *T, bool IsStructor, bool IsInstMethod); + void mangleType(const ArrayType *T, bool IsGlobal); + void mangleExtraDimensions(QualType T); void mangleFunctionClass(const FunctionDecl *FD); void mangleCallingConvention(const FunctionType *T); void mangleThrowSpecification(const FunctionProtoType *T); @@ -243,13 +245,17 @@ void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) { Out << '4'; // Now mangle the type. // ::= - // ::= A # pointers and references + // ::= A # pointers, references, arrays // Pointers and references are odd. The type of 'int * const foo;' gets // mangled as 'QAHA' instead of 'PAHB', for example. QualType Ty = VD->getType(); if (Ty->isPointerType() || Ty->isReferenceType()) { mangleType(Ty); Out << 'A'; + } else if (Ty->isArrayType()) { + // Global arrays are funny, too. + mangleType(static_cast(Ty.getTypePtr()), true); + Out << 'A'; } else { mangleType(Ty.getLocalUnqualifiedType()); mangleQualifiers(Ty.getLocalQualifiers(), false); @@ -662,26 +668,11 @@ void MicrosoftCXXNameMangler::mangleType(QualType T) { case Type::CLASS: \ llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \ return; -#define TYPE(CLASS, PARENT) +#define TYPE(CLASS, PARENT) \ +case Type::CLASS: \ +mangleType(static_cast(T.getTypePtr())); \ +break; #include "clang/AST/TypeNodes.def" - case Type::Builtin: - mangleType(static_cast(T.getTypePtr())); - break; - case Type::Enum: - mangleType(static_cast(T.getTypePtr())); - break; - case Type::Record: - mangleType(static_cast(T.getTypePtr())); - break; - case Type::Pointer: - mangleType(static_cast(T.getTypePtr())); - break; - case Type::LValueReference: - mangleType(static_cast(T.getTypePtr())); - break; - default: - assert(false && "Don't know how to mangle this type!"); - break; } } @@ -763,7 +754,8 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T) { // Structors only appear in decls, so at this point we know it's not a // structor type. - // I'll probably have mangleType(MemberPointerType) call + // I'll probably have mangleType(MemberPointerType) call the mangleType() + // method directly. mangleType(T, false, false); } void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T) { @@ -801,7 +793,7 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionType *T, ArgEnd = Proto->arg_type_end(); Arg != ArgEnd; ++Arg) mangleType(*Arg); - + // ::= Z # ellipsis if (Proto->isVariadic()) Out << 'Z'; @@ -904,6 +896,10 @@ void MicrosoftCXXNameMangler::mangleThrowSpecification( Out << 'Z'; } +void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T) { + assert(false && "Don't know how to mangle UnresolvedUsingTypes yet!"); +} + // ::= | | | // ::= T // ::= U @@ -935,14 +931,88 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) { mangleName(T->getDecl()); } +// ::= +// ::= P [Y +] +// # as global +// ::= Q [Y +] +// # as param +// It's supposed to be the other way around, but for some strange reason, it +// isn't. Today this behavior is retained for the sole purpose of backwards +// compatibility. +void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) { + // This isn't a recursive mangling, so now we have to do it all in this + // one call. + if (IsGlobal) + Out << 'P'; + else + Out << 'Q'; + mangleExtraDimensions(T->getElementType()); +} +void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T) { + mangleType(static_cast(T), false); +} +void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T) { + mangleType(static_cast(T), false); +} +void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T) { + mangleType(static_cast(T), false); +} +void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T) { + mangleType(static_cast(T), false); +} +void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) { + llvm::SmallVector Dimensions; + for (;;) { + if (ElementTy->isConstantArrayType()) { + const ConstantArrayType *CAT = + static_cast(ElementTy.getTypePtr()); + Dimensions.push_back(CAT->getSize()-1); + ElementTy = CAT->getElementType(); + } else if (ElementTy->isVariableArrayType()) { + assert(false && "Don't know how to mangle VLAs!"); + } else if (ElementTy->isDependentSizedArrayType()) { + // The dependent expression has to be folded into a constant (TODO). + assert(false && "Don't know how to mangle dependent-sized arrays!"); + } else if (ElementTy->isIncompleteArrayType()) continue; + else break; + } + mangleQualifiers(ElementTy.getQualifiers(), false); + // If there are any additional dimensions, mangle them now. + if (Dimensions.size() > 0) { + Out << 'Y'; + // ::= # number of extra dimensions minus 1 + mangleNumber(Dimensions.size()-1); + for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) { + mangleNumber(Dimensions[Dim].getLimitedValue()); + } + } + mangleType(ElementTy.getLocalUnqualifiedType()); +} + +void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T) { + assert(false && "Don't know how to mangle MemberPointerTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T) { + assert(false && "Don't know how to mangle TemplateTypeParmTypes yet!"); +} + // ::= // ::= void MicrosoftCXXNameMangler::mangleType(const PointerType *T) { QualType PointeeTy = T->getPointeeType(); - if (!PointeeTy.hasLocalQualifiers()) - // Lack of qualifiers is mangled as 'A'. - Out << 'A'; - mangleType(PointeeTy); + if (PointeeTy->isArrayType()) { + // Pointers to arrays are mangled like arrays. + mangleExtraDimensions(T->getPointeeType()); + } else { + if (!PointeeTy.hasQualifiers()) + // Lack of qualifiers is mangled as 'A'. + Out << 'A'; + mangleType(PointeeTy); + } +} +void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T) { + assert(false && "Don't know how to mangle ObjCObjectPointerTypes yet!"); } // ::= @@ -950,12 +1020,72 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T) { void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T) { Out << 'A'; QualType PointeeTy = T->getPointeeType(); - if (!PointeeTy.hasLocalQualifiers()) + if (!PointeeTy.hasQualifiers()) // Lack of qualifiers is mangled as 'A'. Out << 'A'; mangleType(PointeeTy); } +void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T) { + assert(false && "Don't know how to mangle RValueReferenceTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const ComplexType *T) { + assert(false && "Don't know how to mangle ComplexTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const VectorType *T) { + assert(false && "Don't know how to mangle VectorTypes yet!"); +} +void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T) { + assert(false && "Don't know how to mangle ExtVectorTypes yet!"); +} +void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T) { + assert(false && "Don't know how to mangle DependentSizedExtVectorTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T) { + assert(false && "Don't know how to mangle ObjCInterfaceTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T) { + assert(false && "Don't know how to mangle ObjCObjectTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T) { + assert(false && "Don't know how to mangle BlockPointerTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T) { + assert(false && "Don't know how to mangle InjectedClassNameTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T) { + assert(false && "Don't know how to mangle TemplateSpecializationTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T) { + assert(false && "Don't know how to mangle DependentNameTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType( + const DependentTemplateSpecializationType *T) { + assert(false && + "Don't know how to mangle DependentTemplateSpecializationTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T) { + assert(false && "Don't know how to mangle TypeOfTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T) { + assert(false && "Don't know how to mangle TypeOfExprTypes yet!"); +} + +void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T) { + assert(false && "Don't know how to mangle DecltypeTypes yet!"); +} + void MicrosoftMangleContext::mangleName(const NamedDecl *D, llvm::SmallVectorImpl &Name) { assert((isa(D) || isa(D)) && diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index d0bd4a967d..6f1f95ccd0 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -8,6 +8,7 @@ // CHECK: @"\01?f@foo@@2DD" // CHECK: @"\01?g@bar@@2HA" // CHECK: @"\01?h@@3QAHA" +// CHECK: @"\01?i@@3PAY0BD@HA" int a; @@ -42,6 +43,8 @@ enum quux { qthree }; +// NOTE: The calling convention is supposed to be __thiscall by default, +// but that needs to be fixed in Sema/AST. int foo::operator+(int a) {return a;} // CHECK: @"\01??Hfoo@@QAAHH@Z" @@ -53,6 +56,8 @@ int bar::g; extern int * const h = &a; +int i[10][20]; + // Static functions are mangled, too. // Also make sure calling conventions, arglists, and throw specs work. static void __stdcall alpha(float a, double b) throw() {} @@ -71,3 +76,8 @@ void gamma(class foo, struct bar, union baz, enum quux) {} // Make sure pointer/reference-type mangling works. void delta(int * const a, const long &) {} // CHECK: @"\01?delta@@YAXQAHABJ@Z" + +// Array mangling. (It should be mangled as a const pointer, but that needs +// to be fixed in Sema.) +void epsilon(int a[][10][20]) {} +// CHECK: @"\01?epsilon@@YAXPAY19BD@H@Z"