160 lines
5.9 KiB
C++
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
|