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