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