[llvm] r327734 - [IR] Avoid the need to prefix MS C++ symbols with '\01'

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 16 13:13:32 PDT 2018


Author: rnk
Date: Fri Mar 16 13:13:32 2018
New Revision: 327734

URL: http://llvm.org/viewvc/llvm-project?rev=327734&view=rev
Log:
[IR] Avoid the need to prefix MS C++ symbols with '\01'

Now the Windows mangling modes ('w' and 'x') do not do any mangling for
symbols starting with '?'. This means that clang can stop adding the
hideous '\01' leading escape. This means LLVM debug logs are less likely
to contain ASCII escape characters and it will be easier to copy and
paste MS symbol names from IR.

Finally.

For non-Windows platforms, names starting with '?' still get IR
mangling, so once clang stops escaping MS C++ names, we will get extra
'_' prefixing on MachO. That's fine, since it is currently impossible to
construct a triple that uses the MS C++ ABI in clang and emits macho
object files.

Differential Revision: https://reviews.llvm.org/D7775

Added:
    llvm/trunk/test/CodeGen/X86/mangle-question-mark.ll
    llvm/trunk/unittests/IR/ManglerTest.cpp
Removed:
    llvm/trunk/test/MC/COFF/symbol-mangling.ll
Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/docs/ReleaseNotes.rst
    llvm/trunk/include/llvm/IR/DataLayout.h
    llvm/trunk/lib/IR/Mangler.cpp
    llvm/trunk/unittests/IR/CMakeLists.txt

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=327734&r1=327733&r2=327734&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Fri Mar 16 13:13:32 2018
@@ -1940,17 +1940,22 @@ as follows:
 ``a:<abi>:<pref>``
     This specifies the alignment for an object of aggregate type.
 ``m:<mangling>``
-    If present, specifies that llvm names are mangled in the output. The
+    If present, specifies that llvm names are mangled in the output. Symbols
+    prefixed with the mangling escape character ``\01`` are passed through
+    directly to the assembler without the escape character. The mangling style
     options are
 
     * ``e``: ELF mangling: Private symbols get a ``.L`` prefix.
     * ``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.
-    * ``x``: Windows x86 COFF prefix:  Similar to Windows COFF, but use a ``_``
-      prefix for ``__cdecl`` functions.
+    * ``x``: Windows x86 COFF mangling: Private symbols get the usual prefix.
+      Regular C symbols get a ``_`` prefix. Functions with ``__stdcall``,
+      ``__fastcall``, and ``__vectorcall`` have custom mangling that appends
+      ``@N`` where N is the number of bytes used to pass parameters. C++ symbols
+      starting with ``?`` are not mangled in any way.
+    * ``w``: Windows COFF mangling: Similar to ``x``, except that normal C
+      symbols do not receive a ``_`` prefix.
 ``n<size1>:<size2>:<size3>...``
     This specifies a set of native integer widths for the target CPU in
     bits. For example, it might contain ``n32`` for 32-bit PowerPC,

Modified: llvm/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ReleaseNotes.rst?rev=327734&r1=327733&r2=327734&view=diff
==============================================================================
--- llvm/trunk/docs/ReleaseNotes.rst (original)
+++ llvm/trunk/docs/ReleaseNotes.rst Fri Mar 16 13:13:32 2018
@@ -42,6 +42,9 @@ Non-comprehensive list of changes in thi
 
 * The LoopInstSimplify pass (-loop-instsimplify) has been removed.
 
+* Symbols starting with ``?`` are no longer mangled by LLVM when using the
+  Windows ``x`` or ``w`` IR mangling schemes.
+
 * Note..
 
 .. NOTE

Modified: llvm/trunk/include/llvm/IR/DataLayout.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DataLayout.h?rev=327734&r1=327733&r2=327734&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DataLayout.h (original)
+++ llvm/trunk/include/llvm/IR/DataLayout.h Fri Mar 16 13:13:32 2018
@@ -263,6 +263,12 @@ public:
     return ManglingMode == MM_WinCOFFX86;
   }
 
