mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
8898b1be97
MipsMCAsmInfo was using '$' prefix for Mips32 and '.L' for Mips64 regardless of -target-abi option. By passing MCTargetOptions to MCAsmInfo we can find out Mips ABI and pick appropriate prefix. Tags: #llvm, #clang, #lldb Differential Revision: https://reviews.llvm.org/D66795
252 lines
8.3 KiB
C++
252 lines
8.3 KiB
C++
//===------- JITLinkTestCommon.cpp - Common code for JITLink tests --------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "JITLinkTestCommon.h"
|
|
#include "llvm/MC/MCCodeEmitter.h"
|
|
#include "llvm/MC/MCObjectWriter.h"
|
|
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
|
|
#include "llvm/MC/MCTargetOptions.h"
|
|
#include "llvm/Support/TargetSelect.h"
|
|
|
|
using namespace llvm::jitlink;
|
|
namespace llvm {
|
|
|
|
Expected<std::unique_ptr<JITLinkTestCommon::TestResources>>
|
|
JITLinkTestCommon::TestResources::Create(StringRef AsmSrc, StringRef TripleStr,
|
|
bool PIC, bool LargeCodeModel,
|
|
MCTargetOptions Options) {
|
|
Error Err = Error::success();
|
|
auto R = std::unique_ptr<TestResources>(new TestResources(
|
|
AsmSrc, TripleStr, PIC, LargeCodeModel, std::move(Options), Err));
|
|
if (Err)
|
|
return std::move(Err);
|
|
return std::move(R);
|
|
}
|
|
|
|
MemoryBufferRef
|
|
JITLinkTestCommon::TestResources::getTestObjectBufferRef() const {
|
|
return MemoryBufferRef(StringRef(ObjBuffer.data(), ObjBuffer.size()),
|
|
"Test object");
|
|
}
|
|
|
|
JITLinkTestCommon::TestResources::TestResources(StringRef AsmSrc,
|
|
StringRef TripleStr, bool PIC,
|
|
bool LargeCodeModel,
|
|
MCTargetOptions Options,
|
|
Error &Err)
|
|
: ObjStream(ObjBuffer), Options(std::move(Options)) {
|
|
ErrorAsOutParameter _(&Err);
|
|
Triple TT(Triple::normalize(TripleStr));
|
|
if (auto Err2 = initializeTripleSpecifics(TT)) {
|
|
Err = std::move(Err2);
|
|
return;
|
|
}
|
|
initializeTestSpecifics(AsmSrc, TT, PIC, LargeCodeModel);
|
|
}
|
|
|
|
Error JITLinkTestCommon::TestResources::initializeTripleSpecifics(Triple &TT) {
|
|
std::string ErrorMsg;
|
|
TheTarget = TargetRegistry::lookupTarget("", TT, ErrorMsg);
|
|
|
|
if (!TheTarget)
|
|
return make_error<StringError>(ErrorMsg, inconvertibleErrorCode());
|
|
|
|
MRI.reset(TheTarget->createMCRegInfo(TT.getTriple()));
|
|
if (!MRI)
|
|
report_fatal_error("Could not build MCRegisterInfo for triple");
|
|
|
|
MCTargetOptions MCOptions;
|
|
MAI.reset(TheTarget->createMCAsmInfo(*MRI, TT.getTriple(), MCOptions));
|
|
if (!MAI)
|
|
report_fatal_error("Could not build MCAsmInfo for triple");
|
|
|
|
MCII.reset(TheTarget->createMCInstrInfo());
|
|
if (!MCII)
|
|
report_fatal_error("Could not build MCInstrInfo for triple");
|
|
|
|
STI.reset(TheTarget->createMCSubtargetInfo(TT.getTriple(), "", ""));
|
|
if (!STI)
|
|
report_fatal_error("Could not build MCSubtargetInfo for triple");
|
|
|
|
DisCtx = std::make_unique<MCContext>(MAI.get(), MRI.get(), nullptr);
|
|
Dis.reset(TheTarget->createMCDisassembler(*STI, *DisCtx));
|
|
|
|
if (!Dis)
|
|
report_fatal_error("Could not build MCDisassembler");
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
void JITLinkTestCommon::TestResources::initializeTestSpecifics(
|
|
StringRef AsmSrc, const Triple &TT, bool PIC, bool LargeCodeModel) {
|
|
SrcMgr.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(AsmSrc), SMLoc());
|
|
AsCtx = std::make_unique<MCContext>(MAI.get(), MRI.get(), &MOFI, &SrcMgr);
|
|
MOFI.InitMCObjectFileInfo(TT, PIC, *AsCtx, LargeCodeModel);
|
|
|
|
std::unique_ptr<MCCodeEmitter> CE(
|
|
TheTarget->createMCCodeEmitter(*MCII, *MRI, *AsCtx));
|
|
if (!CE)
|
|
report_fatal_error("Could not build MCCodeEmitter");
|
|
|
|
std::unique_ptr<MCAsmBackend> MAB(
|
|
TheTarget->createMCAsmBackend(*STI, *MRI, Options));
|
|
if (!MAB)
|
|
report_fatal_error("Could not build MCAsmBackend for test");
|
|
|
|
std::unique_ptr<MCObjectWriter> MOW(MAB->createObjectWriter(ObjStream));
|
|
|
|
MOS.reset(TheTarget->createMCObjectStreamer(
|
|
TT, *AsCtx, std::move(MAB), std::move(MOW), std::move(CE), *STI,
|
|
Options.MCRelaxAll, Options.MCIncrementalLinkerCompatible, false));
|
|
|
|
std::unique_ptr<MCAsmParser> MAP(
|
|
createMCAsmParser(SrcMgr, *AsCtx, *MOS, *MAI));
|
|
std::unique_ptr<MCTargetAsmParser> TAP(
|
|
TheTarget->createMCAsmParser(*STI, *MAP, *MCII, Options));
|
|
|
|
if (!TAP)
|
|
report_fatal_error("Could not build MCTargetAsmParser for test");
|
|
|
|
MAP->setTargetParser(*TAP);
|
|
|
|
if (MAP->Run(false))
|
|
report_fatal_error("Failed to parse test case");
|
|
}
|
|
|
|
JITLinkTestCommon::TestJITLinkContext::TestJITLinkContext(
|
|
TestResources &TR, TestCaseFunction TestCase)
|
|
: TR(TR), TestCase(std::move(TestCase)) {}
|
|
|
|
JITLinkTestCommon::TestJITLinkContext &
|
|
JITLinkTestCommon::TestJITLinkContext::setMemoryManager(
|
|
std::unique_ptr<JITLinkMemoryManager> MM) {
|
|
assert(!MemMgr && "Memory manager already set");
|
|
MemMgr = std::move(MM);
|
|
return *this;
|
|
}
|
|
|
|
JITLinkMemoryManager &
|
|
JITLinkTestCommon::TestJITLinkContext::getMemoryManager() {
|
|
if (!MemMgr)
|
|
MemMgr = std::make_unique<InProcessMemoryManager>();
|
|
return *MemMgr;
|
|
}
|
|
|
|
MemoryBufferRef JITLinkTestCommon::TestJITLinkContext::getObjectBuffer() const {
|
|
return TR.getTestObjectBufferRef();
|
|
}
|
|
|
|
void JITLinkTestCommon::TestJITLinkContext::notifyFailed(Error Err) {
|
|
ADD_FAILURE() << "Unexpected failure: " << toString(std::move(Err));
|
|
}
|
|
|
|
void JITLinkTestCommon::TestJITLinkContext::lookup(
|
|
const DenseSet<StringRef> &Symbols,
|
|
std::unique_ptr<JITLinkAsyncLookupContinuation> LC) {
|
|
jitlink::AsyncLookupResult LookupResult;
|
|
DenseSet<StringRef> MissingSymbols;
|
|
for (const auto &Symbol : Symbols) {
|
|
auto I = Externals.find(Symbol);
|
|
if (I != Externals.end())
|
|
LookupResult[Symbol] = I->second;
|
|
else
|
|
MissingSymbols.insert(Symbol);
|
|
}
|
|
|
|
if (MissingSymbols.empty())
|
|
LC->run(std::move(LookupResult));
|
|
else {
|
|
std::string ErrMsg;
|
|
{
|
|
raw_string_ostream ErrMsgStream(ErrMsg);
|
|
ErrMsgStream << "Failed to resolve external symbols: [";
|
|
for (auto &Sym : MissingSymbols)
|
|
ErrMsgStream << " " << Sym;
|
|
ErrMsgStream << " ]\n";
|
|
}
|
|
LC->run(
|
|
make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()));
|
|
}
|
|
}
|
|
|
|
void JITLinkTestCommon::TestJITLinkContext::notifyResolved(LinkGraph &G) {
|
|
if (NotifyResolved)
|
|
NotifyResolved(G);
|
|
}
|
|
|
|
void JITLinkTestCommon::TestJITLinkContext::notifyFinalized(
|
|
std::unique_ptr<JITLinkMemoryManager::Allocation> A) {
|
|
if (NotifyFinalized)
|
|
NotifyFinalized(std::move(A));
|
|
}
|
|
|
|
Error JITLinkTestCommon::TestJITLinkContext::modifyPassConfig(
|
|
const Triple &TT, PassConfiguration &Config) {
|
|
if (TestCase)
|
|
Config.PostFixupPasses.push_back([&](LinkGraph &G) -> Error {
|
|
TestCase(G);
|
|
return Error::success();
|
|
});
|
|
return Error::success();
|
|
}
|
|
|
|
JITLinkTestCommon::JITLinkTestCommon() { initializeLLVMTargets(); }
|
|
|
|
Expected<std::pair<MCInst, size_t>>
|
|
JITLinkTestCommon::disassemble(const MCDisassembler &Dis, jitlink::Block &B,
|
|
size_t Offset) {
|
|
ArrayRef<uint8_t> InstBuffer(
|
|
reinterpret_cast<const uint8_t *>(B.getContent().data()) + Offset,
|
|
B.getContent().size() - Offset);
|
|
|
|
MCInst Inst;
|
|
uint64_t InstSize;
|
|
auto Status =
|
|
Dis.getInstruction(Inst, InstSize, InstBuffer, 0, nulls(), nulls());
|
|
|
|
if (Status != MCDisassembler::Success)
|
|
return make_error<StringError>("Could not disassemble instruction",
|
|
inconvertibleErrorCode());
|
|
|
|
return std::make_pair(Inst, InstSize);
|
|
}
|
|
|
|
Expected<int64_t> JITLinkTestCommon::decodeImmediateOperand(
|
|
const MCDisassembler &Dis, jitlink::Block &B, size_t OpIdx, size_t Offset) {
|
|
auto InstAndSize = disassemble(Dis, B, Offset);
|
|
if (!InstAndSize)
|
|
return InstAndSize.takeError();
|
|
|
|
if (OpIdx >= InstAndSize->first.getNumOperands())
|
|
return make_error<StringError>("Invalid operand index",
|
|
inconvertibleErrorCode());
|
|
|
|
auto &Op = InstAndSize->first.getOperand(OpIdx);
|
|
|
|
if (!Op.isImm())
|
|
return make_error<StringError>("Operand at index is not immediate",
|
|
inconvertibleErrorCode());
|
|
|
|
return Op.getImm();
|
|
}
|
|
|
|
bool JITLinkTestCommon::AreTargetsInitialized = false;
|
|
|
|
void JITLinkTestCommon::initializeLLVMTargets() {
|
|
if (!AreTargetsInitialized) {
|
|
InitializeAllTargets();
|
|
InitializeAllTargetMCs();
|
|
InitializeAllAsmParsers();
|
|
InitializeAllAsmPrinters();
|
|
InitializeAllDisassemblers();
|
|
AreTargetsInitialized = true;
|
|
}
|
|
}
|
|
|
|
} // end namespace llvm
|