compnerd created this revision.
compnerd added reviewers: rafael, rnk.
compnerd added a subscriber: cfe-commits.

Simplify the mangling handling.  This allows for the correct handling of extern
"C" symbols in C++ input.  The observable difference with this simplification 
that additional symbols are marked as naked (\01 prefix), namely asm
labels and redefine_extname.

http://reviews.llvm.org/D12579

Files:
  lib/AST/Mangle.cpp
  test/CodeGen/asm-label.c
  test/CodeGen/mangle.c
  test/CodeGen/pr9614.c
  test/CodeGen/redefine_extname.c
  test/CodeGenCXX/redefine_extname.cpp
  test/CodeGenObjCXX/mangling.mm

Index: test/CodeGenObjCXX/mangling.mm
===================================================================
--- /dev/null
+++ test/CodeGenObjCXX/mangling.mm
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -triple i686-pc-linux -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-IA
+// RUN: %clang_cc1 -triple i386-darwin -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-IA
+// RUN: %clang_cc1 -triple i686-pc-windows-msvc -emit-llvm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MS
+
+extern "C" void extern_c_function(void) { }
+// CHECK: @extern_c_function
+
+extern "C++" void extern_cpp_function(void) { }
+// CHECK-IA: @_Z19extern_cpp_function
+// CHECK-MS: @"\01?extern_cpp_function@@YAXXZ"
+
+void asm_label(void) __asm__("alternate_label");
+void asm_label(void) { }
+// CHECK: @"\01alternate_label"
+
+extern "C++" void extern_cpp_asm_label(void) __asm__("_ZN3cppE");
+extern "C++" void extern_cpp_asm_label(void) { }
+// CHECK: @"\01_ZN3cppE"
+
+#if !defined(_MSC_VER)
+__attribute__ (( objc_root ))
+@interface I
++ (void) class_method;
+- (void) instance_method;
++ (void) class_stdcall_method __attribute__ (( stdcall ));
+- (void) instance_stdcall_method __attribute__ (( stdcall ));
++ (void) class_fastcall_method __attribute__ (( fastcall ));
+- (void) instance_fastcall_method __attribute__ (( fastcall ));
+@end
+
+@implementation I
++ (void) class_method { }
+- (void) instance_method { }
++ (void) class_stdcall_method __attribute__ (( stdcall )) { }
+- (void) instance_stdcall_method __attribute__ (( stdcall )) { }
++ (void) class_fastcall_method __attribute__ (( fastcall )) { }
+- (void) instance_fastcall_method __attribute__ (( fastcall )) { }
+@end
+
+// CHECK-IA: @"\01+[I class_method]"
+// CHECK-IA: @"\01-[I instance_method]"
+// CHECK-IA: @"\01+[I class_stdcall_method]"
+// CHECK-IA: @"\01-[I instance_stdcall_method]"
+// CHECK-IA: @"\01+[I class_fastcall_method]"
+// CHECK-IA: @"\01-[I instance_fastcall_method]"
+#endif
+
+extern "C" void __attribute__ (( stdcall )) stdcall_c_function(void) { }
+// CHECK-IA: @stdcall_c_function
+// CHECK-MS: @"\01_stdcall_c_function@0"
+extern "C++" void __attribute__ (( stdcall )) stdcall_cpp_function(void) { }
+// CHECK-IA: @_Z20stdcall_cpp_functionv
+// CHECK-MS: @"\01?stdcall_cpp_function@@YGXXZ"
+
+extern "C" void __attribute__ (( fastcall )) fastcall_c_function(void) { }
+// CHECK-IA: @fastcall_c_function
+// CHECK-MS: @"\01@fastcall_c_function@0"
+extern "C++" void __attribute__ (( fastcall )) fastcall_cpp_function(void) { }
+// CHECK-IA: @_Z21fastcall_cpp_functionv
+// CHECK-MS: @"\01?fastcall_cpp_function@@YIXXZ"
+
+extern "C" void __attribute__ (( vectorcall )) vectorcall_c_function(void) { }
+// CHECK-IA: @vectorcall_c_function
+// CHECK-MS: @"\01vectorcall_c_function@@0"
+extern "C++" void __attribute__ (( vectorcall )) vectorcall_cpp_function(void) { }
+// CHECK-IA: @_Z23vectorcall_cpp_functionv
+// CHECK-MS: @"\01?vectorcall_cpp_function@@YQXXZ"
+
+struct __attribute__ (( dllexport )) S {
+  void __attribute__ (( thiscall )) thiscall_method(void);
+  void __attribute__ (( stdcall )) stdcall_method(void);
+  void __attribute__ (( fastcall )) fastcall_method(void);
+  void __attribute__ (( vectorcall )) vectorcall_method(void);
+};
+
+void __attribute__ (( thiscall )) S::thiscall_method(void) { }
+// CHECK-IA: @_ZN1S15thiscall_methodEv
+// CHECK-MS: @"\01?thiscall_method@S@@QAEXXZ"
+void __attribute__ (( stdcall )) S::stdcall_method(void) { }
+// CHECK-IA: @_ZN1S14stdcall_methodEv
+// CHECK-MS: @"\01?stdcall_method@S@@QAGXXZ"
+void __attribute__ (( fastcall )) S::fastcall_method(void) { }
+// CHECK-IA: @_ZN1S15fastcall_methodEv
+// CHECK-MS: @"\01?fastcall_method@S@@QAIXXZ"
+void __attribute__ (( vectorcall )) S::vectorcall_method(void) { }
+// CHECK-IA: @_ZN1S17vectorcall_methodEv
+// CHECK-MS: @"\01?fastcall_method@S@@QAQXXZ"
+
Index: test/CodeGenCXX/redefine_extname.cpp
===================================================================
--- test/CodeGenCXX/redefine_extname.cpp
+++ test/CodeGenCXX/redefine_extname.cpp
@@ -13,7 +13,7 @@
   statvfs64(&st);
 // Check that even if there is a structure with redefined name before the
 // pragma, subsequent function name redefined properly. PR5172, Comment 11.
