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