The current values for PrivateGlobalPrefix and PrivateLabelPrefix (@@ and @ respectively) are, in hindsight, poor choices for multiple reasons: First, there exist externally visible routines from the language environment that begin with @@. These functions are certainly not local/private by any means and they should not share a prefix with private globals. Secondly, both private globals and private labels should be handled the same way by GOFF, so it doesn't make much sense for them to have separate prefixes. GOFF remains the only file format where these are different and there is no reason for that to be the case
178 lines
6.5 KiB
C++
178 lines
6.5 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");
|
|
}
|
|
|
|
TEST(ManglerTest, GOFF) {
|
|
LLVMContext Ctx;
|
|
DataLayout DL("m:l"); // GOFF
|
|
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::PrivateLinkage,
|
|
llvm::CallingConv::C, Mod, Mang),
|
|
"L#foo");
|
|
}
|
|
|
|
} // end anonymous namespace
|