-// CHECK:  call i32 @statvfs(%struct.statvfs64* %st)
+// CHECK:  call i32 @"\01statvfs"(%struct.statvfs64* %st)
 }
 
 // This is a case when redefenition is deferred *and* we have a local of the
@@ -25,7 +25,7 @@
 }
 extern "C" {
   int foo() { return 1; }
-// CHECK: define i32 @bar()
+// CHECK: define i32 @"\01bar"()
 }
 
 // Check that #pragma redefine_extname applies to C code only, and shouldn't be
Index: test/CodeGen/redefine_extname.c
===================================================================
--- test/CodeGen/redefine_extname.c
+++ test/CodeGen/redefine_extname.c
@@ -10,9 +10,9 @@
 // __PRAGMA_REDEFINE_EXTNAME should be defined.  This will fail if it isn't...
 int fish() { return fake() + __PRAGMA_REDEFINE_EXTNAME + name; }
 // Check that the call to fake() is emitted as a call to real()
-// CHECK:   call i32 @real()
+// CHECK:   call i32 @"\01real"()
 // Check that this also works with variables names
-// CHECK:   load i32, i32* @alias
+// CHECK:   load i32, i32* @"\01alias"
 
 // This is a case when redefenition is deferred *and* we have a local of the
 // same name. PR23923.
Index: test/CodeGen/pr9614.c
===================================================================
--- test/CodeGen/pr9614.c
+++ test/CodeGen/pr9614.c
@@ -18,7 +18,7 @@
   __builtin_prefetch(0, 0, 1);
 }
 
-extern inline __attribute__((__always_inline__, __gnu_inline__)) void *memchr(void *__s, int __c, __SIZE_TYPE__ __n) {
+extern inline __attribute__((__always_inline__, __gnu_inline__)) void *memchr(const void *__s, int __c, unsigned long __n) {
   return __builtin_memchr(__s, __c, __n);
 }
 
@@ -33,13 +33,13 @@
 // CHECK-LABEL: define void @f()
 // CHECK: call void @foo()
 // CHECK: call i32 @abs(i32 0)
-// CHECK: call i8* @strrchr(
+// CHECK: call i8* @"\01strrchr"(
 // CHECK: call void @llvm.prefetch(
 // CHECK: call i8* @memchr(
 // CHECK: ret void
 
 // CHECK: declare void @foo()
 // CHECK: declare i32 @abs(i32
-// CHECK: declare i8* @strrchr(i8*, i32)
+// CHECK: declare i8* @"\01strrchr"(i8*, i32)
 // CHECK: declare i8* @memchr(
 // CHECK: declare void @llvm.prefetch(
Index: test/CodeGen/mangle.c
===================================================================
--- test/CodeGen/mangle.c
+++ test/CodeGen/mangle.c
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -o - %s | FileCheck %s
 
-// CHECK: @foo
+// CHECK: @"\01foo"
+// CHECK: @"\01foo7"
 
 // Make sure we mangle overloadable, even in C system headers.
 # 1 "somesystemheader.h" 1 3 4
@@ -9,7 +10,7 @@
 // CHECK: @_Z2f0l
 void __attribute__((__overloadable__)) f0(long b) {}
 
-// CHECK: @bar
+// CHECK: @"\01bar"
 
 // These should get merged.
 void foo() __asm__("bar");
@@ -55,7 +56,7 @@
 int func(void);
 extern int func (void) __asm__ ("FUNC");
 
-// CHECK: @FUNC
+// CHECK: @"\01FUNC"
 int func(void) {
   return 42;
 }
Index: test/CodeGen/asm-label.c
===================================================================
--- test/CodeGen/asm-label.c
+++ test/CodeGen/asm-label.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple=i686-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
-// RUN: %clang_cc1 -triple=i686-apple-darwin9 -emit-llvm %s -o - | FileCheck %s --check-prefix=DARWIN
+// RUN: %clang_cc1 -triple=i686-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple=i686-apple-darwin9 -emit-llvm %s -o - | FileCheck %s
 
 char *strerror(int) asm("alias");
 int x __asm("foo");
@@ -10,13 +10,9 @@
   return &y;
 }
 
