1 | //===- CompileUtils.h - Utilities for compiling IR in the JIT ---*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // Contains utilities for compiling IR to object files. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H |
15 | #define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H |
16 | |
17 | #include "llvm/ADT/SmallVector.h" |
18 | #include "llvm/ExecutionEngine/ObjectCache.h" |
19 | #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" |
20 | #include "llvm/IR/LegacyPassManager.h" |
21 | #include "llvm/Object/Binary.h" |
22 | #include "llvm/Object/ObjectFile.h" |
23 | #include "llvm/Support/Error.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | #include "llvm/Support/MemoryBuffer.h" |
26 | #include "llvm/Support/SmallVectorMemoryBuffer.h" |
27 | #include "llvm/Support/raw_ostream.h" |
28 | #include "llvm/Target/TargetMachine.h" |
29 | #include <algorithm> |
30 | #include <memory> |
31 | |
32 | namespace llvm { |
33 | |
34 | class MCContext; |
35 | class Module; |
36 | |
37 | namespace orc { |
38 | |
39 | /// Simple compile functor: Takes a single IR module and returns an ObjectFile. |
40 | /// This compiler supports a single compilation thread and LLVMContext only. |
41 | /// For multithreaded compilation, use ConcurrentIRCompiler below. |
42 | class SimpleCompiler { |
43 | public: |
44 | using CompileResult = std::unique_ptr<MemoryBuffer>; |
45 | |
46 | /// Construct a simple compile functor with the given target. |
47 | SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr) |
48 | : TM(TM), ObjCache(ObjCache) {} |
49 | |
50 | /// Set an ObjectCache to query before compiling. |
51 | void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } |
52 | |
53 | /// Compile a Module to an ObjectFile. |
54 | CompileResult operator()(Module &M) { |
55 | CompileResult CachedObject = tryToLoadFromObjectCache(M); |
56 | if (CachedObject) |
57 | return CachedObject; |
58 | |
59 | SmallVector<char, 0> ObjBufferSV; |
60 | |
61 | { |
62 | raw_svector_ostream ObjStream(ObjBufferSV); |
63 | |
64 | legacy::PassManager PM; |
65 | MCContext *Ctx; |
66 | if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) |
67 | llvm_unreachable("Target does not support MC emission." ); |
68 | PM.run(M); |
69 | } |
70 | |
71 | auto ObjBuffer = |
72 | llvm::make_unique<SmallVectorMemoryBuffer>(std::move(ObjBufferSV)); |
73 | auto Obj = |
74 | object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); |
75 | |
76 | if (Obj) { |
77 | notifyObjectCompiled(M, *ObjBuffer); |
78 | return std::move(ObjBuffer); |
79 | } |
80 | |
81 | // TODO: Actually report errors helpfully. |
82 | consumeError(Obj.takeError()); |
83 | return nullptr; |
84 | } |
85 | |
86 | private: |
87 | |
88 | CompileResult tryToLoadFromObjectCache(const Module &M) { |
89 | if (!ObjCache) |
90 | return CompileResult(); |
91 | |
92 | return ObjCache->getObject(&M); |
93 | } |
94 | |
95 | void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer) { |
96 | if (ObjCache) |
97 | ObjCache->notifyObjectCompiled(&M, ObjBuffer.getMemBufferRef()); |
98 | } |
99 | |
100 | TargetMachine &TM; |
101 | ObjectCache *ObjCache = nullptr; |
102 | }; |
103 | |
104 | /// A thread-safe version of SimpleCompiler. |
105 | /// |
106 | /// This class creates a new TargetMachine and SimpleCompiler instance for each |
107 | /// compile. |
108 | class ConcurrentIRCompiler { |
109 | public: |
110 | ConcurrentIRCompiler(JITTargetMachineBuilder JTMB, |
111 | ObjectCache *ObjCache = nullptr) |
112 | : JTMB(std::move(JTMB)), ObjCache(ObjCache) {} |
113 | |
114 | void setObjectCache(ObjectCache *ObjCache) { this->ObjCache = ObjCache; } |
115 | |
116 | std::unique_ptr<MemoryBuffer> operator()(Module &M) { |
117 | auto TM = cantFail(JTMB.createTargetMachine()); |
118 | SimpleCompiler C(*TM, ObjCache); |
119 | return C(M); |
120 | } |
121 | |
122 | private: |
123 | JITTargetMachineBuilder JTMB; |
124 | ObjectCache *ObjCache = nullptr; |
125 | }; |
126 | |
127 | } // end namespace orc |
128 | |
129 | } // end namespace llvm |
130 | |
131 | #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H |
132 | |