Files
clang-p2996/llvm/unittests/ExecutionEngine/JITLink/JITLinkTestUtils.h
Lang Hames 6128ff6630 [JITLink][MachO] Add convenience functions for default text/data sections.
The getMachODefaultTextSection and getMachODefaultRWDataSection functions
return the "__TEXT,__text" and "__DATA,__data" sections respectively, creating
empty sections if the default sections are not already present in the graph.
These functions can be used by utilities that want to add code or data to these
standard sections (e.g. these functions can be used to supply the section
argument to the createAnonymousPointerJumpStub and
createPointerJumpStubBlock functions in the various targets).
2024-10-28 18:05:40 -07:00

231 lines
7.4 KiB
C++

//===--- JITLinkTestUtils.h - Utilities for JITLink unit tests --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Utilities for JITLink unit tests.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTUTILS_H
#define LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTUTILS_H
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
class MockJITLinkMemoryManager : public llvm::jitlink::JITLinkMemoryManager {
public:
class Alloc {
public:
virtual ~Alloc() {}
};
class SimpleAlloc : public Alloc {
public:
SimpleAlloc(const llvm::jitlink::JITLinkDylib *JD,
llvm::jitlink::LinkGraph &G) {
for (auto *B : G.blocks())
(void)B->getMutableContent(G);
}
};
class MockInFlightAlloc : public InFlightAlloc {
public:
MockInFlightAlloc(MockJITLinkMemoryManager &MJMM, std::unique_ptr<Alloc> A)
: MJMM(MJMM), A(std::move(A)) {}
void abandon(OnAbandonedFunction OnAbandoned) override {
OnAbandoned(MJMM.Abandon(std::move(A)));
}
void finalize(OnFinalizedFunction OnFinalized) override {
OnFinalized(MJMM.Finalize(std::move(A)));
}
private:
MockJITLinkMemoryManager &MJMM;
std::unique_ptr<Alloc> A;
};
MockJITLinkMemoryManager() {
Allocate = [this](const llvm::jitlink::JITLinkDylib *JD,
llvm::jitlink::LinkGraph &G) {
return defaultAllocate(JD, G);
};
Deallocate = [this](std::vector<FinalizedAlloc> Allocs) {
return defaultDeallocate(std::move(Allocs));
};
Abandon = [this](std::unique_ptr<Alloc> A) {
return defaultAbandon(std::move(A));
};
Finalize = [this](std::unique_ptr<Alloc> A) {
return defaultFinalize(std::move(A));
};
}
void allocate(const llvm::jitlink::JITLinkDylib *JD,
llvm::jitlink::LinkGraph &G,
OnAllocatedFunction OnAllocated) override {
auto A = Allocate(JD, G);
if (!A)
OnAllocated(A.takeError());
else
OnAllocated(std::make_unique<MockInFlightAlloc>(*this, std::move(*A)));
}
void deallocate(std::vector<FinalizedAlloc> Allocs,
OnDeallocatedFunction OnDeallocated) override {
OnDeallocated(Deallocate(std::move(Allocs)));
}
using JITLinkMemoryManager::allocate;
using JITLinkMemoryManager::deallocate;
llvm::Expected<std::unique_ptr<Alloc>>
defaultAllocate(const llvm::jitlink::JITLinkDylib *JD,
llvm::jitlink::LinkGraph &G) {
return std::make_unique<SimpleAlloc>(JD, G);
}
llvm::Error defaultDeallocate(std::vector<FinalizedAlloc> Allocs) {
for (auto &A : Allocs)
delete A.release().toPtr<Alloc *>();
return llvm::Error::success();
}
llvm::Error defaultAbandon(std::unique_ptr<Alloc> A) {
return llvm::Error::success();
}
llvm::Expected<FinalizedAlloc> defaultFinalize(std::unique_ptr<Alloc> A) {
return FinalizedAlloc(llvm::orc::ExecutorAddr::fromPtr(A.release()));
}
llvm::unique_function<llvm::Expected<std::unique_ptr<Alloc>>(
const llvm::jitlink::JITLinkDylib *, llvm::jitlink::LinkGraph &)>
Allocate;
llvm::unique_function<llvm::Error(std::vector<FinalizedAlloc>)> Deallocate;
llvm::unique_function<llvm::Error(std::unique_ptr<Alloc>)> Abandon;
llvm::unique_function<llvm::Expected<FinalizedAlloc>(std::unique_ptr<Alloc>)>
Finalize;
};
void lookupResolveEverythingToNull(
const llvm::jitlink::JITLinkContext::LookupMap &Symbols,
std::unique_ptr<llvm::jitlink::JITLinkAsyncLookupContinuation> LC);
void lookupErrorOut(
const llvm::jitlink::JITLinkContext::LookupMap &Symbols,
std::unique_ptr<llvm::jitlink::JITLinkAsyncLookupContinuation> LC);
class MockJITLinkContext : public llvm::jitlink::JITLinkContext {
public:
using HandleFailedFn = llvm::unique_function<void(llvm::Error)>;
MockJITLinkContext(std::unique_ptr<MockJITLinkMemoryManager> MJMM,
HandleFailedFn HandleFailed)
: JITLinkContext(&JD), MJMM(std::move(MJMM)),
HandleFailed(std::move(HandleFailed)) {}
~MockJITLinkContext() {
if (auto Err = MJMM->deallocate(std::move(FinalizedAllocs)))
notifyFailed(std::move(Err));
}
llvm::jitlink::JITLinkMemoryManager &getMemoryManager() override {
return *MJMM;
}
void notifyFailed(llvm::Error Err) override { HandleFailed(std::move(Err)); }
void lookup(const LookupMap &Symbols,
std::unique_ptr<llvm::jitlink::JITLinkAsyncLookupContinuation> LC)
override {
Lookup(Symbols, std::move(LC));
}
llvm::Error notifyResolved(llvm::jitlink::LinkGraph &G) override {
return NotifyResolved ? NotifyResolved(G) : llvm::Error::success();
}
void notifyFinalized(
llvm::jitlink::JITLinkMemoryManager::FinalizedAlloc Alloc) override {
if (NotifyFinalized)
NotifyFinalized(std::move(Alloc));
else
FinalizedAllocs.push_back(std::move(Alloc));
}
bool shouldAddDefaultTargetPasses(const llvm::Triple &TT) const override {
return true;
}
llvm::jitlink::LinkGraphPassFunction
getMarkLivePass(const llvm::Triple &TT) const override {
return MarkLivePass ? llvm::jitlink::LinkGraphPassFunction(
[this](llvm::jitlink::LinkGraph &G) {
return MarkLivePass(G);
})
: llvm::jitlink::LinkGraphPassFunction(
[](llvm::jitlink::LinkGraph &G) {
return markAllSymbolsLive(G);
});
}
llvm::Error
modifyPassConfig(llvm::jitlink::LinkGraph &G,
llvm::jitlink::PassConfiguration &Config) override {
if (ModifyPassConfig)
return ModifyPassConfig(G, Config);
return llvm::Error::success();
}
llvm::jitlink::JITLinkDylib JD{"JD"};
std::unique_ptr<MockJITLinkMemoryManager> MJMM;
HandleFailedFn HandleFailed;
llvm::unique_function<void(
const LookupMap &,
std::unique_ptr<llvm::jitlink::JITLinkAsyncLookupContinuation>)>
Lookup;
llvm::unique_function<llvm::Error(llvm::jitlink::LinkGraph &)> NotifyResolved;
llvm::unique_function<void(
llvm::jitlink::JITLinkMemoryManager::FinalizedAlloc)>
NotifyFinalized;
mutable llvm::unique_function<llvm::Error(llvm::jitlink::LinkGraph &)>
MarkLivePass;
llvm::unique_function<llvm::Error(llvm::jitlink::LinkGraph &,
llvm::jitlink::PassConfiguration &)>
ModifyPassConfig;
std::vector<llvm::jitlink::JITLinkMemoryManager::FinalizedAlloc>
FinalizedAllocs;
};
std::unique_ptr<MockJITLinkContext> makeMockContext(
llvm::unique_function<void(llvm::Error)> HandleFailed,
llvm::unique_function<void(MockJITLinkMemoryManager &)> SetupMemMgr,
llvm::unique_function<void(MockJITLinkContext &)> SetupContext);
void defaultMemMgrSetup(MockJITLinkMemoryManager &);
void defaultCtxSetup(MockJITLinkContext &);
class JoinErrorsInto {
public:
JoinErrorsInto(llvm::Error &Err) : Err(Err) {}
void operator()(llvm::Error E2) {
Err = llvm::joinErrors(std::move(Err), std::move(E2));
}
private:
llvm::Error &Err;
};
extern llvm::ArrayRef<char> BlockContent;
#endif // LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTUTILS_H