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