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(SS, 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(Mod.getContext()); 32 Type *I32Ty = Type::getInt32Ty(Mod.getContext()); 33 FunctionType *FTy = 34 FunctionType::get(VoidTy, {I32Ty, I32Ty, I32Ty}, /*isVarArg=*/false); 35 Function *F = Function::Create(FTy, Linkage, IRName, &Mod); 36 F->setCallingConv(CC); 37 std::string Mangled; 38 raw_string_ostream SS(Mangled); 39 Mang.getNameWithPrefix(SS, F, 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 "@foo"); 175 } 176 177 } // end anonymous namespace 178