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-exception 6 // 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 22 using namespace llvm; 23 24 namespace { 25 26 bool sortByName(const GlobalVariable &L, const GlobalVariable &R) { 27 return L.getName() < R.getName(); 28 } 29 30 bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) { 31 return sortByName(R, L); 32 } 33 34 TEST(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 54 TEST(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 78 TEST(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 91 TEST(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 106 const char *IRString = R"IR( 107 !llvm.module.flags = !{!0} 108 109 !0 = !{i32 1, !"ProfileSummary", !1} 110 !1 = !{!2, !3, !4, !5, !6, !7, !8, !9} 111 !2 = !{!"ProfileFormat", !"SampleProfile"} 112 !3 = !{!"TotalCount", i64 10000} 113 !4 = !{!"MaxCount", i64 10} 114 !5 = !{!"MaxInternalCount", i64 1} 115 !6 = !{!"MaxFunctionCount", i64 1000} 116 !7 = !{!"NumCounts", i64 200} 117 !8 = !{!"NumFunctions", i64 3} 118 !9 = !{!"DetailedSummary", !10} 119 !10 = !{!11, !12, !13} 120 !11 = !{i32 10000, i64 1000, i32 1} 121 !12 = !{i32 990000, i64 300, i32 10} 122 !13 = !{i32 999999, i64 5, i32 100} 123 )IR"; 124 125 TEST(ModuleTest, setProfileSummary) { 126 SMDiagnostic Err; 127 LLVMContext Context; 128 std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context); 129 auto *PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false)); 130 EXPECT_NE(nullptr, PS); 131 EXPECT_FALSE(PS->isPartialProfile()); 132 PS->setPartialProfile(true); 133 M->setProfileSummary(PS->getMD(Context), ProfileSummary::PSK_Sample); 134 delete PS; 135 PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false)); 136 EXPECT_NE(nullptr, PS); 137 EXPECT_EQ(true, PS->isPartialProfile()); 138 delete PS; 139 } 140 141 TEST(ModuleTest, setPartialSampleProfileRatio) { 142 const char *IRString = R"IR( 143 !llvm.module.flags = !{!0} 144 145 !0 = !{i32 1, !"ProfileSummary", !1} 146 !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10, !11} 147 !2 = !{!"ProfileFormat", !"SampleProfile"} 148 !3 = !{!"TotalCount", i64 10000} 149 !4 = !{!"MaxCount", i64 10} 150 !5 = !{!"MaxInternalCount", i64 1} 151 !6 = !{!"MaxFunctionCount", i64 1000} 152 !7 = !{!"NumCounts", i64 200} 153 !8 = !{!"NumFunctions", i64 3} 154 !9 = !{!"IsPartialProfile", i64 1} 155 !10 = !{!"PartialProfileRatio", double 0.0} 156 !11 = !{!"DetailedSummary", !12} 157 !12 = !{!13, !14, !15} 158 !13 = !{i32 10000, i64 1000, i32 1} 159 !14 = !{i32 990000, i64 300, i32 10} 160 !15 = !{i32 999999, i64 5, i32 100} 161 )IR"; 162 163 SMDiagnostic Err; 164 LLVMContext Context; 165 std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context); 166 ModuleSummaryIndex Index(/*HaveGVs*/ false); 167 const unsigned BlockCount = 100; 168 const unsigned NumCounts = 200; 169 Index.setBlockCount(BlockCount); 170 M->setPartialSampleProfileRatio(Index); 171 double Ratio = (double)BlockCount / NumCounts; 172 std::unique_ptr<ProfileSummary> ProfileSummary( 173 ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false))); 174 EXPECT_EQ(Ratio, ProfileSummary->getPartialProfileRatio()); 175 } 176 177 TEST(ModuleTest, AliasList) { 178 // This tests all Module's functions that interact with Module::AliasList. 179 LLVMContext C; 180 SMDiagnostic Err; 181 LLVMContext Context; 182 std::unique_ptr<Module> M = parseAssemblyString(R"( 183 declare void @Foo() 184 @GA = alias void (), ptr @Foo 185 )", 186 Err, Context); 187 Function *Foo = M->getFunction("Foo"); 188 auto *GA = M->getNamedAlias("GA"); 189 EXPECT_EQ(M->alias_size(), 1u); 190 auto *NewGA = 191 GlobalAlias::create(Foo->getType(), 0, GlobalValue::ExternalLinkage, 192 "NewGA", Foo, /*Parent=*/nullptr); 193 EXPECT_EQ(M->alias_size(), 1u); 194 195 M->insertAlias(NewGA); 196 EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA); 197 198 M->removeAlias(NewGA); 199 EXPECT_EQ(M->alias_size(), 1u); 200 M->insertAlias(NewGA); 201 EXPECT_EQ(M->alias_size(), 2u); 202 EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA); 203 204 auto Range = M->aliases(); 205 EXPECT_EQ(&*Range.begin(), GA); 206 EXPECT_EQ(&*std::next(Range.begin()), NewGA); 207 EXPECT_EQ(std::next(Range.begin(), 2), Range.end()); 208 209 M->removeAlias(NewGA); 210 EXPECT_EQ(M->alias_size(), 1u); 211 212 M->insertAlias(NewGA); 213 M->eraseAlias(NewGA); 214 EXPECT_EQ(M->alias_size(), 1u); 215 } 216 217 TEST(ModuleTest, IFuncList) { 218 // This tests all Module's functions that interact with Module::IFuncList. 219 LLVMContext C; 220 SMDiagnostic Err; 221 LLVMContext Context; 222 std::unique_ptr<Module> M = parseAssemblyString(R"( 223 declare void @Foo() 224 @GIF = ifunc void (), ptr @Foo 225 )", 226 Err, Context); 227 Function *Foo = M->getFunction("Foo"); 228 auto *GIF = M->getNamedIFunc("GIF"); 229 EXPECT_EQ(M->ifunc_size(), 1u); 230 auto *NewGIF = 231 GlobalIFunc::create(Foo->getType(), 0, GlobalValue::ExternalLinkage, 232 "NewGIF", Foo, /*Parent=*/nullptr); 233 EXPECT_EQ(M->ifunc_size(), 1u); 234 235 M->insertIFunc(NewGIF); 236 EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF); 237 238 M->removeIFunc(NewGIF); 239 EXPECT_EQ(M->ifunc_size(), 1u); 240 M->insertIFunc(NewGIF); 241 EXPECT_EQ(M->ifunc_size(), 2u); 242 EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF); 243 244 auto Range = M->ifuncs(); 245 EXPECT_EQ(&*Range.begin(), GIF); 246 EXPECT_EQ(&*std::next(Range.begin()), NewGIF); 247 EXPECT_EQ(std::next(Range.begin(), 2), Range.end()); 248 249 M->removeIFunc(NewGIF); 250 EXPECT_EQ(M->ifunc_size(), 1u); 251 252 M->insertIFunc(NewGIF); 253 M->eraseIFunc(NewGIF); 254 EXPECT_EQ(M->ifunc_size(), 1u); 255 } 256 257 TEST(ModuleTest, NamedMDList) { 258 // This tests all Module's functions that interact with Module::NamedMDList. 259 LLVMContext C; 260 SMDiagnostic Err; 261 LLVMContext Context; 262 auto M = std::make_unique<Module>("M", C); 263 NamedMDNode *MDN1 = M->getOrInsertNamedMetadata("MDN1"); 264 EXPECT_EQ(M->named_metadata_size(), 1u); 265 NamedMDNode *MDN2 = M->getOrInsertNamedMetadata("MDN2"); 266 EXPECT_EQ(M->named_metadata_size(), 2u); 267 auto *NewMDN = M->getOrInsertNamedMetadata("NewMDN"); 268 EXPECT_EQ(M->named_metadata_size(), 3u); 269 270 M->removeNamedMDNode(NewMDN); 271 EXPECT_EQ(M->named_metadata_size(), 2u); 272 273 M->insertNamedMDNode(NewMDN); 274 EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN); 275 276 M->removeNamedMDNode(NewMDN); 277 M->insertNamedMDNode(NewMDN); 278 EXPECT_EQ(M->named_metadata_size(), 3u); 279 EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN); 280 281 auto Range = M->named_metadata(); 282 EXPECT_EQ(&*Range.begin(), MDN1); 283 EXPECT_EQ(&*std::next(Range.begin(), 1), MDN2); 284 EXPECT_EQ(&*std::next(Range.begin(), 2), NewMDN); 285 EXPECT_EQ(std::next(Range.begin(), 3), Range.end()); 286 287 M->eraseNamedMDNode(NewMDN); 288 EXPECT_EQ(M->named_metadata_size(), 2u); 289 } 290 291 TEST(ModuleTest, GlobalList) { 292 // This tests all Module's functions that interact with Module::GlobalList. 293 LLVMContext C; 294 SMDiagnostic Err; 295 LLVMContext Context; 296 std::unique_ptr<Module> M = parseAssemblyString(R"( 297 @GV = external global i32 298 )", 299 Err, Context); 300 auto *GV = cast<GlobalVariable>(M->getNamedValue("GV")); 301 EXPECT_EQ(M->global_size(), 1u); 302 GlobalVariable *NewGV = new GlobalVariable( 303 Type::getInt32Ty(C), /*isConstant=*/true, GlobalValue::InternalLinkage, 304 /*Initializer=*/nullptr, "NewGV"); 305 EXPECT_EQ(M->global_size(), 1u); 306 // Insert before 307 M->insertGlobalVariable(M->globals().begin(), NewGV); 308 EXPECT_EQ(M->global_size(), 2u); 309 EXPECT_EQ(&*M->globals().begin(), NewGV); 310 // Insert at end() 311 M->removeGlobalVariable(NewGV); 312 EXPECT_EQ(M->global_size(), 1u); 313 M->insertGlobalVariable(NewGV); 314 EXPECT_EQ(M->global_size(), 2u); 315 EXPECT_EQ(&*std::prev(M->globals().end()), NewGV); 316 // Check globals() 317 auto Range = M->globals(); 318 EXPECT_EQ(&*Range.begin(), GV); 319 EXPECT_EQ(&*std::next(Range.begin()), NewGV); 320 EXPECT_EQ(std::next(Range.begin(), 2), Range.end()); 321 // Check remove 322 M->removeGlobalVariable(NewGV); 323 EXPECT_EQ(M->global_size(), 1u); 324 // Check erase 325 M->insertGlobalVariable(NewGV); 326 M->eraseGlobalVariable(NewGV); 327 EXPECT_EQ(M->global_size(), 1u); 328 } 329 330 TEST(ModuleTest, MoveAssign) { 331 // This tests that we can move-assign modules, we parse two modules and 332 // move assign the second one to the first one, and check that the print 333 // is equal to what we loaded. 334 LLVMContext C; 335 SMDiagnostic Err; 336 LLVMContext Context; 337 std::unique_ptr<Module> M1 = parseAssemblyString(R"( 338 ; ModuleID = '<string>' 339 source_filename = "<string1>" 340 341 @GV1 = external global i32 342 343 @GA1 = alias void (), ptr @Foo1 344 345 define void @Foo1() { 346 ret void 347 } 348 349 !llvm.module.flags = !{!0} 350 !llvm.dbg.cu = !{!1} 351 !foo1 = !{!3} 352 !bar1 = !{!4} 353 354 !0 = !{i32 2, !"Debug Info Version", i32 3} 355 !1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang1", isOptimized: true, flags: "-O2", runtimeVersion: 0, splitDebugFilename: "abc.debug", emissionKind: LineTablesOnly) 356 !2 = !DIFile(filename: "path/to/file1", directory: "/path/to/dir1") 357 !3 = !DILocation(line: 12, column: 34, scope: !4) 358 !4 = distinct !DISubprogram(name: "foo1", scope: null, spFlags: DISPFlagDefinition, unit: !1) 359 )", 360 Err, Context); 361 ASSERT_TRUE(M1.get()); 362 363 StringLiteral M2Str = R"( 364 ; ModuleID = '<string>' 365 source_filename = "<string2>" 366 367 @GV2 = external global i32 368 369 @GA2 = alias void (), ptr @Foo2 370 371 define void @Foo2() { 372 ret void 373 } 374 375 !llvm.module.flags = !{!0} 376 !llvm.dbg.cu = !{!1} 377 !foo2 = !{!3} 378 !bar2 = !{!4} 379 380 !0 = !{i32 2, !"Debug Info Version", i32 3} 381 !1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang2", isOptimized: true, flags: "-O2", runtimeVersion: 0, splitDebugFilename: "abc.debug", emissionKind: LineTablesOnly) 382 !2 = !DIFile(filename: "path/to/file2", directory: "/path/to/dir2") 383 !3 = !DILocation(line: 1234, column: 56, scope: !4) 384 !4 = distinct !DISubprogram(name: "foo2", scope: null, spFlags: DISPFlagDefinition, unit: !1) 385 )"; 386 { 387 std::unique_ptr<Module> M2 = parseAssemblyString(M2Str, Err, Context); 388 ASSERT_TRUE(M2.get()); 389 auto *GV1 = M1->getNamedValue("GV1"); 390 ASSERT_TRUE(GV1); 391 auto *GV2 = M2->getNamedValue("GV2"); 392 ASSERT_TRUE(GV2); 393 ASSERT_EQ(GV2->getParent(), &*M2); 394 *M1 = std::move(*M2); 395 ASSERT_EQ(GV2->getParent(), &*M1); 396 } 397 398 std::string M1Print; 399 { 400 llvm::raw_string_ostream Os(M1Print); 401 Os << "\n" << *M1; 402 } 403 ASSERT_EQ(M2Str, M1Print); 404 } 405 406 } // end namespace 407