//===- CompileUtils.h - Utilities for compiling IR in the JIT ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Contains utilities for compiling IR to object files. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H #define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include <algorithm> #include <memory> namespace llvm { class MCContext; class Module; namespace orc { /// @brief Simple compile functor: Takes a single IR module and returns an /// ObjectFile. class SimpleCompiler { private: class SmallVectorMemoryBuffer : public MemoryBuffer { public: SmallVectorMemoryBuffer(SmallVector<char, 0> Buffer) : Buffer(std::move(Buffer)) { init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(), false); } BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; } private: SmallVector<char, 0> Buffer; }; public: using CompileResult = std::unique_ptr<MemoryBuffer>; /// @brief Construct a simple compile functor with the given target. SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr) : TM(TM), ObjCache(ObjCache) {} /// @brief Set an ObjectCache to query before compiling. void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } /// @brief Compile a Module to an ObjectFile. CompileResult operator()(Module &M) { CompileResult CachedObject = tryToLoadFromObjectCache(M); if (CachedObject) return CachedObject; SmallVector<char, 0> ObjBufferSV; { raw_svector_ostream ObjStream(ObjBufferSV); legacy::PassManager PM; MCContext *Ctx; if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) llvm_unreachable("Target does not support MC emission."); PM.run(M); } auto ObjBuffer = llvm::make_unique<SmallVectorMemoryBuffer>(std::move(ObjBufferSV)); auto Obj = object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); if (Obj) { notifyObjectCompiled(M, *ObjBuffer); return std::move(ObjBuffer); } // TODO: Actually report errors helpfully. consumeError(Obj.takeError()); return nullptr; } private: CompileResult tryToLoadFromObjectCache(const Module &M) { if (!ObjCache) return CompileResult(); return ObjCache->getObject(&M); } void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer) { if (ObjCache) ObjCache->notifyObjectCompiled(&M, ObjBuffer.getMemBufferRef()); } TargetMachine &TM; ObjectCache *ObjCache = nullptr; }; } // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H