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