Home | History | Annotate | Download | only in ExecutionEngine
      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 }
    131