+  /// Returns true if symbols with leading question marks should not receive IR
+  /// mangling. True for Windows mangling modes.
+  bool doNotMangleLeadingQuestionMark() const {
+    return ManglingMode == MM_WinCOFF || ManglingMode == MM_WinCOFFX86;
+  }
+
   bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; }
 
   StringRef getLinkerPrivateGlobalPrefix() const {

Modified: llvm/trunk/lib/IR/Mangler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Mangler.cpp?rev=327734&r1=327733&r2=327734&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Mangler.cpp (original)
+++ llvm/trunk/lib/IR/Mangler.cpp Fri Mar 16 13:13:32 2018
@@ -44,6 +44,9 @@ static void getNameWithPrefixImpl(raw_os
     return;
   }
 
+  if (DL.doNotMangleLeadingQuestionMark() && Name[0] == '?')
+    Prefix = '\0';
+
   if (PrefixTy == Private)
     OS << DL.getPrivateGlobalPrefix();
   else if (PrefixTy == LinkerPrivate)
@@ -135,8 +138,13 @@ void Mangler::getNameWithPrefix(raw_ostr
   // Mangle functions with Microsoft calling conventions specially.  Only do
   // this mangling for x86_64 vectorcall and 32-bit x86.
   const Function *MSFunc = dyn_cast<Function>(GV);
-  if (Name.startswith("\01"))
-    MSFunc = nullptr; // Don't mangle when \01 is present.
+
+  // Don't add byte count suffixes when '\01' or '?' are in the first
+  // character.
+  if (Name.startswith("\01") ||
+      (DL.doNotMangleLeadingQuestionMark() && Name.startswith("?")))
+    MSFunc = nullptr;
+
   CallingConv::ID CC =
       MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C;
   if (!DL.hasMicrosoftFastStdCallMangling() &&

Added: llvm/trunk/test/CodeGen/X86/mangle-question-mark.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mangle-question-mark.ll?rev=327734&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/mangle-question-mark.ll (added)
+++ llvm/trunk/test/CodeGen/X86/mangle-question-mark.ll Fri Mar 16 13:13:32 2018
@@ -0,0 +1,60 @@
+; Test that symbols starting with '?' are not affected by IR mangling.
+
+; RUN: llc -mtriple i686-pc-win32 < %s | FileCheck %s --check-prefix=COFF
+; RUN: llc -mtriple x86_64-pc-win32 < %s | FileCheck %s --check-prefix=COFF64
+; 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 at A@@QBEXXZ"
+; COFF: calll "?withquestion at A@@QBEXXZ"
+; COFF: calll "L?privatequestion at A@@QBEXXZ"
+; COFF: calll "L?privatequestionfast at A@@QBEXXZ"
+; COFF: calll "?escapedprivate at A@@QBEXXZ"
+
+; COFF64: callq "?withescape at A@@QBEXXZ"
+; COFF64: callq "?withquestion at A@@QBEXXZ"
+; COFF64: callq ".L?privatequestion at A@@QBEXXZ"
+; COFF64: callq ".L?privatequestionfast at A@@QBEXXZ"
+; COFF64: callq "?escapedprivate at A@@QBEXXZ"
+
+; ELF: calll "?withescape at A@@QBEXXZ"
+; ELF: calll "?withquestion at A@@QBEXXZ"
+; ELF: calll ".L?privatequestion at A@@QBEXXZ"
+; ELF: calll ".L?privatequestionfast at A@@QBEXXZ"
+; ELF: calll "?escapedprivate at A@@QBEXXZ"
+
+; MACHO: calll "?withescape at A@@QBEXXZ"
+; MACHO: calll "_?withquestion at A@@QBEXXZ"
+; MACHO: calll "l_?privatequestion at A@@QBEXXZ"
+; MACHO: calll "l_?privatequestionfast at A@@QBEXXZ"
+; MACHO: calll "?escapedprivate at A@@QBEXXZ"
+
+%struct.A = type {}
+
+define i32 @main() {
+entry:
+  tail call void @"\01?withescape at A@@QBEXXZ"(%struct.A* null)
+  tail call void @"?withquestion at A@@QBEXXZ"(%struct.A* null)
+  tail call void @"?privatequestion at A@@QBEXXZ"(%struct.A* null)
+  tail call x86_fastcallcc void @"?privatequestionfast at A@@QBEXXZ"(%struct.A* null)
+  tail call void @"\01?escapedprivate at A@@QBEXXZ"(%struct.A* null)
+  ret i32 0
+}
+
+declare void @"\01?withescape at A@@QBEXXZ"(%struct.A*)
+declare void @"?withquestion at A@@QBEXXZ"(%struct.A*)
+
+define private void @"?privatequestion at A@@QBEXXZ"(%struct.A*) {
+  ret void
+}
+
+define private x86_fastcallcc void @"?privatequestionfast at A@@QBEXXZ"(%struct.A*) {
+  ret void
+}
+
+define private void @"\01?escapedprivate at A@@QBEXXZ"(%struct.A*) {
+  ret void
+}

Removed: llvm/trunk/test/MC/COFF/symbol-mangling.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/symbol-mangling.ll?rev=327733&view=auto
==============================================================================
--- llvm/trunk/test/MC/COFF/symbol-mangling.ll (original)
+++ llvm/trunk/test/MC/COFF/symbol-mangling.ll (removed)
@@ -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 at A@@QBEXXZ
-
-%struct.A = type {}
-
-define i32 @main() {
-entry:
-  tail call void @"\01?sayhi at A@@QBEXXZ"(%struct.A* null)
-  ret i32 0
-}
-
-declare void @"\01?sayhi at A@@QBEXXZ"(%struct.A*)

Modified: llvm/trunk/unittests/IR/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/CMakeLists.txt?rev=327734&r1=327733&r2=327734&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/CMakeLists.txt (original)
+++ llvm/trunk/unittests/IR/CMakeLists.txt Fri Mar 16 13:13:32 2018
@@ -25,6 +25,7 @@ set(IRSources
   IntrinsicsTest.cpp
   LegacyPassManagerTest.cpp
   MDBuilderTest.cpp
+  ManglerTest.cpp
   MetadataTest.cpp
   ModuleTest.cpp
   PassManagerTest.cpp

Added: llvm/trunk/unittests/IR/ManglerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/ManglerTest.cpp?rev=327734&view=auto
==============================================================================
--- llvm/trunk/unittests/IR/ManglerTest.cpp (added)
+++ llvm/trunk/unittests/IR/ManglerTest.cpp Fri Mar 16 13:13:32 2018
@@ -0,0 +1,140 @@
+//===- llvm/unittest/IR/ManglerTest.cpp - Mangler unit tests --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/Mangler.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Module.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+static std::string mangleStr(StringRef IRName, Mangler &Mang,
+                             const DataLayout &DL) {
+  std::string Mangled;
+  raw_string_ostream SS(Mangled);
+  Mang.getNameWithPrefix(SS, IRName, DL);
+  SS.flush();
+  return Mangled;
+}
+
+static std::string mangleFunc(StringRef IRName,
+                              GlobalValue::LinkageTypes Linkage,
+                              llvm::CallingConv::ID CC, Module &Mod,
+                              Mangler &Mang) {
+  Type *VoidTy = Type::getVoidTy(Mod.getContext());
+  Type *I32Ty = Type::getInt32Ty(Mod.getContext());
+  FunctionType *FTy =
+      FunctionType::get(VoidTy, {I32Ty, I32Ty, I32Ty}, /*isVarArg=*/false);
+  Function *F = Function::Create(FTy, Linkage, IRName, &Mod);
+  F->setCallingConv(CC);
+  std::string Mangled;
+  raw_string_ostream SS(Mangled);
+  Mang.getNameWithPrefix(SS, F, false);
+  SS.flush();
+  F->eraseFromParent();
+  return Mangled;
+}
+
+namespace {
+
+TEST(ManglerTest, MachO) {
+  LLVMContext Ctx;
+  DataLayout DL("m:o"); // macho
+  Module Mod("test", Ctx);
+  Mod.setDataLayout(DL);
+  Mangler Mang;
+  EXPECT_EQ(mangleStr("foo", Mang, DL), "_foo");
+  EXPECT_EQ(mangleStr("\01foo", Mang, DL), "foo");
+  EXPECT_EQ(mangleStr("?foo", Mang, DL), "_?foo");
+  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::C, Mod, Mang),
+            "_foo");
+  EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::C, Mod, Mang),
+            "_?foo");
+  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage,
+                       llvm::CallingConv::C, Mod, Mang),
+            "L_foo");
+}
+
+TEST(ManglerTest, WindowsX86) {
+  LLVMContext Ctx;
+  DataLayout DL("m:x-p:32:32"); // 32-bit windows
+  Module Mod("test", Ctx);
+  Mod.setDataLayout(DL);
+  Mangler Mang;
+  EXPECT_EQ(mangleStr("foo", Mang, DL), "_foo");
+  EXPECT_EQ(mangleStr("\01foo", Mang, DL), "foo");
+  EXPECT_EQ(mangleStr("?foo", Mang, DL), "?foo");
+  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::C, Mod, Mang),
+            "_foo");
+  EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::C, Mod, Mang),
+            "?foo");
+  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage,
+                       llvm::CallingConv::C, Mod, Mang),
+            "L_foo");
+
+  // Test calling conv mangling.
+  EXPECT_EQ(mangleFunc("stdcall", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::X86_StdCall, Mod, Mang),
+            "_stdcall at 12");
+  EXPECT_EQ(mangleFunc("fastcall", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::X86_FastCall, Mod, Mang),
+            "@fastcall at 12");
+  EXPECT_EQ(mangleFunc("vectorcall", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::X86_VectorCall, Mod, Mang),
+            "vectorcall@@12");
+
+  // Adding a '?' prefix blocks calling convention mangling.
+  EXPECT_EQ(mangleFunc("?fastcall", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::X86_FastCall, Mod, Mang),
+            "?fastcall");
+}
+
+TEST(ManglerTest, WindowsX64) {
+  LLVMContext Ctx;
+  DataLayout DL("m:w-p:64:64"); // windows
+  Module Mod("test", Ctx);
+  Mod.setDataLayout(DL);
+  Mangler Mang;
+  EXPECT_EQ(mangleStr("foo", Mang, DL), "foo");
+  EXPECT_EQ(mangleStr("\01foo", Mang, DL), "foo");
+  EXPECT_EQ(mangleStr("?foo", Mang, DL), "?foo");
+  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::C, Mod, Mang),
+            "foo");
+  EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::C, Mod, Mang),
+            "?foo");
+  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage,
+                       llvm::CallingConv::C, Mod, Mang),
+            ".Lfoo");
+
+  // Test calling conv mangling.
+  EXPECT_EQ(mangleFunc("stdcall", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::X86_StdCall, Mod, Mang),
+            "stdcall");
+  EXPECT_EQ(mangleFunc("fastcall", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::X86_FastCall, Mod, Mang),
+            "fastcall");
+  EXPECT_EQ(mangleFunc("vectorcall", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::X86_VectorCall, Mod, Mang),
+            "vectorcall@@24");
+
+  // Adding a '?' prefix blocks calling convention mangling.
+  EXPECT_EQ(mangleFunc("?vectorcall", llvm::GlobalValue::ExternalLinkage,
+                       llvm::CallingConv::X86_VectorCall, Mod, Mang),
+            "?vectorcall");
+}
+
+} // end anonymous namespace




More information about the llvm-commits mailing list