1 //===- ExecutionEngineTest.cpp - Unit tests for ExecutionEngine -----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ExecutionEngine/Interpreter.h" 11 #include "llvm/IR/DerivedTypes.h" 12 #include "llvm/IR/GlobalVariable.h" 13 #include "llvm/IR/LLVMContext.h" 14 #include "llvm/IR/Module.h" 15 #include "llvm/Support/ManagedStatic.h" 16 #include "gtest/gtest.h" 17 18 using namespace llvm; 19 20 static llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 21 22 namespace { 23 24 class ExecutionEngineTest : public testing::Test { 25 protected: 26 ExecutionEngineTest() { 27 auto Owner = make_unique<Module>("<main>", getGlobalContext()); 28 M = Owner.get(); 29 Engine.reset(EngineBuilder(std::move(Owner)).setErrorStr(&Error).create()); 30 } 31 32 virtual void SetUp() { 33 ASSERT_TRUE(Engine.get() != nullptr) << "EngineBuilder returned error: '" 34 << Error << "'"; 35 } 36 37 GlobalVariable *NewExtGlobal(Type *T, const Twine &Name) { 38 return new GlobalVariable(*M, T, false, // Not constant. 39 GlobalValue::ExternalLinkage, nullptr, Name); 40 } 41 42 std::string Error; 43 Module *M; // Owned by ExecutionEngine. 44 std::unique_ptr<ExecutionEngine> Engine; 45 }; 46 47 TEST_F(ExecutionEngineTest, ForwardGlobalMapping) { 48 GlobalVariable *G1 = 49 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 50 int32_t Mem1 = 3; 51 Engine->addGlobalMapping(G1, &Mem1); 52 EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G1)); 53 int32_t Mem2 = 4; 54 Engine->updateGlobalMapping(G1, &Mem2); 55 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)); 56 Engine->updateGlobalMapping(G1, nullptr); 57 EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G1)); 58 Engine->updateGlobalMapping(G1, &Mem2); 59 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)); 60 61 GlobalVariable *G2 = 62 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 63 EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G2)) 64 << "The NULL return shouldn't depend on having called" 65 << " updateGlobalMapping(..., NULL)"; 66 // Check that update...() can be called before add...(). 67 Engine->updateGlobalMapping(G2, &Mem1); 68 EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G2)); 69 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)) 70 << "A second mapping shouldn't affect the first."; 71 } 72 73 TEST_F(ExecutionEngineTest, ReverseGlobalMapping) { 74 GlobalVariable *G1 = 75 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 76 77 int32_t Mem1 = 3; 78 Engine->addGlobalMapping(G1, &Mem1); 79 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); 80 int32_t Mem2 = 4; 81 Engine->updateGlobalMapping(G1, &Mem2); 82 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); 83 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2)); 84 85 GlobalVariable *G2 = 86 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2"); 87 Engine->updateGlobalMapping(G2, &Mem1); 88 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)); 89 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2)); 90 Engine->updateGlobalMapping(G1, nullptr); 91 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)) 92 << "Removing one mapping doesn't affect a different one."; 93 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem2)); 94 Engine->updateGlobalMapping(G2, &Mem2); 95 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); 96 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem2)) 97 << "Once a mapping is removed, we can point another GV at the" 98 << " now-free address."; 99 } 100 101 TEST_F(ExecutionEngineTest, ClearModuleMappings) { 102 GlobalVariable *G1 = 103 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 104 105 int32_t Mem1 = 3; 106 Engine->addGlobalMapping(G1, &Mem1); 107 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); 108 109 Engine->clearGlobalMappingsFromModule(M); 110 111 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); 112 113 GlobalVariable *G2 = 114 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2"); 115 // After clearing the module mappings, we can assign a new GV to the 116 // same address. 117 Engine->addGlobalMapping(G2, &Mem1); 118 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)); 119 } 120 121 TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) { 122 GlobalVariable *G1 = 123 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 124 int32_t Mem1 = 3; 125 Engine->addGlobalMapping(G1, &Mem1); 126 // Make sure the reverse mapping is enabled. 127 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); 128 // When the GV goes away, the ExecutionEngine should remove any 129 // mappings that refer to it. 130 G1->eraseFromParent(); 131 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); 132 } 133 134 } 135