brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.0 KiB · 30eda73 Raw
437 lines · cpp
1//===- unittests/IR/ModuleTest.cpp - Module 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/Module.h"10#include "llvm/AsmParser/Parser.h"11#include "llvm/IR/Constants.h"12#include "llvm/IR/GlobalVariable.h"13#include "llvm/IR/ModuleSummaryIndex.h"14#include "llvm/Pass.h"15#include "llvm/Support/RandomNumberGenerator.h"16#include "llvm/Support/SourceMgr.h"17#include "llvm/Support/raw_ostream.h"18#include "gtest/gtest.h"19 20#include <random>21 22using namespace llvm;23 24namespace {25 26bool sortByName(const GlobalVariable &L, const GlobalVariable &R) {27  return L.getName() < R.getName();28}29 30bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) {31  return sortByName(R, L);32}33 34TEST(ModuleTest, sortGlobalsByName) {35  LLVMContext Context;36  for (auto compare : {&sortByName, &sortByNameReverse}) {37    Module M("M", Context);38    Type *T = Type::getInt8Ty(Context);39    GlobalValue::LinkageTypes L = GlobalValue::ExternalLinkage;40    (void)new GlobalVariable(M, T, false, L, nullptr, "A");41    (void)new GlobalVariable(M, T, false, L, nullptr, "F");42    (void)new GlobalVariable(M, T, false, L, nullptr, "G");43    (void)new GlobalVariable(M, T, false, L, nullptr, "E");44    (void)new GlobalVariable(M, T, false, L, nullptr, "B");45    (void)new GlobalVariable(M, T, false, L, nullptr, "H");46    (void)new GlobalVariable(M, T, false, L, nullptr, "C");47    (void)new GlobalVariable(M, T, false, L, nullptr, "D");48 49    // Sort the globals by name.50    EXPECT_FALSE(std::is_sorted(M.global_begin(), M.global_end(), compare));51  }52}53 54TEST(ModuleTest, randomNumberGenerator) {55  LLVMContext Context;56  static char ID;57  struct DummyPass : ModulePass {58    DummyPass() : ModulePass(ID) {}59    bool runOnModule(Module &) override { return true; }60  } DP;61 62  Module M("R", Context);63 64  std::uniform_int_distribution<int> dist;65  const size_t NBCheck = 10;66 67  std::array<int, NBCheck> RandomStreams[2];68  for (auto &RandomStream : RandomStreams) {69    std::unique_ptr<RandomNumberGenerator> RNG = M.createRNG(DP.getPassName());70    std::generate(RandomStream.begin(), RandomStream.end(),71                  [&]() { return dist(*RNG); });72  }73 74  EXPECT_TRUE(std::equal(RandomStreams[0].begin(), RandomStreams[0].end(),75                         RandomStreams[1].begin()));76}77 78TEST(ModuleTest, setModuleFlag) {79  LLVMContext Context;80  Module M("M", Context);81  StringRef Key = "Key";82  Metadata *Val1 = MDString::get(Context, "Val1");83  Metadata *Val2 = MDString::get(Context, "Val2");84  EXPECT_EQ(nullptr, M.getModuleFlag(Key));85  M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);86  EXPECT_EQ(Val1, M.getModuleFlag(Key));87  M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val2);88  EXPECT_EQ(Val2, M.getModuleFlag(Key));89}90 91TEST(ModuleTest, setModuleFlagInt) {92  LLVMContext Context;93  Module M("M", Context);94  StringRef Key = "Key";95  uint32_t Val1 = 1;96  uint32_t Val2 = 2;97  EXPECT_EQ(nullptr, M.getModuleFlag(Key));98  M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);99  auto A1 = mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(Key));100  EXPECT_EQ(Val1, A1->getZExtValue());101  M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val2);102  auto A2 = mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(Key));103  EXPECT_EQ(Val2, A2->getZExtValue());104}105 106TEST(ModuleTest, setModuleFlagTwoMod) {107  LLVMContext Context;108  Module MA("MA", Context);109  Module MB("MB", Context);110  StringRef Key = "Key";111  uint32_t Val1 = 1;112  uint32_t Val2 = 2;113 114  // Set a flag to MA115  EXPECT_EQ(nullptr, MA.getModuleFlag(Key));116  MA.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);117  auto A1 = mdconst::extract_or_null<ConstantInt>(MA.getModuleFlag(Key));118  EXPECT_EQ(Val1, A1->getZExtValue());119 120  // Set a flag to MB121  EXPECT_EQ(nullptr, MB.getModuleFlag(Key));122  MB.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);123  auto B1 = mdconst::extract_or_null<ConstantInt>(MB.getModuleFlag(Key));124  EXPECT_EQ(Val1, B1->getZExtValue());125 126  // Change the flag of MA127  MA.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val2);128  auto A2 = mdconst::extract_or_null<ConstantInt>(MA.getModuleFlag(Key));129  EXPECT_EQ(Val2, A2->getZExtValue());130 131  // MB should keep the original flag value132  auto B2 = mdconst::extract_or_null<ConstantInt>(MB.getModuleFlag(Key));133  EXPECT_EQ(Val1, B2->getZExtValue());134}135 136const char *IRString = R"IR(137  !llvm.module.flags = !{!0}138 139  !0 = !{i32 1, !"ProfileSummary", !1}140  !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}141  !2 = !{!"ProfileFormat", !"SampleProfile"}142  !3 = !{!"TotalCount", i64 10000}143  !4 = !{!"MaxCount", i64 10}144  !5 = !{!"MaxInternalCount", i64 1}145  !6 = !{!"MaxFunctionCount", i64 1000}146  !7 = !{!"NumCounts", i64 200}147  !8 = !{!"NumFunctions", i64 3}148  !9 = !{!"DetailedSummary", !10}149  !10 = !{!11, !12, !13}150  !11 = !{i32 10000, i64 1000, i32 1}151  !12 = !{i32 990000, i64 300, i32 10}152  !13 = !{i32 999999, i64 5, i32 100}153)IR";154 155TEST(ModuleTest, setProfileSummary) {156  SMDiagnostic Err;157  LLVMContext Context;158  std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);159  auto *PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));160  EXPECT_NE(nullptr, PS);161  EXPECT_FALSE(PS->isPartialProfile());162  PS->setPartialProfile(true);163  M->setProfileSummary(PS->getMD(Context), ProfileSummary::PSK_Sample);164  delete PS;165  PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));166  EXPECT_NE(nullptr, PS);167  EXPECT_EQ(true, PS->isPartialProfile());168  delete PS;169}170 171TEST(ModuleTest, setPartialSampleProfileRatio) {172  const char *IRString = R"IR(173  !llvm.module.flags = !{!0}174 175  !0 = !{i32 1, !"ProfileSummary", !1}176  !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10, !11}177  !2 = !{!"ProfileFormat", !"SampleProfile"}178  !3 = !{!"TotalCount", i64 10000}179  !4 = !{!"MaxCount", i64 10}180  !5 = !{!"MaxInternalCount", i64 1}181  !6 = !{!"MaxFunctionCount", i64 1000}182  !7 = !{!"NumCounts", i64 200}183  !8 = !{!"NumFunctions", i64 3}184  !9 = !{!"IsPartialProfile", i64 1}185  !10 = !{!"PartialProfileRatio", double 0.0}186  !11 = !{!"DetailedSummary", !12}187  !12 = !{!13, !14, !15}188  !13 = !{i32 10000, i64 1000, i32 1}189  !14 = !{i32 990000, i64 300, i32 10}190  !15 = !{i32 999999, i64 5, i32 100}191  )IR";192 193  SMDiagnostic Err;194  LLVMContext Context;195  std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);196  ModuleSummaryIndex Index(/*HaveGVs*/ false);197  const unsigned BlockCount = 100;198  const unsigned NumCounts = 200;199  Index.setBlockCount(BlockCount);200  M->setPartialSampleProfileRatio(Index);201  double Ratio = (double)BlockCount / NumCounts;202  std::unique_ptr<ProfileSummary> ProfileSummary(203      ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false)));204  EXPECT_EQ(Ratio, ProfileSummary->getPartialProfileRatio());205}206 207TEST(ModuleTest, AliasList) {208  // This tests all Module's functions that interact with Module::AliasList.209  LLVMContext C;210  SMDiagnostic Err;211  LLVMContext Context;212  std::unique_ptr<Module> M = parseAssemblyString(R"(213declare void @Foo()214@GA = alias void (), ptr @Foo215)",216                                                  Err, Context);217  Function *Foo = M->getFunction("Foo");218  auto *GA = M->getNamedAlias("GA");219  EXPECT_EQ(M->alias_size(), 1u);220  auto *NewGA =221      GlobalAlias::create(Foo->getType(), 0, GlobalValue::ExternalLinkage,222                          "NewGA", Foo, /*Parent=*/nullptr);223  EXPECT_EQ(M->alias_size(), 1u);224 225  M->insertAlias(NewGA);226  EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA);227 228  M->removeAlias(NewGA);229  EXPECT_EQ(M->alias_size(), 1u);230  M->insertAlias(NewGA);231  EXPECT_EQ(M->alias_size(), 2u);232  EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA);233 234  auto Range = M->aliases();235  EXPECT_EQ(&*Range.begin(), GA);236  EXPECT_EQ(&*std::next(Range.begin()), NewGA);237  EXPECT_EQ(std::next(Range.begin(), 2), Range.end());238 239  M->removeAlias(NewGA);240  EXPECT_EQ(M->alias_size(), 1u);241 242  M->insertAlias(NewGA);243  M->eraseAlias(NewGA);244  EXPECT_EQ(M->alias_size(), 1u);245}246 247TEST(ModuleTest, IFuncList) {248  // This tests all Module's functions that interact with Module::IFuncList.249  LLVMContext C;250  SMDiagnostic Err;251  LLVMContext Context;252  std::unique_ptr<Module> M = parseAssemblyString(R"(253declare void @Foo()254@GIF = ifunc void (), ptr @Foo255)",256                                                  Err, Context);257  Function *Foo = M->getFunction("Foo");258  auto *GIF = M->getNamedIFunc("GIF");259  EXPECT_EQ(M->ifunc_size(), 1u);260  auto *NewGIF =261      GlobalIFunc::create(Foo->getType(), 0, GlobalValue::ExternalLinkage,262                          "NewGIF", Foo, /*Parent=*/nullptr);263  EXPECT_EQ(M->ifunc_size(), 1u);264 265  M->insertIFunc(NewGIF);266  EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF);267 268  M->removeIFunc(NewGIF);269  EXPECT_EQ(M->ifunc_size(), 1u);270  M->insertIFunc(NewGIF);271  EXPECT_EQ(M->ifunc_size(), 2u);272  EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF);273 274  auto Range = M->ifuncs();275  EXPECT_EQ(&*Range.begin(), GIF);276  EXPECT_EQ(&*std::next(Range.begin()), NewGIF);277  EXPECT_EQ(std::next(Range.begin(), 2), Range.end());278 279  M->removeIFunc(NewGIF);280  EXPECT_EQ(M->ifunc_size(), 1u);281 282  M->insertIFunc(NewGIF);283  M->eraseIFunc(NewGIF);284  EXPECT_EQ(M->ifunc_size(), 1u);285}286 287TEST(ModuleTest, NamedMDList) {288  // This tests all Module's functions that interact with Module::NamedMDList.289  LLVMContext C;290  SMDiagnostic Err;291  LLVMContext Context;292  auto M = std::make_unique<Module>("M", C);293  NamedMDNode *MDN1 = M->getOrInsertNamedMetadata("MDN1");294  EXPECT_EQ(M->named_metadata_size(), 1u);295  NamedMDNode *MDN2 = M->getOrInsertNamedMetadata("MDN2");296  EXPECT_EQ(M->named_metadata_size(), 2u);297  auto *NewMDN = M->getOrInsertNamedMetadata("NewMDN");298  EXPECT_EQ(M->named_metadata_size(), 3u);299 300  M->removeNamedMDNode(NewMDN);301  EXPECT_EQ(M->named_metadata_size(), 2u);302 303  M->insertNamedMDNode(NewMDN);304  EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN);305 306  M->removeNamedMDNode(NewMDN);307  M->insertNamedMDNode(NewMDN);308  EXPECT_EQ(M->named_metadata_size(), 3u);309  EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN);310 311  auto Range = M->named_metadata();312  EXPECT_EQ(&*Range.begin(), MDN1);313  EXPECT_EQ(&*std::next(Range.begin(), 1), MDN2);314  EXPECT_EQ(&*std::next(Range.begin(), 2), NewMDN);315  EXPECT_EQ(std::next(Range.begin(), 3), Range.end());316 317  M->eraseNamedMDNode(NewMDN);318  EXPECT_EQ(M->named_metadata_size(), 2u);319}320 321TEST(ModuleTest, GlobalList) {322  // This tests all Module's functions that interact with Module::GlobalList.323  LLVMContext C;324  SMDiagnostic Err;325  LLVMContext Context;326  std::unique_ptr<Module> M = parseAssemblyString(R"(327@GV = external global i32328)",329                                                  Err, Context);330  auto *GV = cast<GlobalVariable>(M->getNamedValue("GV"));331  EXPECT_EQ(M->global_size(), 1u);332  GlobalVariable *NewGV = new GlobalVariable(333      Type::getInt32Ty(C), /*isConstant=*/true, GlobalValue::InternalLinkage,334      /*Initializer=*/nullptr, "NewGV");335  EXPECT_EQ(M->global_size(), 1u);336  // Insert before337  M->insertGlobalVariable(M->globals().begin(), NewGV);338  EXPECT_EQ(M->global_size(), 2u);339  EXPECT_EQ(&*M->globals().begin(), NewGV);340  // Insert at end()341  M->removeGlobalVariable(NewGV);342  EXPECT_EQ(M->global_size(), 1u);343  M->insertGlobalVariable(NewGV);344  EXPECT_EQ(M->global_size(), 2u);345  EXPECT_EQ(&*std::prev(M->globals().end()), NewGV);346  // Check globals()347  auto Range = M->globals();348  EXPECT_EQ(&*Range.begin(), GV);349  EXPECT_EQ(&*std::next(Range.begin()), NewGV);350  EXPECT_EQ(std::next(Range.begin(), 2), Range.end());351  // Check remove352  M->removeGlobalVariable(NewGV);353  EXPECT_EQ(M->global_size(), 1u);354  // Check erase355  M->insertGlobalVariable(NewGV);356  M->eraseGlobalVariable(NewGV);357  EXPECT_EQ(M->global_size(), 1u);358}359 360TEST(ModuleTest, MoveAssign) {361  // This tests that we can move-assign modules, we parse two modules and362  // move assign the second one to the first one, and check that the print363  // is equal to what we loaded.364  LLVMContext C;365  SMDiagnostic Err;366  LLVMContext Context;367  std::unique_ptr<Module> M1 = parseAssemblyString(R"(368; ModuleID = '<string>'369source_filename = "<string1>"370 371@GV1 = external global i32372 373@GA1 = alias void (), ptr @Foo1374 375define void @Foo1() {376  ret void377}378 379!llvm.module.flags = !{!0}380!llvm.dbg.cu = !{!1}381!foo1 = !{!3}382!bar1 = !{!4}383 384!0 = !{i32 2, !"Debug Info Version", i32 3}385!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang1", isOptimized: true, flags: "-O2", runtimeVersion: 0, splitDebugFilename: "abc.debug", emissionKind: LineTablesOnly)386!2 = !DIFile(filename: "path/to/file1", directory: "/path/to/dir1")387!3 = !DILocation(line: 12, column: 34, scope: !4)388!4 = distinct !DISubprogram(name: "foo1", scope: null, spFlags: DISPFlagDefinition, unit: !1)389)",390                                                   Err, Context);391  ASSERT_TRUE(M1.get());392 393  StringLiteral M2Str = R"(394; ModuleID = '<string>'395source_filename = "<string2>"396 397@GV2 = external global i32398 399@GA2 = alias void (), ptr @Foo2400 401define void @Foo2() {402  ret void403}404 405!llvm.module.flags = !{!0}406!llvm.dbg.cu = !{!1}407!foo2 = !{!3}408!bar2 = !{!4}409 410!0 = !{i32 2, !"Debug Info Version", i32 3}411!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang2", isOptimized: true, flags: "-O2", runtimeVersion: 0, splitDebugFilename: "abc.debug", emissionKind: LineTablesOnly)412!2 = !DIFile(filename: "path/to/file2", directory: "/path/to/dir2")413!3 = !DILocation(line: 1234, column: 56, scope: !4)414!4 = distinct !DISubprogram(name: "foo2", scope: null, spFlags: DISPFlagDefinition, unit: !1)415)";416  {417    std::unique_ptr<Module> M2 = parseAssemblyString(M2Str, Err, Context);418    ASSERT_TRUE(M2.get());419    auto *GV1 = M1->getNamedValue("GV1");420    ASSERT_TRUE(GV1);421    auto *GV2 = M2->getNamedValue("GV2");422    ASSERT_TRUE(GV2);423    ASSERT_EQ(GV2->getParent(), &*M2);424    *M1 = std::move(*M2);425    ASSERT_EQ(GV2->getParent(), &*M1);426  }427 428  std::string M1Print;429  {430    llvm::raw_string_ostream Os(M1Print);431    Os << "\n" << *M1;432  }433  ASSERT_EQ(M2Str, M1Print);434}435 436} // end namespace437