Make ExecutionEngine::updateGlobalMapping(GV, NULL) properly remove GV's old
authorJeffrey Yasskin <jyasskin@google.com>
Tue, 4 Aug 2009 23:53:16 +0000 (23:53 +0000)
committerJeffrey Yasskin <jyasskin@google.com>
Tue, 4 Aug 2009 23:53:16 +0000 (23:53 +0000)
address from the reverse mapping, and add a test that this works now.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78127 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ExecutionEngine/ExecutionEngine.cpp
unittests/ExecutionEngine/ExecutionEngineTest.cpp [new file with mode: 0644]
unittests/ExecutionEngine/Makefile

index 8a999da3d3fe9fbe27af85d5c050ed27d3ed1c9d..e827d36f8617ecc7e1d25a34eb5f4b1ba1c48dae 100644 (file)
@@ -179,7 +179,7 @@ void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) {
     }
     
     if (!state.getGlobalAddressReverseMap(locked).empty())
-      state.getGlobalAddressReverseMap(locked).erase(Addr);
+      state.getGlobalAddressReverseMap(locked).erase(OldVal);
     return OldVal;
   }
   
diff --git a/unittests/ExecutionEngine/ExecutionEngineTest.cpp b/unittests/ExecutionEngine/ExecutionEngineTest.cpp
new file mode 100644 (file)
index 0000000..8478ebd
--- /dev/null
@@ -0,0 +1,92 @@
+//===- ExecutionEngineTest.cpp - Unit tests for ExecutionEngine -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ExecutionEngine/Interpreter.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class ExecutionEngineTest : public testing::Test {
+protected:
+  ExecutionEngineTest()
+    : M(new Module("<main>", getGlobalContext())),
+      Engine(EngineBuilder(M).create()) {
+  }
+
+  virtual void SetUp() {
+    ASSERT_TRUE(Engine.get() != NULL);
+  }
+
+  GlobalVariable *NewExtGlobal(const Type *T, const Twine &Name) {
+    return new GlobalVariable(*M, T, false,  // Not constant.
+                              GlobalValue::ExternalLinkage, NULL, Name);
+  }
+
+  Module *const M;
+  const OwningPtr<ExecutionEngine> Engine;
+};
+
+TEST_F(ExecutionEngineTest, ForwardGlobalMapping) {
+  GlobalVariable *G1 = NewExtGlobal(Type::Int32Ty, "Global1");
+  int32_t Mem1 = 3;
+  Engine->addGlobalMapping(G1, &Mem1);
+  EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G1));
+  int32_t Mem2 = 4;
+  Engine->updateGlobalMapping(G1, &Mem2);
+  EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1));
+  Engine->updateGlobalMapping(G1, NULL);
+  EXPECT_EQ(NULL, Engine->getPointerToGlobalIfAvailable(G1));
+  Engine->updateGlobalMapping(G1, &Mem2);
+  EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1));
+
+  GlobalVariable *G2 = NewExtGlobal(Type::Int32Ty, "Global1");
+  EXPECT_EQ(NULL, Engine->getPointerToGlobalIfAvailable(G2))
+    << "The NULL return shouldn't depend on having called"
+    << " updateGlobalMapping(..., NULL)";
+  // Check that update...() can be called before add...().
+  Engine->updateGlobalMapping(G2, &Mem1);
+  EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G2));
+  EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1))
+    << "A second mapping shouldn't affect the first.";
+}
+
+TEST_F(ExecutionEngineTest, ReverseGlobalMapping) {
+  GlobalVariable *G1 = NewExtGlobal(Type::Int32Ty, "Global1");
+
+  int32_t Mem1 = 3;
+  Engine->addGlobalMapping(G1, &Mem1);
+  EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
+  int32_t Mem2 = 4;
+  Engine->updateGlobalMapping(G1, &Mem2);
+  EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1));
+  EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
+
+  GlobalVariable *G2 = NewExtGlobal(Type::Int32Ty, "Global2");
+  Engine->updateGlobalMapping(G2, &Mem1);
+  EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1));
+  EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
+  Engine->updateGlobalMapping(G1, NULL);
+  EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1))
+    << "Removing one mapping doesn't affect a different one.";
+  EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem2));
+  Engine->updateGlobalMapping(G2, &Mem2);
+  EXPECT_EQ(NULL, Engine->getGlobalValueAtAddress(&Mem1));
+  EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem2))
+    << "Once a mapping is removed, we can point another GV at the"
+    << " now-free address.";
+}
+
+}
index e837a7d4fd3e6a3ab894da6e628f4f887cb29ecd..d4ef92ffb392fb1d3d272bbea38ce95415db79dd 100644 (file)
@@ -8,12 +8,11 @@
 ##===----------------------------------------------------------------------===##
 
 LEVEL = ../..
+TESTNAME = ExecutionEngine
+LINK_COMPONENTS := engine interpreter
 
 include $(LEVEL)/Makefile.config
 
 PARALLEL_DIRS = JIT
 
-include $(LEVEL)/Makefile.common
-
-clean::
-       $(Verb) $(RM) -f *Tests
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest