1 //===---- JITLinkTestCommon.h - Utilities for Orc Unit Tests ----*- C++ -*-===//
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 // Common utilities for JITLink unit tests.
11 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTCOMMON_H
15 #define LLVM_UNITTESTS_EXECUTIONENGINE_JITLINK_JITLINKTESTCOMMON_H
17 #include "llvm/ADT/Triple.h"
18 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
19 #include "llvm/MC/MCAsmBackend.h"
20 #include "llvm/MC/MCAsmInfo.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCObjectFileInfo.h"
25 #include "llvm/MC/MCObjectStreamer.h"
26 #include "llvm/MC/MCParser/MCAsmParser.h"
27 #include "llvm/MC/MCRegisterInfo.h"
28 #include "llvm/MC/MCSubtargetInfo.h"
29 #include "llvm/MC/MCTargetOptions.h"
30 #include "llvm/Support/Endian.h"
31 #include "llvm/Support/SourceMgr.h"
32 #include "llvm/Support/TargetRegistry.h"
34 #include "gtest/gtest.h"
38 class JITLinkTestCommon
{
43 static Expected
<std::unique_ptr
<TestResources
>>
44 Create(StringRef AsmSrc
, StringRef TripleStr
, bool PIC
, bool LargeCodeModel
,
45 MCTargetOptions Options
);
47 MemoryBufferRef
getTestObjectBufferRef() const;
49 const MCDisassembler
&getDisassembler() const { return *Dis
; }
52 TestResources(StringRef AsmSrc
, StringRef TripleStr
, bool PIC
,
53 bool LargeCodeModel
, MCTargetOptions Options
, Error
&Err
);
55 Error
initializeTripleSpecifics(Triple
&TT
);
56 void initializeTestSpecifics(StringRef AsmSource
, const Triple
&TT
,
57 bool PIC
, bool LargeCodeModel
);
59 const Target
*TheTarget
= nullptr;
61 SmallVector
<char, 0> ObjBuffer
;
62 raw_svector_ostream ObjStream
;
64 MCTargetOptions Options
;
65 std::unique_ptr
<MCRegisterInfo
> MRI
;
66 std::unique_ptr
<MCAsmInfo
> MAI
;
67 std::unique_ptr
<MCInstrInfo
> MCII
;
68 std::unique_ptr
<MCSubtargetInfo
> STI
;
70 MCObjectFileInfo MOFI
;
71 std::unique_ptr
<MCContext
> AsCtx
;
72 std::unique_ptr
<MCStreamer
> MOS
;
74 std::unique_ptr
<MCContext
> DisCtx
;
75 std::unique_ptr
<const MCDisassembler
> Dis
;
78 class TestJITLinkContext
: public jitlink::JITLinkContext
{
80 using TestCaseFunction
= std::function
<void(jitlink::AtomGraph
&)>;
82 using NotifyResolvedFunction
= std::function
<void(jitlink::AtomGraph
&G
)>;
84 using NotifyFinalizedFunction
= std::function
<void(
85 std::unique_ptr
<jitlink::JITLinkMemoryManager::Allocation
>)>;
87 TestJITLinkContext(TestResources
&TR
, TestCaseFunction TestCase
);
89 StringMap
<JITEvaluatedSymbol
> &externals() { return Externals
; }
92 setNotifyResolved(NotifyResolvedFunction NotifyResolved
);
95 setNotifyFinalized(NotifyFinalizedFunction NotifyFinalized
);
98 setMemoryManager(std::unique_ptr
<jitlink::JITLinkMemoryManager
> MM
);
100 jitlink::JITLinkMemoryManager
&getMemoryManager() override
;
102 MemoryBufferRef
getObjectBuffer() const override
;
104 void notifyFailed(Error Err
) override
;
107 lookup(const DenseSet
<StringRef
> &Symbols
,
108 jitlink::JITLinkAsyncLookupContinuation LookupContinuation
) override
;
110 void notifyResolved(jitlink::AtomGraph
&G
) override
;
112 void notifyFinalized(
113 std::unique_ptr
<jitlink::JITLinkMemoryManager::Allocation
> A
) override
;
115 Error
modifyPassConfig(const Triple
&TT
,
116 jitlink::PassConfiguration
&Config
) override
;
120 TestCaseFunction TestCase
;
121 NotifyResolvedFunction NotifyResolved
;
122 NotifyFinalizedFunction NotifyFinalized
;
123 std::unique_ptr
<MemoryBuffer
> ObjBuffer
;
124 std::unique_ptr
<jitlink::JITLinkMemoryManager
> MemMgr
;
125 StringMap
<JITEvaluatedSymbol
> Externals
;
130 /// Get TestResources for this target/test.
132 /// If this method fails it is likely because the target is not supported in
133 /// this build. The test should bail out without failing (possibly logging a
135 Expected
<std::unique_ptr
<TestResources
>>
136 getTestResources(StringRef AsmSrc
, StringRef Triple
, bool PIC
,
137 bool LargeCodeModel
, MCTargetOptions Options
) const {
138 return TestResources::Create(AsmSrc
, Triple
, PIC
, LargeCodeModel
,
142 template <typename T
>
143 static Expected
<T
> readInt(jitlink::AtomGraph
&G
, jitlink::DefinedAtom
&A
,
145 if (Offset
+ sizeof(T
) > A
.getContent().size())
146 return make_error
<StringError
>("Reading past end of atom content",
147 inconvertibleErrorCode());
148 return support::endian::read
<T
, 1>(A
.getContent().data() + Offset
,
152 template <typename T
>
153 static Expected
<T
> readInt(jitlink::AtomGraph
&G
, StringRef AtomName
,
155 auto DA
= G
.findDefinedAtomByName(AtomName
);
157 return DA
.takeError();
158 return readInt
<T
>(G
, *DA
);
161 static Expected
<std::pair
<MCInst
, size_t>>
162 disassemble(const MCDisassembler
&Dis
, jitlink::DefinedAtom
&Atom
,
165 static Expected
<int64_t> decodeImmediateOperand(const MCDisassembler
&Dis
,
166 jitlink::DefinedAtom
&Atom
,
170 static jitlink::Atom
&atom(jitlink::AtomGraph
&G
, StringRef Name
) {
171 return G
.getAtomByName(Name
);
174 static jitlink::DefinedAtom
&definedAtom(jitlink::AtomGraph
&G
,
176 return G
.getDefinedAtomByName(Name
);
179 static JITTargetAddress
atomAddr(jitlink::AtomGraph
&G
, StringRef Name
) {
180 return atom(G
, Name
).getAddress();
183 template <typename PredT
>
184 static size_t countEdgesMatching(jitlink::DefinedAtom
&DA
,
186 return std::count_if(DA
.edges().begin(), DA
.edges().end(), Pred
);
189 template <typename PredT
>
190 static size_t countEdgesMatching(jitlink::AtomGraph
&G
, StringRef Name
,
192 return countEdgesMatching(definedAtom(G
, Name
), Pred
);
197 static bool AreTargetsInitialized
;
198 void initializeLLVMTargets();
200 DenseMap
<StringRef
, JITEvaluatedSymbol
> Externals
;
203 } // end namespace llvm