]> granicus.if.org Git - clang/commitdiff
Mangle arrays in the Microsoft C++ Mangler. It's not quite finished (it
authorCharles Davis <cdavis@mines.edu>
Wed, 30 Jun 2010 08:09:57 +0000 (08:09 +0000)
committerCharles Davis <cdavis@mines.edu>
Wed, 30 Jun 2010 08:09:57 +0000 (08:09 +0000)
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

lib/CodeGen/MicrosoftCXXABI.cpp
test/CodeGenCXX/mangle-ms.cpp

index 18e648787e701401de4ed6c1506cb526974fc7bb..1360d522ce7aed79b5fd93088aa7272e5438a4db 100644 (file)
@@ -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.
   // <variable-type> ::= <type> <cvr-qualifiers>
-  //                 ::= <type> A # pointers and references
+  //                 ::= <type> 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<ArrayType *>(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<const CLASS##Type*>(T.getTypePtr())); \
+break;
 #include "clang/AST/TypeNodes.def"
-  case Type::Builtin:
-    mangleType(static_cast<BuiltinType *>(T.getTypePtr()));
-    break;
-  case Type::Enum:
-    mangleType(static_cast<EnumType *>(T.getTypePtr()));
-    break;
-  case Type::Record:
-    mangleType(static_cast<RecordType *>(T.getTypePtr()));
-    break;
-  case Type::Pointer:
-    mangleType(static_cast<PointerType *>(T.getTypePtr()));
-    break;
-  case Type::LValueReference:
-    mangleType(static_cast<LValueReferenceType *>(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);
-    
+
     // <builtin-type>      ::= 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!");
+}
+
 // <type>        ::= <union-type> | <struct-type> | <class-type> | <enum-type>
 // <union-type>  ::= T <name>
 // <struct-type> ::= U <name>
@@ -935,14 +931,88 @@ void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
   mangleName(T->getDecl());
 }
 
+// <type>       ::= <array-type>
+// <array-type> ::= P <cvr-qualifiers> [Y <dimension-count> <dimension>+]
+//                                                  <element-type> # as global
+//              ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
+//                                                  <element-type> # 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<const ArrayType *>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T) {
+  mangleType(static_cast<const ArrayType *>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T) {
+  mangleType(static_cast<const ArrayType *>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T) {
+  mangleType(static_cast<const ArrayType *>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {
+  llvm::SmallVector<llvm::APInt, 3> Dimensions;
+  for (;;) {
+    if (ElementTy->isConstantArrayType()) {
+      const ConstantArrayType *CAT =
+      static_cast<const ConstantArrayType *>(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';
+    // <dimension-count> ::= <number> # 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!");
+}
+
 // <type> ::= <pointer-type>
 // <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
 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!");
 }
 
 // <type> ::= <reference-type>
@@ -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<char> &Name) {
   assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
index d0bd4a967dea641b31b08c2fda5bf2dbb4f01a69..6f1f95ccd08b613fb903e3caa8e482dd250046cd 100644 (file)
@@ -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"