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