Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -1465,8 +1465,12 @@ * ``m``: Mips mangling: Private symbols get a ``$`` prefix. * ``o``: Mach-O mangling: Private symbols get ``L`` prefix. Other symbols get a ``_`` prefix. - * ``w``: Windows COFF prefix: Similar to Mach-O, but stdcall and fastcall - functions also get a suffix based on the frame size. + * ``w``: Windows COFF prefix: Similar to Mach-O, but stdcall, fastcall, and + vectorcall functions also get a suffix based on the parameter pack size. + + Prefixing symbols with the ``\01`` character disables any mangling. + Prefixing non-private symbols with the ``?`` character disables any + mangling. ``n::...`` This specifies a set of native integer widths for the target CPU in bits. For example, it might contain ``n32`` for 32-bit PowerPC, Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -44,6 +44,10 @@ * The minimum required Visual Studio version for building LLVM is now 2013 Update 4. +* Symbols starting with ``?`` are no longer mangled by LLVM, meaning most + symbols used in the Microsoft C++ ABI no longer require ``\01`` prefix + escapes. + * ... next change ... .. NOTE Index: lib/IR/Mangler.cpp =================================================================== --- lib/IR/Mangler.cpp +++ lib/IR/Mangler.cpp @@ -113,13 +113,22 @@ } StringRef Name = GV->getName(); + char Prefix = DL->getGlobalPrefix(); // Mangle functions with Microsoft calling conventions specially. Only do // this mangling for x86_64 vectorcall and 32-bit x86. const Function *MSFunc = dyn_cast(GV); if (Name.startswith("\01")) - MSFunc = nullptr; // Don't mangle when \01 is present. + MSFunc = nullptr; // Don't mangle when the first character is '\01'. + + // Don't add prefixes or MS suffixes for symbols starting with '?'. Add the + // private global prefix if necessary, though. + if (Name.startswith("?")) { + MSFunc = nullptr; + Prefix = '\0'; + } + CallingConv::ID CC = MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C; if (!DL->hasMicrosoftFastStdCallMangling() && Index: test/CodeGen/X86/mangle-question-mark.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/mangle-question-mark.ll @@ -0,0 +1,63 @@ +; The purpose of this test is to see if the MC layer properly handles symbol +; names needing quoting on MS/Windows. This code is generated by clang when +; using -cxx-abi microsoft. At some point, we'd like to stop using the '\01' +; escape and just use a leading '?'. + +; RUN: llc -mtriple i686-pc-win32 < %s | FileCheck %s --check-prefix=COFF +; RUN: llc -mtriple i686-linux-gnu < %s | FileCheck %s --check-prefix=ELF +; RUN: llc -mtriple i686-apple-darwin < %s | FileCheck %s --check-prefix=MACHO + +; Currently all object files allow escaping private symbols, but eventually we +; might want to reject that. + +; COFF: calll "?withescape@A@@QBEXXZ" +; COFF: calll "?withquestion@A@@QBEXXZ" +; COFF: calll "L?privatequestion@A@@QBEXXZ" +; COFF: calll "L?privatequestionfast@A@@QBEXXZ" +; COFF: calll "?escapedprivate@A@@QBEXXZ" + +; ELF: calll "?withescape@A@@QBEXXZ" +; ELF: calll "?withquestion@A@@QBEXXZ" +; ELF: calll ".L?privatequestion@A@@QBEXXZ" +; ELF: calll ".L?privatequestionfast@A@@QBEXXZ" +; ELF: calll "?escapedprivate@A@@QBEXXZ" + +; On MachO, everything gets the local prefix due to stubbing. + +; MACHO: calll "L?withescape@A@@QBEXXZ$stub" +; MACHO: calll "L?withquestion@A@@QBEXXZ$stub" +; MACHO: calll "l?privatequestion@A@@QBEXXZ" +; MACHO: calll "l?privatequestionfast@A@@QBEXXZ" +; MACHO: calll "?escapedprivate@A@@QBEXXZ" + +; Check the stubs. + +; MACHO: .indirect_symbol "?withescape@A@@QBEXXZ" +; MACHO: .indirect_symbol "?withquestion@A@@QBEXXZ" + +%struct.A = type {} + +define i32 @main() { +entry: + tail call void @"\01?withescape@A@@QBEXXZ"(%struct.A* null) + tail call void @"?withquestion@A@@QBEXXZ"(%struct.A* null) + tail call void @"?privatequestion@A@@QBEXXZ"(%struct.A* null) + tail call x86_fastcallcc void @"?privatequestionfast@A@@QBEXXZ"(%struct.A* null) + tail call void @"\01?escapedprivate@A@@QBEXXZ"(%struct.A* null) + ret i32 0 +} + +declare void @"\01?withescape@A@@QBEXXZ"(%struct.A*) +declare void @"?withquestion@A@@QBEXXZ"(%struct.A*) + +define private void @"?privatequestion@A@@QBEXXZ"(%struct.A*) { + ret void +} + +define private x86_fastcallcc void @"?privatequestionfast@A@@QBEXXZ"(%struct.A*) { + ret void +} + +define private void @"\01?escapedprivate@A@@QBEXXZ"(%struct.A*) { + ret void +} Index: test/MC/COFF/symbol-mangling.ll =================================================================== --- test/MC/COFF/symbol-mangling.ll +++ /dev/null @@ -1,17 +0,0 @@ -; The purpose of this test is to see if the MC layer properly handles symbol -; names needing quoting on MS/Windows. This code is generated by clang when -; using -cxx-abi microsoft. - -; RUN: llc -filetype=asm -mtriple i686-pc-win32 %s -o - | FileCheck %s - -; CHECK: ?sayhi@A@@QBEXXZ - -%struct.A = type {} - -define i32 @main() { -entry: - tail call void @"\01?sayhi@A@@QBEXXZ"(%struct.A* null) - ret i32 0 -} - -declare void @"\01?sayhi@A@@QBEXXZ"(%struct.A*) Index: test/MC/COFF/tricky-names.ll =================================================================== --- test/MC/COFF/tricky-names.ll +++ test/MC/COFF/tricky-names.ll @@ -3,14 +3,16 @@ ; Check that we can roundtrip these names through our assembler. ; RUN: llc -mtriple=i686-pc-win32 %s -o - | llvm-mc -triple i686-pc-win32 -filetype=obj | llvm-readobj -t | FileCheck %s --check-prefix=READOBJ +; RUN: llc -mtriple=x86_64-pc-win32 %s -o - | llvm-mc -triple x86_64-pc-win32 -filetype=obj | llvm-readobj -t | FileCheck %s --check-prefix=READOBJ +; We don't need the \01 prefix for MSVC symbols using ?. -@"\01??__E_Generic_object@?$_Error_objects@H@std@@YAXXZ" = global i32 0 +@"??__E_Generic_object@?$_Error_objects@H@std@@YAXXZ" = global i32 0 @"\01__ZL16ExceptionHandlerP19_EXCEPTION_POINTERS@4" = global i32 0 @"\01@foo.bar" = global i32 0 -define weak i32 @"\01??_B?$num_put@_WV?$back_insert_iterator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@std@@@std@@51"() section ".text" { - %a = load i32, i32* @"\01??__E_Generic_object@?$_Error_objects@H@std@@YAXXZ" +define weak i32 @"??_B?$num_put@_WV?$back_insert_iterator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@std@@@std@@51"() section ".text" { + %a = load i32, i32* @"??__E_Generic_object@?$_Error_objects@H@std@@YAXXZ" %b = load i32, i32* @"\01__ZL16ExceptionHandlerP19_EXCEPTION_POINTERS@4" %c = load i32, i32* @"\01@foo.bar" %x = add i32 %a, %b