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