llvm-project/llvm/unittests/IR/ManglerTest.cpp

160 lines
5.9 KiB
C++

//===- 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