xref: /llvm-project/llvm/unittests/Transforms/Utils/ModuleUtilsTest.cpp (revision a0a9bf5152507beacd2a72dda42d054391494c4a)
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