From e81f95d26ca01029d46c8b787775620eeca011ef Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 21 May 2018 21:11:13 +0000 Subject: [PATCH] [ORC] Add IRLayer and ObjectLayer interfaces and related MaterializationUnits. llvm-svn: 332896 --- include/llvm/ExecutionEngine/Orc/Layer.h | 99 ++++++++++++++++++++ lib/ExecutionEngine/Orc/CMakeLists.txt | 1 + lib/ExecutionEngine/Orc/Layer.cpp | 110 +++++++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 include/llvm/ExecutionEngine/Orc/Layer.h create mode 100644 lib/ExecutionEngine/Orc/Layer.cpp diff --git a/include/llvm/ExecutionEngine/Orc/Layer.h b/include/llvm/ExecutionEngine/Orc/Layer.h new file mode 100644 index 00000000000..5aef5a26d2a --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/Layer.h @@ -0,0 +1,99 @@ +//===---------------- Layer.h -- Layer interfaces --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Layer interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LAYER_H +#define LLVM_EXECUTIONENGINE_ORC_LAYER_H + +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/IR/Module.h" + +namespace llvm { +namespace orc { + +class MangleAndInterner { +public: + MangleAndInterner(ExecutionSession &ES, const DataLayout &DL); + SymbolStringPtr operator()(StringRef Name); + +private: + ExecutionSession &ES; + const DataLayout &DL; +}; + +/// Layer interface. +class IRLayer { +public: + IRLayer(ExecutionSession &ES); + virtual ~IRLayer(); + + ExecutionSession &getExecutionSession() { return ES; } + + virtual Error add(VSO &V, VModuleKey K, std::unique_ptr M); + virtual void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr M) = 0; + +private: + ExecutionSession &ES; +}; + +class BasicIRLayerMaterializationUnit : public MaterializationUnit { +public: + BasicIRLayerMaterializationUnit(IRLayer &L, VModuleKey K, + std::unique_ptr M); + +private: + void materialize(MaterializationResponsibility R) override; + void discard(const VSO &V, SymbolStringPtr Name) override; + + IRLayer &L; + VModuleKey K; + std::unique_ptr M; + std::map Discardable; +}; + +class ObjectLayer { +public: + ObjectLayer(ExecutionSession &ES); + virtual ~ObjectLayer(); + + ExecutionSession &getExecutionSession() { return ES; } + + virtual Error add(VSO &V, VModuleKey K, std::unique_ptr O); + virtual void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr O) = 0; + +private: + ExecutionSession &ES; +}; + +/// The MemoryBuffer should represent a valid object file. +/// If there is any chance that the file is invalid it should be validated +/// prior to constructing a BasicObjectLayerMaterializationUnit. +class BasicObjectLayerMaterializationUnit : public MaterializationUnit { +public: + BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K, + std::unique_ptr O); + +private: + void materialize(MaterializationResponsibility R) override; + void discard(const VSO &V, SymbolStringPtr Name) override; + + ObjectLayer &L; + VModuleKey K; + std::unique_ptr O; +}; + +} // End namespace orc +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_LAYER_H diff --git a/lib/ExecutionEngine/Orc/CMakeLists.txt b/lib/ExecutionEngine/Orc/CMakeLists.txt index ca1b9ee005c..ec0d0e0796b 100644 --- a/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(LLVMOrcJIT ExecutionUtils.cpp IndirectionUtils.cpp Legacy.cpp + Layer.cpp NullResolver.cpp OrcABISupport.cpp OrcCBindings.cpp diff --git a/lib/ExecutionEngine/Orc/Layer.cpp b/lib/ExecutionEngine/Orc/Layer.cpp new file mode 100644 index 00000000000..2bb7b907fed --- /dev/null +++ b/lib/ExecutionEngine/Orc/Layer.cpp @@ -0,0 +1,110 @@ +//===-------------------- Layer.cpp - Layer interfaces --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/Orc/Layer.h" +#include "llvm/IR/Mangler.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/MemoryBuffer.h" + +namespace llvm { +namespace orc { + +MangleAndInterner::MangleAndInterner(ExecutionSession &ES, const DataLayout &DL) + : ES(ES), DL(DL) {} + +SymbolStringPtr MangleAndInterner::operator()(StringRef Name) { + std::string MangledName; + { + raw_string_ostream MangledNameStream(MangledName); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); + } + return ES.getSymbolStringPool().intern(MangledName); +} + +IRLayer::IRLayer(ExecutionSession &ES) : ES(ES) {} +IRLayer::~IRLayer() {} + +Error IRLayer::add(VSO &V, VModuleKey K, std::unique_ptr M) { + return V.define(llvm::make_unique( + *this, std::move(K), std::move(M))); +} + +BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit( + IRLayer &L, VModuleKey K, std::unique_ptr M) + : MaterializationUnit(SymbolFlagsMap()), L(L), K(std::move(K)), + M(std::move(M)) { + + auto &ES = L.getExecutionSession(); + MangleAndInterner Mangle(ES, this->M->getDataLayout()); + for (auto &G : this->M->global_values()) { + if (G.hasName() && !G.isDeclaration() && + !G.hasLocalLinkage() && + !G.hasAvailableExternallyLinkage()) { + auto MangledName = Mangle(G.getName()); + SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G); + Discardable[MangledName] = &G; + } + } +} + +void BasicIRLayerMaterializationUnit::materialize( + MaterializationResponsibility R) { + L.emit(std::move(R), std::move(K), std::move(M)); +} + +void BasicIRLayerMaterializationUnit::discard(const VSO &V, + SymbolStringPtr Name) { + auto I = Discardable.find(Name); + assert(I != Discardable.end() && + "Symbol not provided by this MU, or previously discarded"); + I->second->setLinkage(GlobalValue::AvailableExternallyLinkage); + Discardable.erase(I); +} + +ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {} + +ObjectLayer::~ObjectLayer() {} + +Error ObjectLayer::add(VSO &V, VModuleKey K, std::unique_ptr O) { + return V.define(llvm::make_unique( + *this, std::move(K), std::move(O))); +} + +BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit( + ObjectLayer &L, VModuleKey K, std::unique_ptr O) + : MaterializationUnit(SymbolFlagsMap()), L(L), K(std::move(K)), + O(std::move(O)) { + + auto &ES = L.getExecutionSession(); + auto Obj = cantFail( + object::ObjectFile::createObjectFile(this->O->getMemBufferRef())); + + for (auto &Sym : Obj->symbols()) { + if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) && + (Sym.getFlags() & object::BasicSymbolRef::SF_Exported)) { + auto InternedName = + ES.getSymbolStringPool().intern(cantFail(Sym.getName())); + SymbolFlags[InternedName] = JITSymbolFlags::fromObjectSymbol(Sym); + } + } +} + +void BasicObjectLayerMaterializationUnit::materialize( + MaterializationResponsibility R) { + L.emit(std::move(R), std::move(K), std::move(O)); +} + +void BasicObjectLayerMaterializationUnit::discard(const VSO &V, + SymbolStringPtr Name) { + // FIXME: Support object file level discard. This could be done by building a + // filter to pass to the object layer along with the object itself. +} + +} // End namespace orc. +} // End namespace llvm.