[cfe-commits] r106081 - in /cfe/trunk: lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/mangle-ms.cpp
Charles Davis
cdavis at mines.edu
Tue Jun 15 22:33:16 PDT 2010
Author: cdavis
Date: Wed Jun 16 00:33:16 2010
New Revision: 106081
URL: http://llvm.org/viewvc/llvm-project?rev=106081&view=rev
Log:
Start mangling function types in the Microsoft C++ Mangler.
Modified:
cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
cfe/trunk/test/CodeGenCXX/mangle-ms.cpp
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=106081&r1=106080&r2=106081&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Wed Jun 16 00:33:16 2010
@@ -45,6 +45,7 @@
void mangle(const NamedDecl *D, llvm::StringRef Prefix = "?");
void mangleName(const NamedDecl *ND);
+ void mangleFunctionEncoding(const FunctionDecl *FD);
void mangleVariableEncoding(const VarDecl *VD);
void mangleType(QualType T);
@@ -65,6 +66,11 @@
#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T);
#include "clang/AST/TypeNodes.def"
+ void mangleType(const FunctionType *T, bool IsStructor);
+ void mangleFunctionClass(const FunctionDecl *FD);
+ void mangleCallingConvention(const FunctionType *T);
+ void mangleThrowSpecification(const FunctionProtoType *T);
+
};
/// MicrosoftMangleContext - Overrides the default MangleContext for the
@@ -174,16 +180,64 @@
return;
}
- // <mangled-name> ::= ? <name> <type>
+ // <mangled-name> ::= ? <name> <type-encoding>
Out << Prefix;
mangleName(D);
- if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ mangleFunctionEncoding(FD);
+ else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
mangleVariableEncoding(VD);
- // TODO: Function types.
+ // TODO: Fields? Can MSVC even mangle them?
+}
+
+void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+ // <type-encoding> ::= <function-class> <function-type>
+
+ // Don't mangle in the type if this isn't a decl we should typically mangle.
+ if (!Context.shouldMangleDeclName(FD))
+ return;
+
+ // We should never ever see a FunctionNoProtoType at this point.
+ // We don't even know how to mangle their types anyway :).
+ FunctionProtoType *OldType = cast<FunctionProtoType>(FD->getType());
+
+ bool InStructor = false;
+ const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (MD) {
+ if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
+ InStructor = true;
+ }
+
+ // First, the function class.
+ mangleFunctionClass(FD);
+
+ // If this is a C++ instance method, mangle the CVR qualifiers for the
+ // this pointer.
+ if (MD && MD->isInstance())
+ mangleQualifiers(Qualifiers::fromCVRMask(OldType->getTypeQuals()), false);
+
+ // Do the canonicalization out here because parameter types can
+ // undergo additional canonicalization (e.g. array decay).
+ const FunctionProtoType *FT = cast<FunctionProtoType>(getASTContext()
+ .getCanonicalType(OldType));
+ // If the function's type had a throw spec, canonicalization removed it.
+ // Get it back.
+ FT = cast<FunctionProtoType>(getASTContext().getFunctionType(
+ FT->getResultType(),
+ FT->arg_type_begin(),
+ FT->getNumArgs(),
+ FT->isVariadic(),
+ FT->getTypeQuals(),
+ OldType->hasExceptionSpec(),
+ OldType->hasAnyExceptionSpec(),
+ OldType->getNumExceptions(),
+ OldType->exception_begin(),
+ FT->getExtInfo()).getTypePtr());
+ mangleType(FT, InStructor);
}
void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
- // <encoding> ::= <variable name> <storage-class> <variable-type>
+ // <type-encoding> ::= <storage-class> <variable-type>
// <storage-class> ::= 0 # private static member
// ::= 1 # protected static member
// ::= 2 # public static member
@@ -523,6 +577,149 @@
}
}
+// <type> ::= <function-type>
+void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T) {
+ // Structors only appear in decls, so at this point we know it's not a
+ // structor type.
+ mangleType(T, false);
+}
+void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T) {
+ llvm_unreachable("Can't mangle K&R function prototypes");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,
+ bool IsStructor) {
+ // <function-type> ::= <calling-convention> <return-type> <argument-list>
+ // <throw-spec>
+ mangleCallingConvention(T);
+
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+
+ // Structors always have a 'void' return type, but MSVC mangles them as an
+ // '@' (because they have no declared return type).
+ if (IsStructor)
+ Out << '@';
+ else
+ mangleType(Proto->getResultType());
+
+ // <argument-list> ::= X # void
+ // ::= <type>+ @
+ // ::= <type>* Z # varargs
+ if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
+ Out << 'X';
+ } else {
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ mangleType(*Arg);
+
+ // <builtin-type> ::= Z # ellipsis
+ if (Proto->isVariadic())
+ Out << 'Z';
+ else
+ Out << '@';
+ }
+
+ mangleThrowSpecification(Proto);
+}
+
+void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
+ // <function-class> ::= A # private: near
+ // ::= B # private: far
+ // ::= C # private: static near
+ // ::= D # private: static far
+ // ::= E # private: virtual near
+ // ::= F # private: virtual far
+ // ::= G # private: thunk near
+ // ::= H # private: thunk far
+ // ::= I # protected: near
+ // ::= J # protected: far
+ // ::= K # protected: static near
+ // ::= L # protected: static far
+ // ::= M # protected: virtual near
+ // ::= N # protected: virtual far
+ // ::= O # protected: thunk near
+ // ::= P # protected: thunk far
+ // ::= Q # public: near
+ // ::= R # public: far
+ // ::= S # public: static near
+ // ::= T # public: static far
+ // ::= U # public: virtual near
+ // ::= V # public: virtual far
+ // ::= W # public: thunk near
+ // ::= X # public: thunk far
+ // ::= Y # global near
+ // ::= Z # global far
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ switch (MD->getAccess()) {
+ default:
+ case AS_private:
+ if (MD->isStatic())
+ Out << 'C';
+ else if (MD->isVirtual())
+ Out << 'E';
+ else
+ Out << 'A';
+ break;
+ case AS_protected:
+ if (MD->isStatic())
+ Out << 'K';
+ else if (MD->isVirtual())
+ Out << 'M';
+ else
+ Out << 'I';
+ break;
+ case AS_public:
+ if (MD->isStatic())
+ Out << 'S';
+ else if (MD->isVirtual())
+ Out << 'U';
+ else
+ Out << 'Q';
+ }
+ } else
+ Out << 'Y';
+}
+void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
+ // <calling-convention> ::= A # __cdecl
+ // ::= B # __export __cdecl
+ // ::= C # __pascal
+ // ::= D # __export __pascal
+ // ::= E # __thiscall
+ // ::= F # __export __thiscall
+ // ::= G # __stdcall
+ // ::= H # __export __stdcall
+ // ::= I # __fastcall
+ // ::= J # __export __fastcall
+ // 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
+ // that they could be in a DLL and somebody from another module could call
+ // them.)
+ switch (T->getCallConv()) {
+ case CC_Default:
+ case CC_C: Out << 'A'; break;
+ case CC_X86ThisCall: Out << 'E'; break;
+ case CC_X86StdCall: Out << 'G'; break;
+ case CC_X86FastCall: Out << 'I'; break;
+ }
+}
+void MicrosoftCXXNameMangler::mangleThrowSpecification(
+ const FunctionProtoType *FT) {
+ // <throw-spec> ::= Z # throw(...) (default)
+ // ::= @ # throw() or __declspec/__attribute__((nothrow))
+ // ::= <type>+
+ if (!FT->hasExceptionSpec() || FT->hasAnyExceptionSpec())
+ Out << 'Z';
+ else {
+ for (unsigned Exception = 0, NumExceptions = FT->getNumExceptions();
+ Exception < NumExceptions;
+ ++Exception)
+ mangleType(FT->getExceptionType(Exception).getLocalUnqualifiedType());
+ Out << '@';
+ }
+}
+
void MicrosoftMangleContext::mangleName(const NamedDecl *D,
llvm::SmallVectorImpl<char> &Name) {
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
Modified: cfe/trunk/test/CodeGenCXX/mangle-ms.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms.cpp?rev=106081&r1=106080&r2=106081&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms.cpp Wed Jun 16 00:33:16 2010
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-apple-darwin10 | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-apple-darwin10 | FileCheck %s
// CHECK: @"\01?a@@3HA"
// CHECK: @"\01?b at N@@3HA"
@@ -13,6 +13,7 @@
static int c;
int _c(void) {return c;}
+// CHECK: @"\01?_c@@YAHXZ"
class foo {
static const short d;
@@ -26,3 +27,14 @@
volatile long foo::e;
const volatile char foo::f = 'C';
+// Static functions are mangled, too.
+// Also make sure calling conventions, arglists, and throw specs work.
+static void __stdcall alpha(float a, double b) throw() {}
+bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) {
+// CHECK: @"\01?beta@@YI_N_J_W at CE@"
+ alpha(0.f, 0.0);
+ return false;
+}
+
+// CHECK: @"\01?alpha@@YGXMN@@"
+
More information about the cfe-commits
mailing list