1 //===------- JITLinkTestCommon.cpp - Common code for JITLink tests --------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "JITLinkTestCommon.h"
10 #include "llvm/MC/MCCodeEmitter.h"
11 #include "llvm/MC/MCObjectWriter.h"
12 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
13 #include "llvm/Support/TargetSelect.h"
15 using namespace llvm::jitlink
;
18 Expected
<std::unique_ptr
<JITLinkTestCommon::TestResources
>>
19 JITLinkTestCommon::TestResources::Create(StringRef AsmSrc
, StringRef TripleStr
,
20 bool PIC
, bool LargeCodeModel
,
21 MCTargetOptions Options
) {
22 Error Err
= Error::success();
23 auto R
= std::unique_ptr
<TestResources
>(new TestResources(
24 AsmSrc
, TripleStr
, PIC
, LargeCodeModel
, std::move(Options
), Err
));
26 return std::move(Err
);
31 JITLinkTestCommon::TestResources::getTestObjectBufferRef() const {
32 return MemoryBufferRef(StringRef(ObjBuffer
.data(), ObjBuffer
.size()),
36 JITLinkTestCommon::TestResources::TestResources(StringRef AsmSrc
,
37 StringRef TripleStr
, bool PIC
,
39 MCTargetOptions Options
,
41 : ObjStream(ObjBuffer
), Options(std::move(Options
)) {
42 ErrorAsOutParameter
_(&Err
);
43 Triple
TT(Triple::normalize(TripleStr
));
44 if (auto Err2
= initializeTripleSpecifics(TT
)) {
45 Err
= std::move(Err2
);
48 initializeTestSpecifics(AsmSrc
, TT
, PIC
, LargeCodeModel
);
51 Error
JITLinkTestCommon::TestResources::initializeTripleSpecifics(Triple
&TT
) {
53 TheTarget
= TargetRegistry::lookupTarget("", TT
, ErrorMsg
);
56 return make_error
<StringError
>(ErrorMsg
, inconvertibleErrorCode());
58 MRI
.reset(TheTarget
->createMCRegInfo(TT
.getTriple()));
60 report_fatal_error("Could not build MCRegisterInfo for triple");
62 MAI
.reset(TheTarget
->createMCAsmInfo(*MRI
, TT
.getTriple()));
64 report_fatal_error("Could not build MCAsmInfo for triple");
66 MCII
.reset(TheTarget
->createMCInstrInfo());
68 report_fatal_error("Could not build MCInstrInfo for triple");
70 STI
.reset(TheTarget
->createMCSubtargetInfo(TT
.getTriple(), "", ""));
72 report_fatal_error("Could not build MCSubtargetInfo for triple");
74 DisCtx
= std::make_unique
<MCContext
>(MAI
.get(), MRI
.get(), nullptr);
75 Dis
.reset(TheTarget
->createMCDisassembler(*STI
, *DisCtx
));
78 report_fatal_error("Could not build MCDisassembler");
80 return Error::success();
83 void JITLinkTestCommon::TestResources::initializeTestSpecifics(
84 StringRef AsmSrc
, const Triple
&TT
, bool PIC
, bool LargeCodeModel
) {
85 SrcMgr
.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(AsmSrc
), SMLoc());
86 AsCtx
= std::make_unique
<MCContext
>(MAI
.get(), MRI
.get(), &MOFI
, &SrcMgr
);
87 MOFI
.InitMCObjectFileInfo(TT
, PIC
, *AsCtx
, LargeCodeModel
);
89 std::unique_ptr
<MCCodeEmitter
> CE(
90 TheTarget
->createMCCodeEmitter(*MCII
, *MRI
, *AsCtx
));
92 report_fatal_error("Could not build MCCodeEmitter");
94 std::unique_ptr
<MCAsmBackend
> MAB(
95 TheTarget
->createMCAsmBackend(*STI
, *MRI
, Options
));
97 report_fatal_error("Could not build MCAsmBackend for test");
99 std::unique_ptr
<MCObjectWriter
> MOW(MAB
->createObjectWriter(ObjStream
));
101 MOS
.reset(TheTarget
->createMCObjectStreamer(
102 TT
, *AsCtx
, std::move(MAB
), std::move(MOW
), std::move(CE
), *STI
,
103 Options
.MCRelaxAll
, Options
.MCIncrementalLinkerCompatible
, false));
105 std::unique_ptr
<MCAsmParser
> MAP(
106 createMCAsmParser(SrcMgr
, *AsCtx
, *MOS
, *MAI
));
107 std::unique_ptr
<MCTargetAsmParser
> TAP(
108 TheTarget
->createMCAsmParser(*STI
, *MAP
, *MCII
, Options
));
111 report_fatal_error("Could not build MCTargetAsmParser for test");
113 MAP
->setTargetParser(*TAP
);
116 report_fatal_error("Failed to parse test case");
119 JITLinkTestCommon::TestJITLinkContext::TestJITLinkContext(
120 TestResources
&TR
, TestCaseFunction TestCase
)
121 : TR(TR
), TestCase(std::move(TestCase
)) {}
123 JITLinkTestCommon::TestJITLinkContext
&
124 JITLinkTestCommon::TestJITLinkContext::setMemoryManager(
125 std::unique_ptr
<JITLinkMemoryManager
> MM
) {
126 assert(!MemMgr
&& "Memory manager already set");
127 MemMgr
= std::move(MM
);
131 JITLinkMemoryManager
&
132 JITLinkTestCommon::TestJITLinkContext::getMemoryManager() {
134 MemMgr
= std::make_unique
<InProcessMemoryManager
>();
138 MemoryBufferRef
JITLinkTestCommon::TestJITLinkContext::getObjectBuffer() const {
139 return TR
.getTestObjectBufferRef();
142 void JITLinkTestCommon::TestJITLinkContext::notifyFailed(Error Err
) {
143 ADD_FAILURE() << "Unexpected failure: " << toString(std::move(Err
));
146 void JITLinkTestCommon::TestJITLinkContext::lookup(
147 const DenseSet
<StringRef
> &Symbols
,
148 std::unique_ptr
<JITLinkAsyncLookupContinuation
> LC
) {
149 jitlink::AsyncLookupResult LookupResult
;
150 DenseSet
<StringRef
> MissingSymbols
;
151 for (const auto &Symbol
: Symbols
) {
152 auto I
= Externals
.find(Symbol
);
153 if (I
!= Externals
.end())
154 LookupResult
[Symbol
] = I
->second
;
156 MissingSymbols
.insert(Symbol
);
159 if (MissingSymbols
.empty())
160 LC
->run(std::move(LookupResult
));
164 raw_string_ostream
ErrMsgStream(ErrMsg
);
165 ErrMsgStream
<< "Failed to resolve external symbols: [";
166 for (auto &Sym
: MissingSymbols
)
167 ErrMsgStream
<< " " << Sym
;
168 ErrMsgStream
<< " ]\n";
171 make_error
<StringError
>(std::move(ErrMsg
), inconvertibleErrorCode()));
175 void JITLinkTestCommon::TestJITLinkContext::notifyResolved(LinkGraph
&G
) {
180 void JITLinkTestCommon::TestJITLinkContext::notifyFinalized(
181 std::unique_ptr
<JITLinkMemoryManager::Allocation
> A
) {
183 NotifyFinalized(std::move(A
));
186 Error
JITLinkTestCommon::TestJITLinkContext::modifyPassConfig(
187 const Triple
&TT
, PassConfiguration
&Config
) {
189 Config
.PostFixupPasses
.push_back([&](LinkGraph
&G
) -> Error
{
191 return Error::success();
193 return Error::success();
196 JITLinkTestCommon::JITLinkTestCommon() { initializeLLVMTargets(); }
198 Expected
<std::pair
<MCInst
, size_t>>
199 JITLinkTestCommon::disassemble(const MCDisassembler
&Dis
, jitlink::Block
&B
,
201 ArrayRef
<uint8_t> InstBuffer(
202 reinterpret_cast<const uint8_t *>(B
.getContent().data()) + Offset
,
203 B
.getContent().size() - Offset
);
208 Dis
.getInstruction(Inst
, InstSize
, InstBuffer
, 0, nulls(), nulls());
210 if (Status
!= MCDisassembler::Success
)
211 return make_error
<StringError
>("Could not disassemble instruction",
212 inconvertibleErrorCode());
214 return std::make_pair(Inst
, InstSize
);
217 Expected
<int64_t> JITLinkTestCommon::decodeImmediateOperand(
218 const MCDisassembler
&Dis
, jitlink::Block
&B
, size_t OpIdx
, size_t Offset
) {
219 auto InstAndSize
= disassemble(Dis
, B
, Offset
);
221 return InstAndSize
.takeError();
223 if (OpIdx
>= InstAndSize
->first
.getNumOperands())
224 return make_error
<StringError
>("Invalid operand index",
225 inconvertibleErrorCode());
227 auto &Op
= InstAndSize
->first
.getOperand(OpIdx
);
230 return make_error
<StringError
>("Operand at index is not immediate",
231 inconvertibleErrorCode());
236 bool JITLinkTestCommon::AreTargetsInitialized
= false;
238 void JITLinkTestCommon::initializeLLVMTargets() {
239 if (!AreTargetsInitialized
) {
240 InitializeAllTargets();
241 InitializeAllTargetMCs();
242 InitializeAllAsmParsers();
243 InitializeAllAsmPrinters();
244 InitializeAllDisassemblers();
245 AreTargetsInitialized
= true;
249 } // end namespace llvm