76 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			76 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C++
		
	
	
	
#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(llvm::make_unique<SimpleMaterializationUnit>(
 | 
						|
      SymbolFlagsMap({{DummyTarget, JITSymbolFlags::Exported}}),
 | 
						|
      [&](MaterializationResponsibility R) {
 | 
						|
        DummyTargetMaterialized = true;
 | 
						|
        R.resolve(
 | 
						|
            {{DummyTarget,
 | 
						|
              JITEvaluatedSymbol(static_cast<JITTargetAddress>(
 | 
						|
                                     reinterpret_cast<uintptr_t>(&dummyTarget)),
 | 
						|
                                 JITSymbolFlags::Exported)}});
 | 
						|
        R.emit();
 | 
						|
      })));
 | 
						|
 | 
						|
  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";
 | 
						|
}
 |