[llvm] [cmake] Add possibility to use ChooseMSVCCRT.cmake when include LLVM library
[llvm-core.git] / unittests / ExecutionEngine / JITLink / JITLinkTestCommon.cpp
blob23f8a691c8ffefa30c8fc436fca0c005a57dc16f
1 //===------- JITLinkTestCommon.cpp - Common code for JITLink tests --------===//
2 //
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
6 //
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;
16 namespace llvm {
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));
25 if (Err)
26 return std::move(Err);
27 return std::move(R);
30 MemoryBufferRef
31 JITLinkTestCommon::TestResources::getTestObjectBufferRef() const {
32 return MemoryBufferRef(StringRef(ObjBuffer.data(), ObjBuffer.size()),
33 "Test object");
36 JITLinkTestCommon::TestResources::TestResources(StringRef AsmSrc,
37 StringRef TripleStr, bool PIC,
38 bool LargeCodeModel,
39 MCTargetOptions Options,
40 Error &Err)
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);
46 return;
48 initializeTestSpecifics(AsmSrc, TT, PIC, LargeCodeModel);
51 Error JITLinkTestCommon::TestResources::initializeTripleSpecifics(Triple &TT) {
52 std::string ErrorMsg;
53 TheTarget = TargetRegistry::lookupTarget("", TT, ErrorMsg);
55 if (!TheTarget)
56 return make_error<StringError>(ErrorMsg, inconvertibleErrorCode());
58 MRI.reset(TheTarget->createMCRegInfo(TT.getTriple()));
59 if (!MRI)
60 report_fatal_error("Could not build MCRegisterInfo for triple");
62 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TT.getTriple()));
63 if (!MAI)
64 report_fatal_error("Could not build MCAsmInfo for triple");
66 MCII.reset(TheTarget->createMCInstrInfo());
67 if (!MCII)
68 report_fatal_error("Could not build MCInstrInfo for triple");
70 STI.reset(TheTarget->createMCSubtargetInfo(TT.getTriple(), "", ""));
71 if (!STI)
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));
77 if (!Dis)
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));
91 if (!CE)
92 report_fatal_error("Could not build MCCodeEmitter");
94 std::unique_ptr<MCAsmBackend> MAB(
95 TheTarget->createMCAsmBackend(*STI, *MRI, Options));
96 if (!MAB)
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));
110 if (!TAP)
111 report_fatal_error("Could not build MCTargetAsmParser for test");
113 MAP->setTargetParser(*TAP);
115 if (MAP->Run(false))
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);
128 return *this;
131 JITLinkMemoryManager &
132 JITLinkTestCommon::TestJITLinkContext::getMemoryManager() {
133 if (!MemMgr)
134 MemMgr = std::make_unique<InProcessMemoryManager>();
135 return *MemMgr;
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 JITLinkAsyncLookupContinuation LookupContinuation) {
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;
155 else
156 MissingSymbols.insert(Symbol);
159 if (MissingSymbols.empty())
160 LookupContinuation(std::move(LookupResult));
161 else {
162 std::string ErrMsg;
164 raw_string_ostream ErrMsgStream(ErrMsg);
165 ErrMsgStream << "Failed to resolve external symbols: [";
166 for (auto &Sym : MissingSymbols)
167 ErrMsgStream << " " << Sym;
168 ErrMsgStream << " ]\n";
170 LookupContinuation(
171 make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()));
175 void JITLinkTestCommon::TestJITLinkContext::notifyResolved(AtomGraph &G) {
176 if (NotifyResolved)
177 NotifyResolved(G);
180 void JITLinkTestCommon::TestJITLinkContext::notifyFinalized(
181 std::unique_ptr<JITLinkMemoryManager::Allocation> A) {
182 if (NotifyFinalized)
183 NotifyFinalized(std::move(A));
186 Error JITLinkTestCommon::TestJITLinkContext::modifyPassConfig(
187 const Triple &TT, PassConfiguration &Config) {
188 if (TestCase)
189 Config.PostFixupPasses.push_back([&](AtomGraph &G) -> Error {
190 TestCase(G);
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,
200 jitlink::DefinedAtom &Atom, size_t Offset) {
201 ArrayRef<uint8_t> InstBuffer(
202 reinterpret_cast<const uint8_t *>(Atom.getContent().data()) + Offset,
203 Atom.getContent().size() - Offset);
205 MCInst Inst;
206 uint64_t InstSize;
207 auto Status =
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>
218 JITLinkTestCommon::decodeImmediateOperand(const MCDisassembler &Dis,
219 jitlink::DefinedAtom &Atom,
220 size_t OpIdx, size_t Offset) {
221 auto InstAndSize = disassemble(Dis, Atom, Offset);
222 if (!InstAndSize)
223 return InstAndSize.takeError();
225 if (OpIdx >= InstAndSize->first.getNumOperands())
226 return make_error<StringError>("Invalid operand index",
227 inconvertibleErrorCode());
229 auto &Op = InstAndSize->first.getOperand(OpIdx);
231 if (!Op.isImm())
232 return make_error<StringError>("Operand at index is not immediate",
233 inconvertibleErrorCode());
235 return Op.getImm();
238 bool JITLinkTestCommon::AreTargetsInitialized = false;
240 void JITLinkTestCommon::initializeLLVMTargets() {
241 if (!AreTargetsInitialized) {
242 InitializeAllTargets();
243 InitializeAllTargetMCs();
244 InitializeAllAsmParsers();
245 InitializeAllAsmPrinters();
246 InitializeAllDisassemblers();
247 AreTargetsInitialized = true;
251 } // end namespace llvm