1 | //===- llvm/unittest/IR/ManglerTest.cpp - Mangler unit tests --------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
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" |
15 | |
16 | using namespace llvm; |
17 | |
18 | static std::string mangleStr(StringRef IRName, Mangler &Mang, |
19 | const DataLayout &DL) { |
20 | std::string Mangled; |
21 | raw_string_ostream SS(Mangled); |
22 | Mang.getNameWithPrefix(OS&: SS, GVName: IRName, DL); |
23 | SS.flush(); |
24 | return Mangled; |
25 | } |
26 | |
27 | static std::string mangleFunc(StringRef IRName, |
28 | GlobalValue::LinkageTypes Linkage, |
29 | llvm::CallingConv::ID CC, Module &Mod, |
30 | Mangler &Mang) { |
31 | Type *VoidTy = Type::getVoidTy(C&: Mod.getContext()); |
32 | Type *I32Ty = Type::getInt32Ty(C&: Mod.getContext()); |
33 | FunctionType *FTy = |
34 | FunctionType::get(Result: VoidTy, Params: {I32Ty, I32Ty, I32Ty}, /*isVarArg=*/false); |
35 | Function *F = Function::Create(Ty: FTy, Linkage, N: IRName, M: &Mod); |
36 | F->setCallingConv(CC); |
37 | std::string Mangled; |
38 | raw_string_ostream SS(Mangled); |
39 | Mang.getNameWithPrefix(OS&: SS, GV: F, CannotUsePrivateLabel: false); |
40 | SS.flush(); |
41 | F->eraseFromParent(); |
42 | return Mangled; |
43 | } |
44 | |
45 | namespace { |
46 | |
47 | TEST(ManglerTest, MachO) { |
48 | LLVMContext Ctx; |
49 | DataLayout DL("m:o" ); // macho |
50 | Module Mod("test" , Ctx); |
51 | Mod.setDataLayout(DL); |
52 | Mangler Mang; |
53 | EXPECT_EQ(mangleStr("foo" , Mang, DL), "_foo" ); |
54 | EXPECT_EQ(mangleStr("\01foo" , Mang, DL), "foo" ); |
55 | EXPECT_EQ(mangleStr("?foo" , Mang, DL), "_?foo" ); |
56 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::ExternalLinkage, |
57 | llvm::CallingConv::C, Mod, Mang), |
58 | "_foo" ); |
59 | EXPECT_EQ(mangleFunc("?foo" , llvm::GlobalValue::ExternalLinkage, |
60 | llvm::CallingConv::C, Mod, Mang), |
61 | "_?foo" ); |
62 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::PrivateLinkage, |
63 | llvm::CallingConv::C, Mod, Mang), |
64 | "L_foo" ); |
65 | } |
66 | |
67 | TEST(ManglerTest, WindowsX86) { |
68 | LLVMContext Ctx; |
69 | DataLayout DL("m:x-p:32:32" ); // 32-bit windows |
70 | Module Mod("test" , Ctx); |
71 | Mod.setDataLayout(DL); |
72 | Mangler Mang; |
73 | EXPECT_EQ(mangleStr("foo" , Mang, DL), "_foo" ); |
74 | EXPECT_EQ(mangleStr("\01foo" , Mang, DL), "foo" ); |
75 | EXPECT_EQ(mangleStr("?foo" , Mang, DL), "?foo" ); |
76 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::ExternalLinkage, |
77 | llvm::CallingConv::C, Mod, Mang), |
78 | "_foo" ); |
79 | EXPECT_EQ(mangleFunc("?foo" , llvm::GlobalValue::ExternalLinkage, |
80 | llvm::CallingConv::C, Mod, Mang), |
81 | "?foo" ); |
82 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::PrivateLinkage, |
83 | llvm::CallingConv::C, Mod, Mang), |
84 | "L_foo" ); |
85 | |
86 | // Test calling conv mangling. |
87 | EXPECT_EQ(mangleFunc("stdcall" , llvm::GlobalValue::ExternalLinkage, |
88 | llvm::CallingConv::X86_StdCall, Mod, Mang), |
89 | "_stdcall@12" ); |
90 | EXPECT_EQ(mangleFunc("fastcall" , llvm::GlobalValue::ExternalLinkage, |
91 | llvm::CallingConv::X86_FastCall, Mod, Mang), |
92 | "@fastcall@12" ); |
93 | EXPECT_EQ(mangleFunc("vectorcall" , llvm::GlobalValue::ExternalLinkage, |
94 | llvm::CallingConv::X86_VectorCall, Mod, Mang), |
95 | "vectorcall@@12" ); |
96 | |
97 | // Adding a '?' prefix blocks calling convention mangling. |
98 | EXPECT_EQ(mangleFunc("?fastcall" , llvm::GlobalValue::ExternalLinkage, |
99 | llvm::CallingConv::X86_FastCall, Mod, Mang), |
100 | "?fastcall" ); |
101 | } |
102 | |
103 | TEST(ManglerTest, WindowsX64) { |
104 | LLVMContext Ctx; |
105 | DataLayout DL("m:w-p:64:64" ); // windows |
106 | Module Mod("test" , Ctx); |
107 | Mod.setDataLayout(DL); |
108 | Mangler Mang; |
109 | EXPECT_EQ(mangleStr("foo" , Mang, DL), "foo" ); |
110 | EXPECT_EQ(mangleStr("\01foo" , Mang, DL), "foo" ); |
111 | EXPECT_EQ(mangleStr("?foo" , Mang, DL), "?foo" ); |
112 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::ExternalLinkage, |
113 | llvm::CallingConv::C, Mod, Mang), |
114 | "foo" ); |
115 | EXPECT_EQ(mangleFunc("?foo" , llvm::GlobalValue::ExternalLinkage, |
116 | llvm::CallingConv::C, Mod, Mang), |
117 | "?foo" ); |
118 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::PrivateLinkage, |
119 | llvm::CallingConv::C, Mod, Mang), |
120 | ".Lfoo" ); |
121 | |
122 | // Test calling conv mangling. |
123 | EXPECT_EQ(mangleFunc("stdcall" , llvm::GlobalValue::ExternalLinkage, |
124 | llvm::CallingConv::X86_StdCall, Mod, Mang), |
125 | "stdcall" ); |
126 | EXPECT_EQ(mangleFunc("fastcall" , llvm::GlobalValue::ExternalLinkage, |
127 | llvm::CallingConv::X86_FastCall, Mod, Mang), |
128 | "fastcall" ); |
129 | EXPECT_EQ(mangleFunc("vectorcall" , llvm::GlobalValue::ExternalLinkage, |
130 | llvm::CallingConv::X86_VectorCall, Mod, Mang), |
131 | "vectorcall@@24" ); |
132 | |
133 | // Adding a '?' prefix blocks calling convention mangling. |
134 | EXPECT_EQ(mangleFunc("?vectorcall" , llvm::GlobalValue::ExternalLinkage, |
135 | llvm::CallingConv::X86_VectorCall, Mod, Mang), |
136 | "?vectorcall" ); |
137 | } |
138 | |
139 | TEST(ManglerTest, XCOFF) { |
140 | LLVMContext Ctx; |
141 | DataLayout DL("m:a" ); // XCOFF/AIX |
142 | Module Mod("test" , Ctx); |
143 | Mod.setDataLayout(DL); |
144 | Mangler Mang; |
145 | EXPECT_EQ(mangleStr("foo" , Mang, DL), "foo" ); |
146 | EXPECT_EQ(mangleStr("\01foo" , Mang, DL), "foo" ); |
147 | EXPECT_EQ(mangleStr("?foo" , Mang, DL), "?foo" ); |
148 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::ExternalLinkage, |
149 | llvm::CallingConv::C, Mod, Mang), |
150 | "foo" ); |
151 | EXPECT_EQ(mangleFunc("?foo" , llvm::GlobalValue::ExternalLinkage, |
152 | llvm::CallingConv::C, Mod, Mang), |
153 | "?foo" ); |
154 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::PrivateLinkage, |
155 | llvm::CallingConv::C, Mod, Mang), |
156 | "L..foo" ); |
157 | } |
158 | |
159 | TEST(ManglerTest, GOFF) { |
160 | LLVMContext Ctx; |
161 | DataLayout DL("m:l" ); // GOFF |
162 | Module Mod("test" , Ctx); |
163 | Mod.setDataLayout(DL); |
164 | Mangler Mang; |
165 | |
166 | EXPECT_EQ(mangleStr("foo" , Mang, DL), "foo" ); |
167 | EXPECT_EQ(mangleStr("\01foo" , Mang, DL), "foo" ); |
168 | EXPECT_EQ(mangleStr("?foo" , Mang, DL), "?foo" ); |
169 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::ExternalLinkage, |
170 | llvm::CallingConv::C, Mod, Mang), |
171 | "foo" ); |
172 | EXPECT_EQ(mangleFunc("foo" , llvm::GlobalValue::PrivateLinkage, |
173 | llvm::CallingConv::C, Mod, Mang), |
174 | "L#foo" ); |
175 | } |
176 | |
177 | } // end anonymous namespace |
178 | |