-// LINUX: @bar = internal global i32 0
-// LINUX: @foo = common global i32 0
-// LINUX: declare i8* @alias(i32)
-
-// DARWIN: @"\01bar" = internal global i32 0
-// DARWIN: @"\01foo" = common global i32 0
-// DARWIN: declare i8* @"\01alias"(i32)
+// CHECK: @"\01bar" = internal global i32 0
+// CHECK: @"\01foo" = common global i32 0
+// CHECK: declare i8* @"\01alias"(i32)
 
 // PR7887
 int pr7887_1 asm("");
Index: lib/AST/Mangle.cpp
===================================================================
--- lib/AST/Mangle.cpp
+++ lib/AST/Mangle.cpp
@@ -119,46 +119,37 @@
   // over all other naming in the .o file.
   if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
     // If we have an asm name, then we use it as the mangling.
-
-    // Adding the prefix can cause problems when one file has a "foo" and
-    // another has a "\01foo". That is known to happen on ELF with the
-    // tricks normally used for producing aliases (PR9177). Fortunately the
-    // llvm mangler on ELF is a nop, so we can just avoid adding the \01
-    // marker.  We also avoid adding the marker if this is an alias for an
-    // LLVM intrinsic.
-    StringRef UserLabelPrefix =
-        getASTContext().getTargetInfo().getUserLabelPrefix();
-    if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm."))
+    if (!ALA->getLabel().startswith("llvm."))
       Out << '\01'; // LLVM IR Marker for __asm("foo")
 
     Out << ALA->getLabel();
     return;
   }
 
+  // ObjectiveC/C++ cannot support alternate calling conventions due to method
+  // dispatch.  Honour the mangling irrespective of the annotations.
+  if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
+    return mangleObjCMethodName(OMD, Out);
+
   const ASTContext &ASTContext = getASTContext();
   CCMangling CC = getCallingConvMangling(ASTContext, D);
   bool MCXX = shouldMangleCXXName(D);
   const TargetInfo &TI = Context.getTargetInfo();
-  if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) {
-    if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
-      mangleObjCMethodName(OMD, Out);
-    else
-      mangleCXXName(D, Out);
-    return;
-  }
 
-  Out << '\01';
+  // shouldMangleCXXName lies sometimes for the MS-ABI, so check the CC mangling
+  // when targeting MS-ABI (it doesnt consider CC which take precedence over
+  // language).
+  if (MCXX || (CC == CM_Other && TI.getCXXABI() == TargetCXXABI::Microsoft))
+    return mangleCXXName(D, Out);
+
   if (CC == CCM_Std)
-    Out << '_';
+    Out << "\01_";
   else if (CC == CCM_Fast)
-    Out << '@';
+    Out << "\01@";
+  else if (C == CCM_Vector)
+    Out << '\01';
 
-  if (!MCXX)
-    Out << D->getIdentifier()->getName();
-  else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
-    mangleObjCMethodName(OMD, Out);
-  else
-    mangleCXXName(D, Out);
+  Out << D->getIdentifier()->getName();
 
   const FunctionDecl *FD = cast<FunctionDecl>(D);
   const FunctionType *FT = FD->getType()->castAs<FunctionType>();
@@ -197,7 +188,7 @@
   if (discriminator == 0)
     Out << "_block_invoke";
   else
-    Out << "_block_invoke_" << discriminator+1;
+    Out << "_block_invoke_" << discriminator + 1;
 }
 
 void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to