summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp
blob: d4757e0f86e665a6d3529d90b3a71e45a032430e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "OrcTestCommon.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
#include "gtest/gtest.h"

using namespace llvm;
using namespace llvm::orc;

class LazyReexportsTest : public CoreAPIsBasedStandardTest {};

static int dummyTarget() { return 42; }

TEST_F(LazyReexportsTest, BasicLocalCallThroughManagerOperation) {
  // Create a callthrough manager for the host (if possible) and verify that
  // a call to the lazy call-through:
  // (1) Materializes the MU. This verifies that the symbol was looked up, and
  //     that we didn't arrive at the target via some other path
  // (2) Returns the expected value (which we take as proof that the call
  //     reached the target).

  auto JTMB = JITTargetMachineBuilder::detectHost();

  // Bail out if we can not detect the host.
  if (!JTMB) {
    consumeError(JTMB.takeError());
    return;
  }

  // Bail out if we can not build a local call-through manager.
  auto LCTM = createLocalLazyCallThroughManager(JTMB->getTargetTriple(), ES, 0);
  if (!LCTM) {
    consumeError(LCTM.takeError());
    return;
  }

  auto DummyTarget = ES.intern("DummyTarget");

  bool DummyTargetMaterialized = false;

  cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
      SymbolFlagsMap({{DummyTarget, JITSymbolFlags::Exported}}),
      [&](MaterializationResponsibility R) {
        DummyTargetMaterialized = true;
        R.notifyResolved(
            {{DummyTarget,
              JITEvaluatedSymbol(static_cast<JITTargetAddress>(
                                     reinterpret_cast<uintptr_t>(&dummyTarget)),
                                 JITSymbolFlags::Exported)}});
        R.notifyEmitted();
      })));

  unsigned NotifyResolvedCount = 0;
  auto NotifyResolved = LazyCallThroughManager::createNotifyResolvedFunction(
      [&](JITDylib &JD, const SymbolStringPtr &SymbolName,
          JITTargetAddress ResolvedAddr) {
        ++NotifyResolvedCount;
        return Error::success();
      });

  auto CallThroughTrampoline = cantFail((*LCTM)->getCallThroughTrampoline(
      JD, DummyTarget, std::move(NotifyResolved)));

  auto CTTPtr = reinterpret_cast<int (*)()>(
      static_cast<uintptr_t>(CallThroughTrampoline));

  // Call twice to verify nothing unexpected happens on redundant calls.
  auto Result = CTTPtr();
  (void)CTTPtr();

  EXPECT_TRUE(DummyTargetMaterialized)
      << "CallThrough did not materialize target";
  EXPECT_EQ(NotifyResolvedCount, 1U)
      << "CallThrough should have generated exactly one 'NotifyResolved' call";
  EXPECT_EQ(Result, 42) << "Failed to call through to target";
}
OpenPOWER on IntegriCloud