forked from OSchip/llvm-project
206 lines
6.8 KiB
C++
206 lines
6.8 KiB
C++
//===---- JITLinkTestCommon.h - Utilities for Orc 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Common utilities for JITLink unit tests.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTCOMMON_H
|
|
#define LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTCOMMON_H
|
|
|
|
#include "llvm/ADT/Triple.h"
|
|
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
|
|
#include "llvm/MC/MCAsmBackend.h"
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
|
|
#include "llvm/MC/MCInstrInfo.h"
|
|
#include "llvm/MC/MCObjectFileInfo.h"
|
|
#include "llvm/MC/MCObjectStreamer.h"
|
|
#include "llvm/MC/MCParser/MCAsmParser.h"
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
|
#include "llvm/MC/MCTargetOptions.h"
|
|
#include "llvm/Support/Endian.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace llvm {
|
|
|
|
class JITLinkTestCommon {
|
|
public:
|
|
|
|
class TestResources {
|
|
public:
|
|
static Expected<std::unique_ptr<TestResources>>
|
|
Create(StringRef AsmSrc, StringRef TripleStr, bool PIC, bool LargeCodeModel,
|
|
MCTargetOptions Options);
|
|
|
|
MemoryBufferRef getTestObjectBufferRef() const;
|
|
|
|
const MCDisassembler &getDisassembler() const { return *Dis; }
|
|
|
|
private:
|
|
TestResources(StringRef AsmSrc, StringRef TripleStr, bool PIC,
|
|
bool LargeCodeModel, MCTargetOptions Options, Error &Err);
|
|
|
|
Error initializeTripleSpecifics(Triple &TT);
|
|
void initializeTestSpecifics(StringRef AsmSource, const Triple &TT,
|
|
bool PIC, bool LargeCodeModel);
|
|
|
|
const Target *TheTarget = nullptr;
|
|
SourceMgr SrcMgr;
|
|
SmallVector<char, 0> ObjBuffer;
|
|
raw_svector_ostream ObjStream;
|
|
|
|
MCTargetOptions Options;
|
|
std::unique_ptr<MCRegisterInfo> MRI;
|
|
std::unique_ptr<MCAsmInfo> MAI;
|
|
std::unique_ptr<MCInstrInfo> MCII;
|
|
std::unique_ptr<MCSubtargetInfo> STI;
|
|
|
|
MCObjectFileInfo MOFI;
|
|
std::unique_ptr<MCContext> AsCtx;
|
|
std::unique_ptr<MCStreamer> MOS;
|
|
|
|
std::unique_ptr<MCContext> DisCtx;
|
|
std::unique_ptr<const MCDisassembler> Dis;
|
|
};
|
|
|
|
class TestJITLinkContext : public jitlink::JITLinkContext {
|
|
public:
|
|
using TestCaseFunction = std::function<void(jitlink::AtomGraph &)>;
|
|
|
|
using NotifyResolvedFunction = std::function<void(jitlink::AtomGraph &G)>;
|
|
|
|
using NotifyFinalizedFunction = std::function<void(
|
|
std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>)>;
|
|
|
|
TestJITLinkContext(TestResources &TR, TestCaseFunction TestCase);
|
|
|
|
StringMap<JITEvaluatedSymbol> &externals() { return Externals; }
|
|
|
|
TestJITLinkContext &
|
|
setNotifyResolved(NotifyResolvedFunction NotifyResolved);
|
|
|
|
TestJITLinkContext &
|
|
setNotifyFinalized(NotifyFinalizedFunction NotifyFinalized);
|
|
|
|
TestJITLinkContext &
|
|
setMemoryManager(std::unique_ptr<jitlink::JITLinkMemoryManager> MM);
|
|
|
|
jitlink::JITLinkMemoryManager &getMemoryManager() override;
|
|
|
|
MemoryBufferRef getObjectBuffer() const override;
|
|
|
|
void notifyFailed(Error Err) override;
|
|
|
|
void
|
|
lookup(const DenseSet<StringRef> &Symbols,
|
|
jitlink::JITLinkAsyncLookupContinuation LookupContinuation) override;
|
|
|
|
void notifyResolved(jitlink::AtomGraph &G) override;
|
|
|
|
void notifyFinalized(
|
|
std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation> A) override;
|
|
|
|
Error modifyPassConfig(const Triple &TT,
|
|
jitlink::PassConfiguration &Config) override;
|
|
|
|
private:
|
|
TestResources &TR;
|
|
TestCaseFunction TestCase;
|
|
NotifyResolvedFunction NotifyResolved;
|
|
NotifyFinalizedFunction NotifyFinalized;
|
|
std::unique_ptr<MemoryBuffer> ObjBuffer;
|
|
std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr;
|
|
StringMap<JITEvaluatedSymbol> Externals;
|
|
};
|
|
|
|
JITLinkTestCommon();
|
|
|
|
/// Get TestResources for this target/test.
|
|
///
|
|
/// If this method fails it is likely because the target is not supported in
|
|
/// this build. The test should bail out without failing (possibly logging a
|
|
/// diagnostic).
|
|
Expected<std::unique_ptr<TestResources>>
|
|
getTestResources(StringRef AsmSrc, StringRef Triple, bool PIC,
|
|
bool LargeCodeModel, MCTargetOptions Options) const {
|
|
return TestResources::Create(AsmSrc, Triple, PIC, LargeCodeModel,
|
|
std::move(Options));
|
|
}
|
|
|
|
template <typename T>
|
|
static Expected<T> readInt(jitlink::AtomGraph &G, jitlink::DefinedAtom &A,
|
|
size_t Offset = 0) {
|
|
if (Offset + sizeof(T) > A.getContent().size())
|
|
return make_error<StringError>("Reading past end of atom content",
|
|
inconvertibleErrorCode());
|
|
return support::endian::read<T, 1>(A.getContent().data() + Offset,
|
|
G.getEndianness());
|
|
}
|
|
|
|
template <typename T>
|
|
static Expected<T> readInt(jitlink::AtomGraph &G, StringRef AtomName,
|
|
size_t Offset = 0) {
|
|
auto DA = G.findDefinedAtomByName(AtomName);
|
|
if (!DA)
|
|
return DA.takeError();
|
|
return readInt<T>(G, *DA);
|
|
}
|
|
|
|
static Expected<std::pair<MCInst, size_t>>
|
|
disassemble(const MCDisassembler &Dis, jitlink::DefinedAtom &Atom,
|
|
size_t Offset = 0);
|
|
|
|
static Expected<int64_t> decodeImmediateOperand(const MCDisassembler &Dis,
|
|
jitlink::DefinedAtom &Atom,
|
|
size_t OpIdx,
|
|
size_t Offset = 0);
|
|
|
|
static jitlink::Atom &atom(jitlink::AtomGraph &G, StringRef Name) {
|
|
return G.getAtomByName(Name);
|
|
}
|
|
|
|
static jitlink::DefinedAtom &definedAtom(jitlink::AtomGraph &G,
|
|
StringRef Name) {
|
|
return G.getDefinedAtomByName(Name);
|
|
}
|
|
|
|
static JITTargetAddress atomAddr(jitlink::AtomGraph &G, StringRef Name) {
|
|
return atom(G, Name).getAddress();
|
|
}
|
|
|
|
template <typename PredT>
|
|
static size_t countEdgesMatching(jitlink::DefinedAtom &DA,
|
|
const PredT &Pred) {
|
|
return std::count_if(DA.edges().begin(), DA.edges().end(), Pred);
|
|
}
|
|
|
|
template <typename PredT>
|
|
static size_t countEdgesMatching(jitlink::AtomGraph &G, StringRef Name,
|
|
const PredT &Pred) {
|
|
return countEdgesMatching(definedAtom(G, Name), Pred);
|
|
}
|
|
|
|
private:
|
|
|
|
static bool AreTargetsInitialized;
|
|
void initializeLLVMTargets();
|
|
|
|
DenseMap<StringRef, JITEvaluatedSymbol> Externals;
|
|
};
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif
|