1ed511560SReshabh Sharma //===- ModuleUtilsTest.cpp - Unit tests for Module utility ----===// 2ed511560SReshabh Sharma // 3ed511560SReshabh Sharma // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ed511560SReshabh Sharma // See https://llvm.org/LICENSE.txt for license information. 5ed511560SReshabh Sharma // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ed511560SReshabh Sharma // 7ed511560SReshabh Sharma //===----------------------------------------------------------------------===// 8ed511560SReshabh Sharma 9ed511560SReshabh Sharma #include "llvm/Transforms/Utils/ModuleUtils.h" 10ed511560SReshabh Sharma #include "llvm/ADT/StringRef.h" 11ed511560SReshabh Sharma #include "llvm/AsmParser/Parser.h" 12*a0a9bf51SVitaly Buka #include "llvm/IR/Constants.h" 13ed511560SReshabh Sharma #include "llvm/IR/LLVMContext.h" 14ed511560SReshabh Sharma #include "llvm/IR/Module.h" 15ed511560SReshabh Sharma #include "llvm/Support/SourceMgr.h" 16ed511560SReshabh Sharma #include "gtest/gtest.h" 17ed511560SReshabh Sharma 18ed511560SReshabh Sharma using namespace llvm; 19ed511560SReshabh Sharma 20*a0a9bf51SVitaly Buka static std::unique_ptr<Module> parseIR(LLVMContext &C, StringRef IR) { 21ed511560SReshabh Sharma SMDiagnostic Err; 22ed511560SReshabh Sharma std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); 23ed511560SReshabh Sharma if (!Mod) 24ed511560SReshabh Sharma Err.print("ModuleUtilsTest", errs()); 25ed511560SReshabh Sharma return Mod; 26ed511560SReshabh Sharma } 27ed511560SReshabh Sharma 2888ef76c4SVitaly Buka static int getListSize(Module &M, StringRef Name) { 2988ef76c4SVitaly Buka auto *List = M.getGlobalVariable(Name); 3088ef76c4SVitaly Buka if (!List) 31ed511560SReshabh Sharma return 0; 3288ef76c4SVitaly Buka auto *T = cast<ArrayType>(List->getValueType()); 3388ef76c4SVitaly Buka return T->getNumElements(); 34ed511560SReshabh Sharma } 35ed511560SReshabh Sharma 36ed511560SReshabh Sharma TEST(ModuleUtils, AppendToUsedList1) { 37ed511560SReshabh Sharma LLVMContext C; 38ed511560SReshabh Sharma 39ed511560SReshabh Sharma std::unique_ptr<Module> M = parseIR( 40ed511560SReshabh Sharma C, R"(@x = addrspace(4) global [2 x i32] zeroinitializer, align 4)"); 41ed511560SReshabh Sharma SmallVector<GlobalValue *, 2> Globals; 42ed511560SReshabh Sharma for (auto &G : M->globals()) { 43ed511560SReshabh Sharma Globals.push_back(&G); 44ed511560SReshabh Sharma } 4588ef76c4SVitaly Buka EXPECT_EQ(0, getListSize(*M, "llvm.compiler.used")); 46ed511560SReshabh Sharma appendToCompilerUsed(*M, Globals); 4788ef76c4SVitaly Buka EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); 48ed511560SReshabh Sharma 4988ef76c4SVitaly Buka EXPECT_EQ(0, getListSize(*M, "llvm.used")); 50ed511560SReshabh Sharma appendToUsed(*M, Globals); 5188ef76c4SVitaly Buka EXPECT_EQ(1, getListSize(*M, "llvm.used")); 52ed511560SReshabh Sharma } 53ed511560SReshabh Sharma 54ed511560SReshabh Sharma TEST(ModuleUtils, AppendToUsedList2) { 55ed511560SReshabh Sharma LLVMContext C; 56ed511560SReshabh Sharma 57ed511560SReshabh Sharma std::unique_ptr<Module> M = 58ed511560SReshabh Sharma parseIR(C, R"(@x = global [2 x i32] zeroinitializer, align 4)"); 59ed511560SReshabh Sharma SmallVector<GlobalValue *, 2> Globals; 60ed511560SReshabh Sharma for (auto &G : M->globals()) { 61ed511560SReshabh Sharma Globals.push_back(&G); 62ed511560SReshabh Sharma } 6388ef76c4SVitaly Buka EXPECT_EQ(0, getListSize(*M, "llvm.compiler.used")); 64ed511560SReshabh Sharma appendToCompilerUsed(*M, Globals); 6588ef76c4SVitaly Buka EXPECT_EQ(1, getListSize(*M, "llvm.compiler.used")); 66ed511560SReshabh Sharma 6788ef76c4SVitaly Buka EXPECT_EQ(0, getListSize(*M, "llvm.used")); 68ed511560SReshabh Sharma appendToUsed(*M, Globals); 6988ef76c4SVitaly Buka EXPECT_EQ(1, getListSize(*M, "llvm.used")); 70ed511560SReshabh Sharma } 71*a0a9bf51SVitaly Buka 72*a0a9bf51SVitaly Buka using AppendFnType = decltype(&appendToGlobalCtors); 73*a0a9bf51SVitaly Buka using ParamType = std::tuple<StringRef, AppendFnType>; 74*a0a9bf51SVitaly Buka class ModuleUtilsTest : public testing::TestWithParam<ParamType> { 75*a0a9bf51SVitaly Buka public: 76*a0a9bf51SVitaly Buka StringRef arrayName() const { return std::get<0>(GetParam()); } 77*a0a9bf51SVitaly Buka AppendFnType appendFn() const { return std::get<AppendFnType>(GetParam()); } 78*a0a9bf51SVitaly Buka }; 79*a0a9bf51SVitaly Buka 80*a0a9bf51SVitaly Buka INSTANTIATE_TEST_SUITE_P( 81*a0a9bf51SVitaly Buka ModuleUtilsTestCtors, ModuleUtilsTest, 82*a0a9bf51SVitaly Buka ::testing::Values(ParamType{"llvm.global_ctors", &appendToGlobalCtors}, 83*a0a9bf51SVitaly Buka ParamType{"llvm.global_dtors", &appendToGlobalDtors})); 84*a0a9bf51SVitaly Buka 85*a0a9bf51SVitaly Buka TEST_P(ModuleUtilsTest, AppendToMissingArray) { 86*a0a9bf51SVitaly Buka LLVMContext C; 87*a0a9bf51SVitaly Buka 88*a0a9bf51SVitaly Buka std::unique_ptr<Module> M = parseIR(C, ""); 89*a0a9bf51SVitaly Buka 90*a0a9bf51SVitaly Buka EXPECT_EQ(0, getListSize(*M, arrayName())); 91*a0a9bf51SVitaly Buka Function *F = cast<Function>( 92*a0a9bf51SVitaly Buka M->getOrInsertFunction("ctor", Type::getVoidTy(C)).getCallee()); 93*a0a9bf51SVitaly Buka appendFn()(*M, F, 11, F); 94*a0a9bf51SVitaly Buka ASSERT_EQ(1, getListSize(*M, arrayName())); 95*a0a9bf51SVitaly Buka 96*a0a9bf51SVitaly Buka ConstantArray *CA = dyn_cast<ConstantArray>( 97*a0a9bf51SVitaly Buka M->getGlobalVariable(arrayName())->getInitializer()); 98*a0a9bf51SVitaly Buka ASSERT_NE(nullptr, CA); 99*a0a9bf51SVitaly Buka ConstantStruct *CS = dyn_cast<ConstantStruct>(CA->getOperand(0)); 100*a0a9bf51SVitaly Buka ASSERT_NE(nullptr, CS); 101*a0a9bf51SVitaly Buka ConstantInt *Pri = dyn_cast<ConstantInt>(CS->getOperand(0)); 102*a0a9bf51SVitaly Buka ASSERT_NE(nullptr, Pri); 103*a0a9bf51SVitaly Buka EXPECT_EQ(11u, Pri->getLimitedValue()); 104*a0a9bf51SVitaly Buka EXPECT_EQ(F, dyn_cast<Function>(CS->getOperand(1))); 105*a0a9bf51SVitaly Buka EXPECT_EQ(F, CS->getOperand(2)); 106*a0a9bf51SVitaly Buka } 107*a0a9bf51SVitaly Buka 108*a0a9bf51SVitaly Buka TEST_P(ModuleUtilsTest, AppendToArray) { 109*a0a9bf51SVitaly Buka LLVMContext C; 110*a0a9bf51SVitaly Buka 111*a0a9bf51SVitaly Buka std::unique_ptr<Module> M = 112*a0a9bf51SVitaly Buka parseIR(C, (R"(@)" + arrayName() + 113*a0a9bf51SVitaly Buka R"( = appending global [2 x { i32, ptr, ptr }] [ 114*a0a9bf51SVitaly Buka { i32, ptr, ptr } { i32 65535, ptr null, ptr null }, 115*a0a9bf51SVitaly Buka { i32, ptr, ptr } { i32 0, ptr null, ptr null }] 116*a0a9bf51SVitaly Buka )") 117*a0a9bf51SVitaly Buka .str()); 118*a0a9bf51SVitaly Buka 119*a0a9bf51SVitaly Buka EXPECT_EQ(2, getListSize(*M, arrayName())); 120*a0a9bf51SVitaly Buka appendFn()( 121*a0a9bf51SVitaly Buka *M, 122*a0a9bf51SVitaly Buka cast<Function>( 123*a0a9bf51SVitaly Buka M->getOrInsertFunction("ctor", Type::getVoidTy(C)).getCallee()), 124*a0a9bf51SVitaly Buka 11, nullptr); 125*a0a9bf51SVitaly Buka EXPECT_EQ(3, getListSize(*M, arrayName())); 126*a0a9bf51SVitaly Buka } 127