blob: b92b3f6e9845dcbd5a304ceeb7104d963ee2ada8 [file] [log] [blame]
Jeffrey Yasskin337b1242009-08-04 23:53:16 +00001//===- ExecutionEngineTest.cpp - Unit tests for ExecutionEngine -----------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Jeffrey Yasskin337b1242009-08-04 23:53:16 +00006//
7//===----------------------------------------------------------------------===//
8
Chandler Carruth9a67b072017-06-06 11:06:56 +00009#include "llvm/ADT/STLExtras.h"
Chandler Carruth130cec22012-12-04 10:23:08 +000010#include "llvm/ExecutionEngine/Interpreter.h"
David Blaikiece3f5732014-09-29 21:25:13 +000011#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000012#include "llvm/IR/DerivedTypes.h"
13#include "llvm/IR/GlobalVariable.h"
14#include "llvm/IR/LLVMContext.h"
15#include "llvm/IR/Module.h"
David Blaikiece3f5732014-09-29 21:25:13 +000016#include "llvm/Support/DynamicLibrary.h"
NAKAMURA Takumi4d723ba2014-09-23 13:49:51 +000017#include "llvm/Support/ManagedStatic.h"
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000018#include "gtest/gtest.h"
19
20using namespace llvm;
21
22namespace {
23
24class ExecutionEngineTest : public testing::Test {
NAKAMURA Takumidbf2c212014-09-23 14:41:02 +000025private:
26 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
27
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000028protected:
Rafael Espindola2a8a2792014-08-19 04:04:25 +000029 ExecutionEngineTest() {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +000030 auto Owner = std::make_unique<Module>("<main>", Context);
Rafael Espindola2a8a2792014-08-19 04:04:25 +000031 M = Owner.get();
32 Engine.reset(EngineBuilder(std::move(Owner)).setErrorStr(&Error).create());
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000033 }
34
Alexander Kornienkof817c1c2015-04-11 02:11:45 +000035 void SetUp() override {
Craig Topper66f09ad2014-06-08 22:29:17 +000036 ASSERT_TRUE(Engine.get() != nullptr) << "EngineBuilder returned error: '"
Dylan Noblesmithf6f9f1d2011-12-02 20:53:53 +000037 << Error << "'";
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000038 }
39
Chris Lattner229907c2011-07-18 04:54:35 +000040 GlobalVariable *NewExtGlobal(Type *T, const Twine &Name) {
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000041 return new GlobalVariable(*M, T, false, // Not constant.
Craig Topper66f09ad2014-06-08 22:29:17 +000042 GlobalValue::ExternalLinkage, nullptr, Name);
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000043 }
44
Dylan Noblesmithf6f9f1d2011-12-02 20:53:53 +000045 std::string Error;
Mehdi Amini03b42e42016-04-14 21:59:01 +000046 LLVMContext Context;
Rafael Espindola2a8a2792014-08-19 04:04:25 +000047 Module *M; // Owned by ExecutionEngine.
48 std::unique_ptr<ExecutionEngine> Engine;
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000049};
50
51TEST_F(ExecutionEngineTest, ForwardGlobalMapping) {
Mehdi Amini03b42e42016-04-14 21:59:01 +000052 GlobalVariable *G1 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000053 int32_t Mem1 = 3;
54 Engine->addGlobalMapping(G1, &Mem1);
55 EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G1));
Lang Hames3dac3f72015-03-31 20:31:14 +000056 EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable("Global1"));
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000057 int32_t Mem2 = 4;
58 Engine->updateGlobalMapping(G1, &Mem2);
59 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1));
Craig Topper66f09ad2014-06-08 22:29:17 +000060 Engine->updateGlobalMapping(G1, nullptr);
61 EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G1));
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000062 Engine->updateGlobalMapping(G1, &Mem2);
63 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1));
64
Mehdi Amini03b42e42016-04-14 21:59:01 +000065 GlobalVariable *G2 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
Craig Topper66f09ad2014-06-08 22:29:17 +000066 EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G2))
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000067 << "The NULL return shouldn't depend on having called"
68 << " updateGlobalMapping(..., NULL)";
69 // Check that update...() can be called before add...().
70 Engine->updateGlobalMapping(G2, &Mem1);
71 EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G2));
72 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1))
73 << "A second mapping shouldn't affect the first.";
74}
75
76TEST_F(ExecutionEngineTest, ReverseGlobalMapping) {
Mehdi Amini03b42e42016-04-14 21:59:01 +000077 GlobalVariable *G1 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000078
79 int32_t Mem1 = 3;
80 Engine->addGlobalMapping(G1, &Mem1);
81 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
82 int32_t Mem2 = 4;
83 Engine->updateGlobalMapping(G1, &Mem2);
Craig Topper66f09ad2014-06-08 22:29:17 +000084 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000085 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
86
Mehdi Amini03b42e42016-04-14 21:59:01 +000087 GlobalVariable *G2 = NewExtGlobal(Type::getInt32Ty(Context), "Global2");
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000088 Engine->updateGlobalMapping(G2, &Mem1);
89 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1));
90 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
Craig Topper66f09ad2014-06-08 22:29:17 +000091 Engine->updateGlobalMapping(G1, nullptr);
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000092 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1))
93 << "Removing one mapping doesn't affect a different one.";
Craig Topper66f09ad2014-06-08 22:29:17 +000094 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem2));
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000095 Engine->updateGlobalMapping(G2, &Mem2);
Craig Topper66f09ad2014-06-08 22:29:17 +000096 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
Jeffrey Yasskin337b1242009-08-04 23:53:16 +000097 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
Jeffrey Yasskin307c0532009-10-09 22:10:27 +0000102TEST_F(ExecutionEngineTest, ClearModuleMappings) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000103 GlobalVariable *G1 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
Jeffrey Yasskin307c0532009-10-09 22:10:27 +0000104
105 int32_t Mem1 = 3;
106 Engine->addGlobalMapping(G1, &Mem1);
107 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
108
109 Engine->clearGlobalMappingsFromModule(M);
110
Craig Topper66f09ad2014-06-08 22:29:17 +0000111 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
Jeffrey Yasskin307c0532009-10-09 22:10:27 +0000112
Mehdi Amini03b42e42016-04-14 21:59:01 +0000113 GlobalVariable *G2 = NewExtGlobal(Type::getInt32Ty(Context), "Global2");
Jeffrey Yasskin307c0532009-10-09 22:10:27 +0000114 // After clearing the module mappings, we can assign a new GV to the
115 // same address.
116 Engine->addGlobalMapping(G2, &Mem1);
117 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1));
118}
119
Jeffrey Yasskinf98e9812009-10-13 17:42:08 +0000120TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) {
Mehdi Amini03b42e42016-04-14 21:59:01 +0000121 GlobalVariable *G1 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
Jeffrey Yasskinf98e9812009-10-13 17:42:08 +0000122 int32_t Mem1 = 3;
123 Engine->addGlobalMapping(G1, &Mem1);
124 // Make sure the reverse mapping is enabled.
125 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
126 // When the GV goes away, the ExecutionEngine should remove any
127 // mappings that refer to it.
128 G1->eraseFromParent();
Craig Topper66f09ad2014-06-08 22:29:17 +0000129 EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
Jeffrey Yasskinf98e9812009-10-13 17:42:08 +0000130}
131
David Blaikiece3f5732014-09-29 21:25:13 +0000132TEST_F(ExecutionEngineTest, LookupWithMangledAndDemangledSymbol) {
133 int x;
134 int _x;
135 llvm::sys::DynamicLibrary::AddSymbol("x", &x);
136 llvm::sys::DynamicLibrary::AddSymbol("_x", &_x);
137
Lang Hames3b514552016-03-03 21:23:15 +0000138 // RTDyldMemoryManager::getSymbolAddressInProcess expects a mangled symbol,
139 // but DynamicLibrary is a wrapper for dlsym, which expects the unmangled C
140 // symbol name. This test verifies that getSymbolAddressInProcess strips the
Lang Hames75601bf2016-08-18 01:33:28 +0000141 // leading '_' on Darwin, but not on other platforms.
142#ifdef __APPLE__
Lang Hames2f27b2f2014-10-01 04:11:13 +0000143 EXPECT_EQ(reinterpret_cast<uint64_t>(&x),
144 RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
Lang Hames3b514552016-03-03 21:23:15 +0000145#else
Lang Hames2f27b2f2014-10-01 04:11:13 +0000146 EXPECT_EQ(reinterpret_cast<uint64_t>(&_x),
147 RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
Lang Hames3b514552016-03-03 21:23:15 +0000148#endif
David Blaikiece3f5732014-09-29 21:25:13 +0000149}
150
Jeffrey Yasskin337b1242009-08-04 23:53:16 +0000151}