| //===- llvm/unittest/IR/ManglerTest.cpp - Mangler unit tests --------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #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"); |
| } |
| |
| TEST(ManglerTest, XCOFF) { |
| LLVMContext Ctx; |
| DataLayout DL("m:a"); // XCOFF/AIX |
| 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"); |
| } |
| |
| } // end anonymous namespace |