1 //===- llvm/unittest/IR/ManglerTest.cpp - Mangler unit tests --------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/Mangler.h"
10 #include "llvm/IR/CallingConv.h"
11 #include "llvm/IR/DataLayout.h"
12 #include "llvm/IR/GlobalValue.h"
13 #include "llvm/IR/Module.h"
14 #include "gtest/gtest.h"
18 static std::string
mangleStr(StringRef IRName
, Mangler
&Mang
,
19 const DataLayout
&DL
) {
21 raw_string_ostream
SS(Mangled
);
22 Mang
.getNameWithPrefix(SS
, IRName
, DL
);
26 static std::string
mangleFunc(StringRef IRName
,
27 GlobalValue::LinkageTypes Linkage
,
28 llvm::CallingConv::ID CC
, Module
&Mod
,
30 Type
*VoidTy
= Type::getVoidTy(Mod
.getContext());
31 Type
*I32Ty
= Type::getInt32Ty(Mod
.getContext());
33 FunctionType::get(VoidTy
, {I32Ty
, I32Ty
, I32Ty
}, /*isVarArg=*/false);
34 Function
*F
= Function::Create(FTy
, Linkage
, IRName
, &Mod
);
35 F
->setCallingConv(CC
);
37 raw_string_ostream
SS(Mangled
);
38 Mang
.getNameWithPrefix(SS
, F
, false);
45 TEST(ManglerTest
, MachO
) {
47 DataLayout
DL("m:o"); // macho
48 Module
Mod("test", Ctx
);
49 Mod
.setDataLayout(DL
);
51 EXPECT_EQ(mangleStr("foo", Mang
, DL
), "_foo");
52 EXPECT_EQ(mangleStr("\01foo", Mang
, DL
), "foo");
53 EXPECT_EQ(mangleStr("?foo", Mang
, DL
), "_?foo");
54 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage
,
55 llvm::CallingConv::C
, Mod
, Mang
),
57 EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage
,
58 llvm::CallingConv::C
, Mod
, Mang
),
60 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage
,
61 llvm::CallingConv::C
, Mod
, Mang
),
65 TEST(ManglerTest
, WindowsX86
) {
67 DataLayout
DL("m:x-p:32:32"); // 32-bit windows
68 Module
Mod("test", Ctx
);
69 Mod
.setDataLayout(DL
);
71 EXPECT_EQ(mangleStr("foo", Mang
, DL
), "_foo");
72 EXPECT_EQ(mangleStr("\01foo", Mang
, DL
), "foo");
73 EXPECT_EQ(mangleStr("?foo", Mang
, DL
), "?foo");
74 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage
,
75 llvm::CallingConv::C
, Mod
, Mang
),
77 EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage
,
78 llvm::CallingConv::C
, Mod
, Mang
),
80 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage
,
81 llvm::CallingConv::C
, Mod
, Mang
),
84 // Test calling conv mangling.
85 EXPECT_EQ(mangleFunc("stdcall", llvm::GlobalValue::ExternalLinkage
,
86 llvm::CallingConv::X86_StdCall
, Mod
, Mang
),
88 EXPECT_EQ(mangleFunc("fastcall", llvm::GlobalValue::ExternalLinkage
,
89 llvm::CallingConv::X86_FastCall
, Mod
, Mang
),
91 EXPECT_EQ(mangleFunc("vectorcall", llvm::GlobalValue::ExternalLinkage
,
92 llvm::CallingConv::X86_VectorCall
, Mod
, Mang
),
95 // Adding a '?' prefix blocks calling convention mangling.
96 EXPECT_EQ(mangleFunc("?fastcall", llvm::GlobalValue::ExternalLinkage
,
97 llvm::CallingConv::X86_FastCall
, Mod
, Mang
),
101 TEST(ManglerTest
, WindowsX64
) {
103 DataLayout
DL("m:w-p:64:64"); // windows
104 Module
Mod("test", Ctx
);
105 Mod
.setDataLayout(DL
);
107 EXPECT_EQ(mangleStr("foo", Mang
, DL
), "foo");
108 EXPECT_EQ(mangleStr("\01foo", Mang
, DL
), "foo");
109 EXPECT_EQ(mangleStr("?foo", Mang
, DL
), "?foo");
110 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage
,
111 llvm::CallingConv::C
, Mod
, Mang
),
113 EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage
,
114 llvm::CallingConv::C
, Mod
, Mang
),
116 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage
,
117 llvm::CallingConv::C
, Mod
, Mang
),
120 // Test calling conv mangling.
121 EXPECT_EQ(mangleFunc("stdcall", llvm::GlobalValue::ExternalLinkage
,
122 llvm::CallingConv::X86_StdCall
, Mod
, Mang
),
124 EXPECT_EQ(mangleFunc("fastcall", llvm::GlobalValue::ExternalLinkage
,
125 llvm::CallingConv::X86_FastCall
, Mod
, Mang
),
127 EXPECT_EQ(mangleFunc("vectorcall", llvm::GlobalValue::ExternalLinkage
,
128 llvm::CallingConv::X86_VectorCall
, Mod
, Mang
),
131 // Adding a '?' prefix blocks calling convention mangling.
132 EXPECT_EQ(mangleFunc("?vectorcall", llvm::GlobalValue::ExternalLinkage
,
133 llvm::CallingConv::X86_VectorCall
, Mod
, Mang
),
137 TEST(ManglerTest
, XCOFF
) {
139 DataLayout
DL("m:a"); // XCOFF/AIX
140 Module
Mod("test", Ctx
);
141 Mod
.setDataLayout(DL
);
143 EXPECT_EQ(mangleStr("foo", Mang
, DL
), "foo");
144 EXPECT_EQ(mangleStr("\01foo", Mang
, DL
), "foo");
145 EXPECT_EQ(mangleStr("?foo", Mang
, DL
), "?foo");
146 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage
,
147 llvm::CallingConv::C
, Mod
, Mang
),
149 EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage
,
150 llvm::CallingConv::C
, Mod
, Mang
),
152 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage
,
153 llvm::CallingConv::C
, Mod
, Mang
),
157 TEST(ManglerTest
, GOFF
) {
159 DataLayout
DL("m:l"); // GOFF
160 Module
Mod("test", Ctx
);
161 Mod
.setDataLayout(DL
);
164 EXPECT_EQ(mangleStr("foo", Mang
, DL
), "foo");
165 EXPECT_EQ(mangleStr("\01foo", Mang
, DL
), "foo");
166 EXPECT_EQ(mangleStr("?foo", Mang
, DL
), "?foo");
167 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage
,
168 llvm::CallingConv::C
, Mod
, Mang
),
170 EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage
,
171 llvm::CallingConv::C
, Mod
, Mang
),
175 TEST(ManglerTest
, Arm64EC
) {
176 constexpr std::string_view Arm64ECNames
[] = {
183 // Regression test: https://github.com/llvm/llvm-project/issues/115231
184 "?GetValue@?$Wrapper@UA@@@@$$hQEBAHXZ",
188 // namespace A::B::C::D {
190 // virtual int f() { return 0; }
193 // struct Derived : public A::B::C::D::Base {
194 // virtual int f() override { return 1; }
196 // A::B::C::D::Base* MakeObj() { return new Derived(); }
198 // void * __cdecl operator new(unsigned __int64)
200 // public: virtual int __cdecl A::B::C::D::Base::f(void)
201 "?f@Base@D@C@B@A@@$$hUEAAHXZ",
202 // public: __cdecl A::B::C::D::Base::Base(void)
203 "??0Base@D@C@B@A@@$$hQEAA@XZ",
204 // public: virtual int __cdecl Derived::f(void)
205 "?f@Derived@@$$hUEAAHXZ",
206 // public: __cdecl Derived::Derived(void)
207 "??0Derived@@$$hQEAA@XZ",
208 // struct A::B::C::D::Base * __cdecl MakeObj(void)
209 "?MakeObj@@$$hYAPEAUBase@D@C@B@A@@XZ",
213 // template <typename T> struct WW { struct Z{}; };
214 // template <typename X> struct Wrapper {
215 // int GetValue(typename WW<X>::Z) const;
218 // template <typename X> int Wrapper<X>::GetValue(typename WW<X>::Z) const
220 // template class Wrapper<A>;
222 // public: int __cdecl Wrapper<struct A>::GetValue(struct WW<struct
224 "?GetValue@?$Wrapper@UA@@@@$$hQEBAHUZ@?$WW@UA@@@@@Z",
227 for (const auto &Arm64ECName
: Arm64ECNames
) {
228 // Check that this is a mangled name.
229 EXPECT_TRUE(isArm64ECMangledFunctionName(Arm64ECName
))
230 << "Test case: " << Arm64ECName
;
231 // Refuse to mangle it again.
232 EXPECT_FALSE(getArm64ECMangledFunctionName(Arm64ECName
).has_value())
233 << "Test case: " << Arm64ECName
;
236 auto Arm64Name
= getArm64ECDemangledFunctionName(Arm64ECName
);
237 EXPECT_TRUE(Arm64Name
.has_value()) << "Test case: " << Arm64ECName
;
238 // Check that it is not mangled.
239 EXPECT_FALSE(isArm64ECMangledFunctionName(Arm64Name
.value()))
240 << "Test case: " << Arm64ECName
;
241 // Refuse to demangle it again.
242 EXPECT_FALSE(getArm64ECDemangledFunctionName(Arm64Name
.value()).has_value())
243 << "Test case: " << Arm64ECName
;
246 auto RoundTripArm64ECName
=
247 getArm64ECMangledFunctionName(Arm64Name
.value());
248 EXPECT_EQ(RoundTripArm64ECName
, Arm64ECName
);
252 } // end anonymous namespace