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/ExecutionEngine/RTDyldMemoryManager.h" 12 #include "llvm/ADT/STLExtras.h" 13 #include "llvm/IR/DerivedTypes.h" 14 #include "llvm/IR/GlobalVariable.h" 15 #include "llvm/IR/LLVMContext.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/Support/DynamicLibrary.h" 18 #include "llvm/Support/ManagedStatic.h" 19 #include "gtest/gtest.h" 20 21 using namespace llvm; 22 23 namespace { 24 25 class ExecutionEngineTest : public testing::Test { 26 private: 27 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 28 29 protected: 30 ExecutionEngineTest() { 31 auto Owner = make_unique<Module>("<main>", getGlobalContext()); 32 M = Owner.get(); 33 Engine.reset(EngineBuilder(std::move(Owner)).setErrorStr(&Error).create()); 34 } 35 36 virtual void SetUp() { 37 ASSERT_TRUE(Engine.get() != nullptr) << "EngineBuilder returned error: '" 38 << Error << "'"; 39 } 40 41 GlobalVariable *NewExtGlobal(Type *T, const Twine &Name) { 42 return new GlobalVariable(*M, T, false, // Not constant. 43 GlobalValue::ExternalLinkage, nullptr, Name); 44 } 45 46 std::string Error; 47 Module *M; // Owned by ExecutionEngine. 48 std::unique_ptr<ExecutionEngine> Engine; 49 }; 50 51 TEST_F(ExecutionEngineTest, ForwardGlobalMapping) { 52 GlobalVariable *G1 = 53 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 54 int32_t Mem1 = 3; 55 Engine->addGlobalMapping(G1, &Mem1); 56 EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G1)); 57 int32_t Mem2 = 4; 58 Engine->updateGlobalMapping(G1, &Mem2); 59 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)); 60 Engine->updateGlobalMapping(G1, nullptr); 61 EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G1)); 62 Engine->updateGlobalMapping(G1, &Mem2); 63 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)); 64 65 GlobalVariable *G2 = 66 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 67 EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G2)) 68 << "The NULL return shouldn't depend on having called" 69 << " updateGlobalMapping(..., NULL)"; 70 // Check that update...() can be called before add...(). 71 Engine->updateGlobalMapping(G2, &Mem1); 72 EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G2)); 73 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1)) 74 << "A second mapping shouldn't affect the first."; 75 } 76 77 TEST_F(ExecutionEngineTest, ReverseGlobalMapping) { 78 GlobalVariable *G1 = 79 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 80 81 int32_t Mem1 = 3; 82 Engine->addGlobalMapping(G1, &Mem1); 83 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); 84 int32_t Mem2 = 4; 85 Engine->updateGlobalMapping(G1, &Mem2); 86 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); 87 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2)); 88 89 GlobalVariable *G2 = 90 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2"); 91 Engine->updateGlobalMapping(G2, &Mem1); 92 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)); 93 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2)); 94 Engine->updateGlobalMapping(G1, nullptr); 95 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)) 96 << "Removing one mapping doesn't affect a different one."; 97 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem2)); 98 Engine->updateGlobalMapping(G2, &Mem2); 99 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); 100 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem2)) 101 << "Once a mapping is removed, we can point another GV at the" 102 << " now-free address."; 103 } 104 105 TEST_F(ExecutionEngineTest, ClearModuleMappings) { 106 GlobalVariable *G1 = 107 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 108 109 int32_t Mem1 = 3; 110 Engine->addGlobalMapping(G1, &Mem1); 111 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); 112 113 Engine->clearGlobalMappingsFromModule(M); 114 115 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); 116 117 GlobalVariable *G2 = 118 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2"); 119 // After clearing the module mappings, we can assign a new GV to the 120 // same address. 121 Engine->addGlobalMapping(G2, &Mem1); 122 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1)); 123 } 124 125 TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) { 126 GlobalVariable *G1 = 127 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1"); 128 int32_t Mem1 = 3; 129 Engine->addGlobalMapping(G1, &Mem1); 130 // Make sure the reverse mapping is enabled. 131 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1)); 132 // When the GV goes away, the ExecutionEngine should remove any 133 // mappings that refer to it. 134 G1->eraseFromParent(); 135 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); 136 } 137 138 TEST_F(ExecutionEngineTest, LookupWithMangledName) { 139 int x; 140 llvm::sys::DynamicLibrary::AddSymbol("x", &x); 141 142 // Demonstrate that getSymbolAddress accepts mangled names and always strips 143 // the leading underscore. 144 EXPECT_EQ(reinterpret_cast<uint64_t>(&x), 145 RTDyldMemoryManager::getSymbolAddressInProcess("_x")); 146 } 147 148 TEST_F(ExecutionEngineTest, LookupWithMangledAndDemangledSymbol) { 149 int x; 150 int _x; 151 llvm::sys::DynamicLibrary::AddSymbol("x", &x); 152 llvm::sys::DynamicLibrary::AddSymbol("_x", &_x); 153 154 // Lookup the demangled name first, even if there's a demangled symbol that 155 // matches the input already. 156 EXPECT_EQ(reinterpret_cast<uint64_t>(&x), 157 RTDyldMemoryManager::getSymbolAddressInProcess("_x")); 158 } 159 160 TEST_F(ExecutionEngineTest, LookupwithDemangledName) { 161 int _x; 162 llvm::sys::DynamicLibrary::AddSymbol("_x", &_x); 163 164 // But do fallback to looking up a demangled name if there's no ambiguity 165 EXPECT_EQ(reinterpret_cast<uint64_t>(&_x), 166 RTDyldMemoryManager::getSymbolAddressInProcess("_x")); 167 } 168 169 } 170