ExecutionEngineTest.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. //===- ExecutionEngineTest.cpp - Unit tests for ExecutionEngine -----------===//
  2. //
  3. // 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
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ADT/STLExtras.h"
  9. #include "llvm/ExecutionEngine/Interpreter.h"
  10. #include "llvm/ExecutionEngine/RTDyldMemoryManager.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 "llvm/Support/DynamicLibrary.h"
  16. #include "llvm/Support/ManagedStatic.h"
  17. #include "gtest/gtest.h"
  18. using namespace llvm;
  19. namespace {
  20. class ExecutionEngineTest : public testing::Test {
  21. private:
  22. llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
  23. protected:
  24. ExecutionEngineTest() {
  25. auto Owner = std::make_unique<Module>("<main>", Context);
  26. M = Owner.get();
  27. Engine.reset(EngineBuilder(std::move(Owner)).setErrorStr(&Error).create());
  28. }
  29. void SetUp() override {
  30. ASSERT_TRUE(Engine.get() != nullptr) << "EngineBuilder returned error: '"
  31. << Error << "'";
  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. std::string Error;
  38. LLVMContext Context;
  39. Module *M; // Owned by ExecutionEngine.
  40. std::unique_ptr<ExecutionEngine> Engine;
  41. };
  42. TEST_F(ExecutionEngineTest, ForwardGlobalMapping) {
  43. GlobalVariable *G1 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
  44. int32_t Mem1 = 3;
  45. Engine->addGlobalMapping(G1, &Mem1);
  46. EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G1));
  47. EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable("Global1"));
  48. int32_t Mem2 = 4;
  49. Engine->updateGlobalMapping(G1, &Mem2);
  50. EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1));
  51. Engine->updateGlobalMapping(G1, nullptr);
  52. EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G1));
  53. Engine->updateGlobalMapping(G1, &Mem2);
  54. EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1));
  55. GlobalVariable *G2 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
  56. EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G2))
  57. << "The NULL return shouldn't depend on having called"
  58. << " updateGlobalMapping(..., NULL)";
  59. // Check that update...() can be called before add...().
  60. Engine->updateGlobalMapping(G2, &Mem1);
  61. EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G2));
  62. EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1))
  63. << "A second mapping shouldn't affect the first.";
  64. }
  65. TEST_F(ExecutionEngineTest, ReverseGlobalMapping) {
  66. GlobalVariable *G1 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
  67. int32_t Mem1 = 3;
  68. Engine->addGlobalMapping(G1, &Mem1);
  69. EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
  70. int32_t Mem2 = 4;
  71. Engine->updateGlobalMapping(G1, &Mem2);
  72. EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
  73. EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
  74. GlobalVariable *G2 = NewExtGlobal(Type::getInt32Ty(Context), "Global2");
  75. Engine->updateGlobalMapping(G2, &Mem1);
  76. EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1));
  77. EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
  78. Engine->updateGlobalMapping(G1, nullptr);
  79. EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1))
  80. << "Removing one mapping doesn't affect a different one.";
  81. EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem2));
  82. Engine->updateGlobalMapping(G2, &Mem2);
  83. EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
  84. EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem2))
  85. << "Once a mapping is removed, we can point another GV at the"
  86. << " now-free address.";
  87. }
  88. TEST_F(ExecutionEngineTest, ClearModuleMappings) {
  89. GlobalVariable *G1 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
  90. int32_t Mem1 = 3;
  91. Engine->addGlobalMapping(G1, &Mem1);
  92. EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
  93. Engine->clearGlobalMappingsFromModule(M);
  94. EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
  95. GlobalVariable *G2 = NewExtGlobal(Type::getInt32Ty(Context), "Global2");
  96. // After clearing the module mappings, we can assign a new GV to the
  97. // same address.
  98. Engine->addGlobalMapping(G2, &Mem1);
  99. EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1));
  100. }
  101. TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) {
  102. GlobalVariable *G1 = NewExtGlobal(Type::getInt32Ty(Context), "Global1");
  103. int32_t Mem1 = 3;
  104. Engine->addGlobalMapping(G1, &Mem1);
  105. // Make sure the reverse mapping is enabled.
  106. EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
  107. // When the GV goes away, the ExecutionEngine should remove any
  108. // mappings that refer to it.
  109. G1->eraseFromParent();
  110. EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
  111. }
  112. TEST_F(ExecutionEngineTest, LookupWithMangledAndDemangledSymbol) {
  113. int x;
  114. int _x;
  115. llvm::sys::DynamicLibrary::AddSymbol("x", &x);
  116. llvm::sys::DynamicLibrary::AddSymbol("_x", &_x);
  117. // RTDyldMemoryManager::getSymbolAddressInProcess expects a mangled symbol,
  118. // but DynamicLibrary is a wrapper for dlsym, which expects the unmangled C
  119. // symbol name. This test verifies that getSymbolAddressInProcess strips the
  120. // leading '_' on Darwin, but not on other platforms.
  121. #ifdef __APPLE__
  122. EXPECT_EQ(reinterpret_cast<uint64_t>(&x),
  123. RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
  124. #else
  125. EXPECT_EQ(reinterpret_cast<uint64_t>(&_x),
  126. RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
  127. #endif
  128. }
  129. }