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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits