blob: 74a2ccdd0663011ed242d1e98ab1750ed0e2ec8c [file] [log] [blame]
Jeffrey Yasskin0a962312009-08-04 23:53:16 +00001//===- 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
18using namespace llvm;
19
20namespace {
21
22class ExecutionEngineTest : public testing::Test {
23protected:
24 ExecutionEngineTest()
Dylan Noblesmith35af1d72011-12-02 20:53:53 +000025 : M(new Module("<main>", getGlobalContext())), Error(""),
26 Engine(EngineBuilder(M).setErrorStr(&Error).create()) {
Jeffrey Yasskin0a962312009-08-04 23:53:16 +000027 }
28
29 virtual void SetUp() {
Dylan Noblesmith35af1d72011-12-02 20:53:53 +000030 ASSERT_TRUE(Engine.get() != NULL) << "EngineBuilder returned error: '"
31 << Error << "'";
Jeffrey Yasskin0a962312009-08-04 23:53:16 +000032 }
33
Chris Lattnerdb125cf2011-07-18 04:54:35 +000034 GlobalVariable *NewExtGlobal(Type *T, const Twine &Name) {
Jeffrey Yasskin0a962312009-08-04 23:53:16 +000035 return new GlobalVariable(*M, T, false, // Not constant.
36 GlobalValue::ExternalLinkage, NULL, Name);
37 }
38
39 Module *const M;
Dylan Noblesmith35af1d72011-12-02 20:53:53 +000040 std::string Error;
Jeffrey Yasskin0a962312009-08-04 23:53:16 +000041 const OwningPtr<ExecutionEngine> Engine;
42};
43
44TEST_F(ExecutionEngineTest, ForwardGlobalMapping) {
Owen Anderson1d0be152009-08-13 21:58:54 +000045 GlobalVariable *G1 =
46 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1");
Jeffrey Yasskin0a962312009-08-04 23:53:16 +000047 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, NULL);
54 EXPECT_EQ(NULL, Engine->getPointerToGlobalIfAvailable(G1));
55 Engine->updateGlobalMapping(G1, &Mem2);
56 EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1));
57
Owen Anderson1d0be152009-08-13 21:58:54 +000058 GlobalVariable *G2 =
59 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1");
Jeffrey Yasskin0a962312009-08-04 23:53:16 +000060 EXPECT_EQ(NULL, 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
70TEST_F(ExecutionEngineTest, ReverseGlobalMapping) {
Owen Anderson1d0be152009-08-13 21:58:54 +000071 GlobalVariable *G1 =
72 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1");
Jeffrey Yasskin0a962312009-08-04 23:53:16 +000073
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(NULL, Engine->getGlobalValueAtAddress(&Mem1));
80 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
81
Owen Anderson1d0be152009-08-13 21:58:54 +000082 GlobalVariable *G2 =
83 NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2");
Jeffrey Yasskin0a962312009-08-04 23:53:16 +000084 Engine->updateGlobalMapping(G2, &Mem1);
85 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1));
86 EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
87 Engine->updateGlobalMapping(G1, NULL);
88 EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1))
89 << "Removing one mapping doesn't affect a different one.";
90 EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem2));
91 Engine->updateGlobalMapping(G2, &Mem2);
92 EXPECT_EQ(NULL, 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
Jeffrey Yasskinc89d27a2009-10-09 22:10:27 +000098TEST_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(NULL, 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
Jeffrey Yasskin4c5b23b2009-10-13 17:42:08 +0000118TEST_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(NULL, Engine->getGlobalValueAtAddress(&Mem1));
129}
130
Jeffrey Yasskin0a962312009-08-04 23:53:16 +0000131}