blob: a8050ff22080979693dd8d4effc5edf65c5ba605 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- 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/ObjectMemoryBuffer.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/raw_ostream.h"
27#include "llvm/Target/TargetMachine.h"
28#include <algorithm>
29#include <memory>
30
31namespace llvm {
32
33class MCContext;
34class Module;
35
36namespace orc {
37
38/// @brief Simple compile functor: Takes a single IR module and returns an
39/// ObjectFile.
40class SimpleCompiler {
41private:
42 class SmallVectorMemoryBuffer : public MemoryBuffer {
43 public:
44 SmallVectorMemoryBuffer(SmallVector<char, 0> Buffer)
45 : Buffer(std::move(Buffer)) {
46 init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),
47 false);
48 }
49
50 BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
51
52 private:
53 SmallVector<char, 0> Buffer;
54 };
55
56public:
57 using CompileResult = std::unique_ptr<MemoryBuffer>;
58
59 /// @brief Construct a simple compile functor with the given target.
60 SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr)
61 : TM(TM), ObjCache(ObjCache) {}
62
63 /// @brief Set an ObjectCache to query before compiling.
64 void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
65
66 /// @brief Compile a Module to an ObjectFile.
67 CompileResult operator()(Module &M) {
68 CompileResult CachedObject = tryToLoadFromObjectCache(M);
69 if (CachedObject)
70 return CachedObject;
71
72 SmallVector<char, 0> ObjBufferSV;
73
74 {
75 raw_svector_ostream ObjStream(ObjBufferSV);
76
77 legacy::PassManager PM;
78 MCContext *Ctx;
79 if (TM.addPassesToEmitMC(PM, Ctx, ObjStream))
80 llvm_unreachable("Target does not support MC emission.");
81 PM.run(M);
82 }
83
84 auto ObjBuffer =
85 llvm::make_unique<SmallVectorMemoryBuffer>(std::move(ObjBufferSV));
86 auto Obj =
87 object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
88
89 if (Obj) {
90 notifyObjectCompiled(M, *ObjBuffer);
91 return std::move(ObjBuffer);
92 }
93
94 // TODO: Actually report errors helpfully.
95 consumeError(Obj.takeError());
96 return nullptr;
97 }
98
99private:
100
101 CompileResult tryToLoadFromObjectCache(const Module &M) {
102 if (!ObjCache)
103 return CompileResult();
104
105 return ObjCache->getObject(&M);
106 }
107
108 void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer) {
109 if (ObjCache)
110 ObjCache->notifyObjectCompiled(&M, ObjBuffer.getMemBufferRef());
111 }
112
113 TargetMachine &TM;
114 ObjectCache *ObjCache = nullptr;
115};
116
117} // end namespace orc
118
119} // end namespace llvm
120
121#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H