``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,
--- /dev/null
+; 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@A@@QBEXXZ"
+; COFF: calll "?withquestion@A@@QBEXXZ"
+; COFF: calll "L?privatequestion@A@@QBEXXZ"
+; COFF: calll "L?privatequestionfast@A@@QBEXXZ"
+; COFF: calll "?escapedprivate@A@@QBEXXZ"
+
+; COFF64: callq "?withescape@A@@QBEXXZ"
+; COFF64: callq "?withquestion@A@@QBEXXZ"
+; COFF64: callq ".L?privatequestion@A@@QBEXXZ"
+; COFF64: callq ".L?privatequestionfast@A@@QBEXXZ"
+; COFF64: callq "?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"
+
+; MACHO: calll "?withescape@A@@QBEXXZ"
+; MACHO: calll "_?withquestion@A@@QBEXXZ"
+; MACHO: calll "l_?privatequestion@A@@QBEXXZ"
+; MACHO: calll "l_?privatequestionfast@A@@QBEXXZ"
+; MACHO: calll "?escapedprivate@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
+}
--- /dev/null
+//===- 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@12");
+ EXPECT_EQ(mangleFunc("fastcall", llvm::GlobalValue::ExternalLinkage,
+ llvm::CallingConv::X86_FastCall, Mod, Mang),
+ "@fastcall@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