brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.0 KiB · bb0b3ed Raw
277 lines · cpp
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-exception6//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 16using namespace llvm;17 18static 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  return Mangled;24}25 26static std::string mangleFunc(StringRef IRName,27                              GlobalValue::LinkageTypes Linkage,28                              llvm::CallingConv::ID CC, Module &Mod,29                              Mangler &Mang) {30  Type *VoidTy = Type::getVoidTy(Mod.getContext());31  Type *I32Ty = Type::getInt32Ty(Mod.getContext());32  FunctionType *FTy =33      FunctionType::get(VoidTy, {I32Ty, I32Ty, I32Ty}, /*isVarArg=*/false);34  Function *F = Function::Create(FTy, Linkage, IRName, &Mod);35  F->setCallingConv(CC);36  std::string Mangled;37  raw_string_ostream SS(Mangled);38  Mang.getNameWithPrefix(SS, F, false);39  F->eraseFromParent();40  return Mangled;41}42 43namespace {44 45TEST(ManglerTest, MachO) {46  LLVMContext Ctx;47  DataLayout DL("m:o"); // macho48  Module Mod("test", Ctx);49  Mod.setDataLayout(DL);50  Mangler Mang;51  EXPECT_EQ(mangleStr("foo", Mang, DL), "_foo");52  EXPECT_EQ(mangleStr("\01foo", Mang, DL), "foo");53  EXPECT_EQ(mangleStr("?foo", Mang, DL), "_?foo");54  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage,55                       llvm::CallingConv::C, Mod, Mang),56            "_foo");57  EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage,58                       llvm::CallingConv::C, Mod, Mang),59            "_?foo");60  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage,61                       llvm::CallingConv::C, Mod, Mang),62            "L_foo");63}64 65TEST(ManglerTest, WindowsX86) {66  LLVMContext Ctx;67  DataLayout DL("m:x-p:32:32"); // 32-bit windows68  Module Mod("test", Ctx);69  Mod.setDataLayout(DL);70  Mangler Mang;71  EXPECT_EQ(mangleStr("foo", Mang, DL), "_foo");72  EXPECT_EQ(mangleStr("\01foo", Mang, DL), "foo");73  EXPECT_EQ(mangleStr("?foo", Mang, DL), "?foo");74  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage,75                       llvm::CallingConv::C, Mod, Mang),76            "_foo");77  EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage,78                       llvm::CallingConv::C, Mod, Mang),79            "?foo");80  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage,81                       llvm::CallingConv::C, Mod, Mang),82            "L_foo");83 84  // Test calling conv mangling.85  EXPECT_EQ(mangleFunc("stdcall", llvm::GlobalValue::ExternalLinkage,86                       llvm::CallingConv::X86_StdCall, Mod, Mang),87            "_stdcall@12");88  EXPECT_EQ(mangleFunc("fastcall", llvm::GlobalValue::ExternalLinkage,89                       llvm::CallingConv::X86_FastCall, Mod, Mang),90            "@fastcall@12");91  EXPECT_EQ(mangleFunc("vectorcall", llvm::GlobalValue::ExternalLinkage,92                       llvm::CallingConv::X86_VectorCall, Mod, Mang),93            "vectorcall@@12");94 95  // Adding a '?' prefix blocks calling convention mangling.96  EXPECT_EQ(mangleFunc("?fastcall", llvm::GlobalValue::ExternalLinkage,97                       llvm::CallingConv::X86_FastCall, Mod, Mang),98            "?fastcall");99}100 101TEST(ManglerTest, WindowsX64) {102  LLVMContext Ctx;103  DataLayout DL("m:w-p:64:64"); // windows104  Module Mod("test", Ctx);105  Mod.setDataLayout(DL);106  Mangler Mang;107  EXPECT_EQ(mangleStr("foo", Mang, DL), "foo");108  EXPECT_EQ(mangleStr("\01foo", Mang, DL), "foo");109  EXPECT_EQ(mangleStr("?foo", Mang, DL), "?foo");110  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage,111                       llvm::CallingConv::C, Mod, Mang),112            "foo");113  EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage,114                       llvm::CallingConv::C, Mod, Mang),115            "?foo");116  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage,117                       llvm::CallingConv::C, Mod, Mang),118            ".Lfoo");119 120  // Test calling conv mangling.121  EXPECT_EQ(mangleFunc("stdcall", llvm::GlobalValue::ExternalLinkage,122                       llvm::CallingConv::X86_StdCall, Mod, Mang),123            "stdcall");124  EXPECT_EQ(mangleFunc("fastcall", llvm::GlobalValue::ExternalLinkage,125                       llvm::CallingConv::X86_FastCall, Mod, Mang),126            "fastcall");127  EXPECT_EQ(mangleFunc("vectorcall", llvm::GlobalValue::ExternalLinkage,128                       llvm::CallingConv::X86_VectorCall, Mod, Mang),129            "vectorcall@@24");130 131  // Adding a '?' prefix blocks calling convention mangling.132  EXPECT_EQ(mangleFunc("?vectorcall", llvm::GlobalValue::ExternalLinkage,133                       llvm::CallingConv::X86_VectorCall, Mod, Mang),134            "?vectorcall");135}136 137TEST(ManglerTest, UEFIX64) {138  LLVMContext Ctx;139  DataLayout DL("e-m:w-p270:32:32-p271:32:32-p272:64:64-"140                "i64:64-i128:128-f80:128-n8:16:32:64-S128"); // uefi X86_64141  Module Mod("test", Ctx);142  Mod.setDataLayout(DL);143  Mangler Mang;144  EXPECT_EQ(mangleStr("foo", Mang, DL), "foo");145  EXPECT_EQ(mangleStr("\01foo", Mang, DL), "foo");146  EXPECT_EQ(mangleStr("?foo", Mang, DL), "?foo");147  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage,148                       llvm::CallingConv::C, Mod, Mang),149            "foo");150  EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage,151                       llvm::CallingConv::C, Mod, Mang),152            "?foo");153  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage,154                       llvm::CallingConv::C, Mod, Mang),155            ".Lfoo");156}157 158TEST(ManglerTest, XCOFF) {159  LLVMContext Ctx;160  DataLayout DL("m:a"); // XCOFF/AIX161  Module Mod("test", Ctx);162  Mod.setDataLayout(DL);163  Mangler Mang;164  EXPECT_EQ(mangleStr("foo", Mang, DL), "foo");165  EXPECT_EQ(mangleStr("\01foo", Mang, DL), "foo");166  EXPECT_EQ(mangleStr("?foo", Mang, DL), "?foo");167  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage,168                       llvm::CallingConv::C, Mod, Mang),169            "foo");170  EXPECT_EQ(mangleFunc("?foo", llvm::GlobalValue::ExternalLinkage,171                       llvm::CallingConv::C, Mod, Mang),172            "?foo");173  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage,174                       llvm::CallingConv::C, Mod, Mang),175            "L..foo");176}177 178TEST(ManglerTest, GOFF) {179  LLVMContext Ctx;180  DataLayout DL("m:l"); // GOFF181  Module Mod("test", Ctx);182  Mod.setDataLayout(DL);183  Mangler Mang;184 185  EXPECT_EQ(mangleStr("foo", Mang, DL), "foo");186  EXPECT_EQ(mangleStr("\01foo", Mang, DL), "foo");187  EXPECT_EQ(mangleStr("?foo", Mang, DL), "?foo");188  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::ExternalLinkage,189                       llvm::CallingConv::C, Mod, Mang),190            "foo");191  EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage,192                       llvm::CallingConv::C, Mod, Mang),193            "L#foo");194}195 196TEST(ManglerTest, Arm64EC) {197  constexpr std::string_view Arm64ECNames[] = {198      // Basic C name.199      "#Foo",200 201      // Basic C++ name.202      "?foo@@$$hYAHXZ",203 204      // Regression test: https://github.com/llvm/llvm-project/issues/115231205      "?GetValue@?$Wrapper@UA@@@@$$hQEBAHXZ",206 207      // Symbols from:208      // ```209      // namespace A::B::C::D {210      // struct Base {211      //   virtual int f() { return 0; }212      // };213      // }214      // struct Derived : public A::B::C::D::Base {215      //   virtual int f() override { return 1; }216      // };217      // A::B::C::D::Base* MakeObj() { return new Derived(); }218      // ```219      // void * __cdecl operator new(unsigned __int64)220      "??2@$$hYAPEAX_K@Z",221      // public: virtual int __cdecl A::B::C::D::Base::f(void)222      "?f@Base@D@C@B@A@@$$hUEAAHXZ",223      // public: __cdecl A::B::C::D::Base::Base(void)224      "??0Base@D@C@B@A@@$$hQEAA@XZ",225      // public: virtual int __cdecl Derived::f(void)226      "?f@Derived@@$$hUEAAHXZ",227      // public: __cdecl Derived::Derived(void)228      "??0Derived@@$$hQEAA@XZ",229      // struct A::B::C::D::Base * __cdecl MakeObj(void)230      "?MakeObj@@$$hYAPEAUBase@D@C@B@A@@XZ",231 232      // Symbols from:233      // ```234      // template <typename T> struct WW { struct Z{}; };235      // template <typename X> struct Wrapper {236      //   int GetValue(typename WW<X>::Z) const;237      // };238      // struct A { };239      // template <typename X> int Wrapper<X>::GetValue(typename WW<X>::Z) const240      // { return 3; }241      // template class Wrapper<A>;242      // ```243      // public: int __cdecl Wrapper<struct A>::GetValue(struct WW<struct244      // A>::Z)const245      "?GetValue@?$Wrapper@UA@@@@$$hQEBAHUZ@?$WW@UA@@@@@Z",246 247      // MD5 symbol248      "??@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@$$h@",249  };250 251  for (const auto &Arm64ECName : Arm64ECNames) {252    // Check that this is a mangled name.253    EXPECT_TRUE(isArm64ECMangledFunctionName(Arm64ECName))254        << "Test case: " << Arm64ECName;255    // Refuse to mangle it again.256    EXPECT_FALSE(getArm64ECMangledFunctionName(Arm64ECName).has_value())257        << "Test case: " << Arm64ECName;258 259    // Demangle.260    auto Arm64Name = getArm64ECDemangledFunctionName(Arm64ECName);261    EXPECT_TRUE(Arm64Name.has_value()) << "Test case: " << Arm64ECName;262    // Check that it is not mangled.263    EXPECT_FALSE(isArm64ECMangledFunctionName(Arm64Name.value()))264        << "Test case: " << Arm64ECName;265    // Refuse to demangle it again.266    EXPECT_FALSE(getArm64ECDemangledFunctionName(Arm64Name.value()).has_value())267        << "Test case: " << Arm64ECName;268 269    // Round-trip.270    auto RoundTripArm64ECName =271        getArm64ECMangledFunctionName(Arm64Name.value());272    EXPECT_EQ(RoundTripArm64ECName, Arm64ECName);273  }274}275 276} // end anonymous namespace277