|
9 | 9 | #include "llvm/Transforms/Utils/ModuleUtils.h"
|
10 | 10 | #include "llvm/ADT/StringRef.h"
|
11 | 11 | #include "llvm/AsmParser/Parser.h"
|
| 12 | +#include "llvm/IR/Constants.h" |
12 | 13 | #include "llvm/IR/LLVMContext.h"
|
13 | 14 | #include "llvm/IR/Module.h"
|
14 | 15 | #include "llvm/Support/SourceMgr.h"
|
15 | 16 | #include "gtest/gtest.h"
|
16 | 17 |
|
17 | 18 | using namespace llvm;
|
18 | 19 |
|
19 |
| -static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { |
| 20 | +static std::unique_ptr<Module> parseIR(LLVMContext &C, StringRef IR) { |
20 | 21 | SMDiagnostic Err;
|
21 | 22 | std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
|
22 | 23 | if (!Mod)
|
@@ -67,3 +68,59 @@ TEST(ModuleUtils, AppendToUsedList2) {
|
67 | 68 | appendToUsed(*M, Globals);
|
68 | 69 | EXPECT_EQ(1, getListSize(*M, "llvm.used"));
|
69 | 70 | }
|
| 71 | + |
| 72 | +using AppendFnType = decltype(&appendToGlobalCtors); |
| 73 | +using ParamType = std::tuple<StringRef, AppendFnType>; |
| 74 | +class ModuleUtilsTest : public testing::TestWithParam<ParamType> { |
| 75 | +public: |
| 76 | + StringRef arrayName() const { return std::get<0>(GetParam()); } |
| 77 | + AppendFnType appendFn() const { return std::get<AppendFnType>(GetParam()); } |
| 78 | +}; |
| 79 | + |
| 80 | +INSTANTIATE_TEST_SUITE_P( |
| 81 | + ModuleUtilsTestCtors, ModuleUtilsTest, |
| 82 | + ::testing::Values(ParamType{"llvm.global_ctors", &appendToGlobalCtors}, |
| 83 | + ParamType{"llvm.global_dtors", &appendToGlobalDtors})); |
| 84 | + |
| 85 | +TEST_P(ModuleUtilsTest, AppendToMissingArray) { |
| 86 | + LLVMContext C; |
| 87 | + |
| 88 | + std::unique_ptr<Module> M = parseIR(C, ""); |
| 89 | + |
| 90 | + EXPECT_EQ(0, getListSize(*M, arrayName())); |
| 91 | + Function *F = cast<Function>( |
| 92 | + M->getOrInsertFunction("ctor", Type::getVoidTy(C)).getCallee()); |
| 93 | + appendFn()(*M, F, 11, F); |
| 94 | + ASSERT_EQ(1, getListSize(*M, arrayName())); |
| 95 | + |
| 96 | + ConstantArray *CA = dyn_cast<ConstantArray>( |
| 97 | + M->getGlobalVariable(arrayName())->getInitializer()); |
| 98 | + ASSERT_NE(nullptr, CA); |
| 99 | + ConstantStruct *CS = dyn_cast<ConstantStruct>(CA->getOperand(0)); |
| 100 | + ASSERT_NE(nullptr, CS); |
| 101 | + ConstantInt *Pri = dyn_cast<ConstantInt>(CS->getOperand(0)); |
| 102 | + ASSERT_NE(nullptr, Pri); |
| 103 | + EXPECT_EQ(11u, Pri->getLimitedValue()); |
| 104 | + EXPECT_EQ(F, dyn_cast<Function>(CS->getOperand(1))); |
| 105 | + EXPECT_EQ(F, CS->getOperand(2)); |
| 106 | +} |
| 107 | + |
| 108 | +TEST_P(ModuleUtilsTest, AppendToArray) { |
| 109 | + LLVMContext C; |
| 110 | + |
| 111 | + std::unique_ptr<Module> M = |
| 112 | + parseIR(C, (R"(@)" + arrayName() + |
| 113 | + R"( = appending global [2 x { i32, ptr, ptr }] [ |
| 114 | + { i32, ptr, ptr } { i32 65535, ptr null, ptr null }, |
| 115 | + { i32, ptr, ptr } { i32 0, ptr null, ptr null }] |
| 116 | + )") |
| 117 | + .str()); |
| 118 | + |
| 119 | + EXPECT_EQ(2, getListSize(*M, arrayName())); |
| 120 | + appendFn()( |
| 121 | + *M, |
| 122 | + cast<Function>( |
| 123 | + M->getOrInsertFunction("ctor", Type::getVoidTy(C)).getCallee()), |
| 124 | + 11, nullptr); |
| 125 | + EXPECT_EQ(3, getListSize(*M, arrayName())); |
| 126 | +} |
0 commit comments