diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h index f3be51149a43..cfeedc2a0bda 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Layer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Layer.h @@ -140,14 +140,28 @@ public: /// Returns the execution session for this layer. ExecutionSession &getExecutionSession() { return ES; } - /// Adds a MaterializationUnit representing the given IR to the given - /// JITDylib. - virtual Error add(ResourceTrackerSP RT, std::unique_ptr O); + /// Adds a MaterializationUnit for the object file in the given memory buffer + /// to the JITDylib for the given ResourceTracker. + virtual Error add(ResourceTrackerSP RT, std::unique_ptr O, + MaterializationUnit::Interface I); - Error add(JITDylib &JD, std::unique_ptr O) { - return add(JD.getDefaultResourceTracker(), std::move(O)); + /// Adds a MaterializationUnit for the object file in the given memory buffer + /// to the JITDylib for the given ResourceTracker. The interface for the + /// object will be built using the default object interface builder. + Error add(ResourceTrackerSP RT, std::unique_ptr O); + + /// Adds a MaterializationUnit for the object file in the given memory buffer + /// to the given JITDylib. + Error add(JITDylib &JD, std::unique_ptr O, + MaterializationUnit::Interface I) { + return add(JD.getDefaultResourceTracker(), std::move(O), std::move(I)); } + /// Adds a MaterializationUnit for the object file in the given memory buffer + /// to the given JITDylib. The interface for the object will be built using + /// the default object interface builder. + Error add(JITDylib &JD, std::unique_ptr O); + /// Emit should materialize the given IR. virtual void emit(std::unique_ptr R, std::unique_ptr O) = 0; @@ -160,6 +174,7 @@ private: /// instance) by calling 'emit' on the given ObjectLayer. class BasicObjectLayerMaterializationUnit : public MaterializationUnit { public: + /// Create using the default object interface builder function. static Expected> Create(ObjectLayer &L, std::unique_ptr O); diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h index 313842b6d3d0..77429f4b11ee 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Mangling.h @@ -55,11 +55,6 @@ public: SymbolNameToDefinitionMap *SymbolToDefinition = nullptr); }; -/// Returns a SymbolFlagsMap for the object file represented by the given -/// buffer, or an error if the buffer does not contain a valid object file. -Expected -getObjectInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer); - } // End namespace orc } // End namespace llvm diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectFileInterface.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectFileInterface.h new file mode 100644 index 000000000000..1bf09069163e --- /dev/null +++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectFileInterface.h @@ -0,0 +1,38 @@ +//===-- ObjectFileInterface.h - MU interface utils for objects --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Utilities for building MaterializationUnit::Interface objects from +// object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTFILEINTERFACE_H +#define LLVM_EXECUTIONENGINE_ORC_OBJECTFILEINTERFACE_H + +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/Support/MemoryBuffer.h" + +namespace llvm { +namespace orc { + +/// Adds an initializer symbol to the given MU interface. +/// The init symbol's name is guaranteed to be unique within I, and will be of +/// the form $..__inits., where N is some integer. +void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES, + StringRef ObjFileName); + +/// Returns a MaterializationUnit::Interface for the object file contained in +/// the given buffer, or an error if the buffer does not contain a valid object +/// file. +Expected +getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer); + +} // End namespace orc +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTFILEINTERFACE_H diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt index 0c503d7ce20f..cf8e0c85840c 100644 --- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_component_library(LLVMOrcJIT EPCGenericRTDyldMemoryManager.cpp EPCIndirectionUtils.cpp ExecutionUtils.cpp + ObjectFileInterface.cpp IndirectionUtils.cpp IRCompileLayer.cpp IRTransformLayer.cpp diff --git a/llvm/lib/ExecutionEngine/Orc/Layer.cpp b/llvm/lib/ExecutionEngine/Orc/Layer.cpp index 9ec2db640eb4..adb8861793b1 100644 --- a/llvm/lib/ExecutionEngine/Orc/Layer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Layer.cpp @@ -10,9 +10,8 @@ #include "llvm/ExecutionEngine/Orc/DebugUtils.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" #include "llvm/IR/Constants.h" -#include "llvm/Object/MachO.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "orc" @@ -161,20 +160,35 @@ ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {} ObjectLayer::~ObjectLayer() {} -Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr O) { +Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr O, + MaterializationUnit::Interface I) { assert(RT && "RT can not be null"); - auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(O)); - if (!ObjMU) - return ObjMU.takeError(); auto &JD = RT->getJITDylib(); - return JD.define(std::move(*ObjMU), std::move(RT)); + return JD.define(std::make_unique( + *this, std::move(O), std::move(I)), + std::move(RT)); +} + +Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr O) { + auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef()); + if (!I) + return I.takeError(); + return add(std::move(RT), std::move(O), std::move(*I)); +} + +Error ObjectLayer::add(JITDylib &JD, std::unique_ptr O) { + auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef()); + if (!I) + return I.takeError(); + return add(JD, std::move(O), std::move(*I)); } Expected> BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, std::unique_ptr O) { + auto ObjInterface = - getObjectInterface(L.getExecutionSession(), O->getMemBufferRef()); + getObjectFileInterface(L.getExecutionSession(), O->getMemBufferRef()); if (!ObjInterface) return ObjInterface.takeError(); diff --git a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp index 3639370c1717..9c243c9bf1d2 100644 --- a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp @@ -7,13 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/Mangling.h" -#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" -#include "llvm/ExecutionEngine/Orc/MachOPlatform.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Mangler.h" -#include "llvm/Object/ELFObjectFile.h" -#include "llvm/Object/MachO.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "orc" @@ -85,190 +80,5 @@ void IRSymbolMapper::add(ExecutionSession &ES, const ManglingOptions &MO, } } -static SymbolStringPtr addInitSymbol(SymbolFlagsMap &SymbolFlags, - ExecutionSession &ES, - StringRef ObjFileName) { - SymbolStringPtr InitSymbol; - size_t Counter = 0; - - do { - std::string InitSymString; - raw_string_ostream(InitSymString) - << "$." << ObjFileName << ".__inits." << Counter++; - InitSymbol = ES.intern(InitSymString); - } while (SymbolFlags.count(InitSymbol)); - - SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly; - return InitSymbol; -} - -static Expected -getMachOObjectFileSymbolInfo(ExecutionSession &ES, - const object::MachOObjectFile &Obj) { - SymbolFlagsMap SymbolFlags; - - for (auto &Sym : Obj.symbols()) { - Expected SymFlagsOrErr = Sym.getFlags(); - if (!SymFlagsOrErr) - // TODO: Test this error. - return SymFlagsOrErr.takeError(); - - // Skip symbols not defined in this object file. - if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) - continue; - - // Skip symbols that are not global. - if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) - continue; - - // Skip symbols that have type SF_File. - if (auto SymType = Sym.getType()) { - if (*SymType == object::SymbolRef::ST_File) - continue; - } else - return SymType.takeError(); - - auto Name = Sym.getName(); - if (!Name) - return Name.takeError(); - auto InternedName = ES.intern(*Name); - auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); - if (!SymFlags) - return SymFlags.takeError(); - - // Strip the 'exported' flag from MachO linker-private symbols. - if (Name->startswith("l")) - *SymFlags &= ~JITSymbolFlags::Exported; - - SymbolFlags[InternedName] = std::move(*SymFlags); - } - - SymbolStringPtr InitSymbol; - for (auto &Sec : Obj.sections()) { - auto SecType = Obj.getSectionType(Sec); - if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) { - InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName()); - break; - } - auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl()); - auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl())); - if (MachOPlatform::isInitializerSection(SegName, SecName)) { - InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName()); - break; - } - } - - return MaterializationUnit::Interface(std::move(SymbolFlags), - std::move(InitSymbol)); -} - -static Expected -getELFObjectFileSymbolInfo(ExecutionSession &ES, - const object::ELFObjectFileBase &Obj) { - SymbolFlagsMap SymbolFlags; - for (auto &Sym : Obj.symbols()) { - Expected SymFlagsOrErr = Sym.getFlags(); - if (!SymFlagsOrErr) - // TODO: Test this error. - return SymFlagsOrErr.takeError(); - - // Skip symbols not defined in this object file. - if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) - continue; - - // Skip symbols that are not global. - if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) - continue; - - // Skip symbols that have type SF_File. - if (auto SymType = Sym.getType()) { - if (*SymType == object::SymbolRef::ST_File) - continue; - } else - return SymType.takeError(); - - auto Name = Sym.getName(); - if (!Name) - return Name.takeError(); - auto InternedName = ES.intern(*Name); - auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); - if (!SymFlags) - return SymFlags.takeError(); - - // ELF STB_GNU_UNIQUE should map to Weak for ORC. - if (Sym.getBinding() == ELF::STB_GNU_UNIQUE) - *SymFlags |= JITSymbolFlags::Weak; - - SymbolFlags[InternedName] = std::move(*SymFlags); - } - - SymbolStringPtr InitSymbol; - for (auto &Sec : Obj.sections()) { - if (auto SecName = Sec.getName()) { - if (ELFNixPlatform::isInitializerSection(*SecName)) { - InitSymbol = addInitSymbol(SymbolFlags, ES, Obj.getFileName()); - break; - } - } - } - - return MaterializationUnit::Interface(std::move(SymbolFlags), - std::move(InitSymbol)); -} - -Expected -getGenericObjectFileSymbolInfo(ExecutionSession &ES, - const object::ObjectFile &Obj) { - SymbolFlagsMap SymbolFlags; - for (auto &Sym : Obj.symbols()) { - Expected SymFlagsOrErr = Sym.getFlags(); - if (!SymFlagsOrErr) - // TODO: Test this error. - return SymFlagsOrErr.takeError(); - - // Skip symbols not defined in this object file. - if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) - continue; - - // Skip symbols that are not global. - if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) - continue; - - // Skip symbols that have type SF_File. - if (auto SymType = Sym.getType()) { - if (*SymType == object::SymbolRef::ST_File) - continue; - } else - return SymType.takeError(); - - auto Name = Sym.getName(); - if (!Name) - return Name.takeError(); - auto InternedName = ES.intern(*Name); - auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); - if (!SymFlags) - return SymFlags.takeError(); - - SymbolFlags[InternedName] = std::move(*SymFlags); - } - - return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr); -} - -Expected -getObjectInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { - auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); - - if (!Obj) - return Obj.takeError(); - - if (auto *MachOObj = dyn_cast(Obj->get())) - return getMachOObjectFileSymbolInfo(ES, *MachOObj); - else if (auto *ELFObj = dyn_cast(Obj->get())) - return getELFObjectFileSymbolInfo(ES, *ELFObj); - - return getGenericObjectFileSymbolInfo(ES, **Obj); -} - } // End namespace orc. } // End namespace llvm. diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp new file mode 100644 index 000000000000..c1ad569dd65d --- /dev/null +++ b/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp @@ -0,0 +1,205 @@ +//===------ ObjectFileInterface.cpp - MU interface utils for objects ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" +#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h" +#include "llvm/ExecutionEngine/Orc/MachOPlatform.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "orc" + +namespace llvm { +namespace orc { + +void addInitSymbol(MaterializationUnit::Interface &I, ExecutionSession &ES, + StringRef ObjFileName) { + assert(!I.InitSymbol && "I already has an init symbol"); + size_t Counter = 0; + + do { + std::string InitSymString; + raw_string_ostream(InitSymString) + << "$." << ObjFileName << ".__inits." << Counter++; + I.InitSymbol = ES.intern(InitSymString); + } while (I.SymbolFlags.count(I.InitSymbol)); + + I.SymbolFlags[I.InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly; +} + +static Expected +getMachOObjectFileSymbolInfo(ExecutionSession &ES, + const object::MachOObjectFile &Obj) { + MaterializationUnit::Interface I; + + for (auto &Sym : Obj.symbols()) { + Expected SymFlagsOrErr = Sym.getFlags(); + if (!SymFlagsOrErr) + // TODO: Test this error. + return SymFlagsOrErr.takeError(); + + // Skip symbols not defined in this object file. + if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) + continue; + + // Skip symbols that are not global. + if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) + continue; + + // Skip symbols that have type SF_File. + if (auto SymType = Sym.getType()) { + if (*SymType == object::SymbolRef::ST_File) + continue; + } else + return SymType.takeError(); + + auto Name = Sym.getName(); + if (!Name) + return Name.takeError(); + auto InternedName = ES.intern(*Name); + auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); + if (!SymFlags) + return SymFlags.takeError(); + + // Strip the 'exported' flag from MachO linker-private symbols. + if (Name->startswith("l")) + *SymFlags &= ~JITSymbolFlags::Exported; + + I.SymbolFlags[InternedName] = std::move(*SymFlags); + } + + for (auto &Sec : Obj.sections()) { + auto SecType = Obj.getSectionType(Sec); + if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) { + addInitSymbol(I, ES, Obj.getFileName()); + break; + } + auto SegName = Obj.getSectionFinalSegmentName(Sec.getRawDataRefImpl()); + auto SecName = cantFail(Obj.getSectionName(Sec.getRawDataRefImpl())); + if (MachOPlatform::isInitializerSection(SegName, SecName)) { + addInitSymbol(I, ES, Obj.getFileName()); + break; + } + } + + return I; +} + +static Expected +getELFObjectFileSymbolInfo(ExecutionSession &ES, + const object::ELFObjectFileBase &Obj) { + MaterializationUnit::Interface I; + + for (auto &Sym : Obj.symbols()) { + Expected SymFlagsOrErr = Sym.getFlags(); + if (!SymFlagsOrErr) + // TODO: Test this error. + return SymFlagsOrErr.takeError(); + + // Skip symbols not defined in this object file. + if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) + continue; + + // Skip symbols that are not global. + if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) + continue; + + // Skip symbols that have type SF_File. + if (auto SymType = Sym.getType()) { + if (*SymType == object::SymbolRef::ST_File) + continue; + } else + return SymType.takeError(); + + auto Name = Sym.getName(); + if (!Name) + return Name.takeError(); + auto InternedName = ES.intern(*Name); + auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); + if (!SymFlags) + return SymFlags.takeError(); + + // ELF STB_GNU_UNIQUE should map to Weak for ORC. + if (Sym.getBinding() == ELF::STB_GNU_UNIQUE) + *SymFlags |= JITSymbolFlags::Weak; + + I.SymbolFlags[InternedName] = std::move(*SymFlags); + } + + SymbolStringPtr InitSymbol; + for (auto &Sec : Obj.sections()) { + if (auto SecName = Sec.getName()) { + if (ELFNixPlatform::isInitializerSection(*SecName)) { + addInitSymbol(I, ES, Obj.getFileName()); + break; + } + } + } + + return I; +} + +Expected +getGenericObjectFileSymbolInfo(ExecutionSession &ES, + const object::ObjectFile &Obj) { + MaterializationUnit::Interface I; + + for (auto &Sym : Obj.symbols()) { + Expected SymFlagsOrErr = Sym.getFlags(); + if (!SymFlagsOrErr) + // TODO: Test this error. + return SymFlagsOrErr.takeError(); + + // Skip symbols not defined in this object file. + if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) + continue; + + // Skip symbols that are not global. + if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) + continue; + + // Skip symbols that have type SF_File. + if (auto SymType = Sym.getType()) { + if (*SymType == object::SymbolRef::ST_File) + continue; + } else + return SymType.takeError(); + + auto Name = Sym.getName(); + if (!Name) + return Name.takeError(); + auto InternedName = ES.intern(*Name); + auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); + if (!SymFlags) + return SymFlags.takeError(); + + I.SymbolFlags[InternedName] = std::move(*SymFlags); + } + + return I; +} + +Expected +getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { + auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); + + if (!Obj) + return Obj.takeError(); + + if (auto *MachOObj = dyn_cast(Obj->get())) + return getMachOObjectFileSymbolInfo(ES, *MachOObj); + else if (auto *ELFObj = dyn_cast(Obj->get())) + return getELFObjectFileSymbolInfo(ES, *ELFObj); + + return getGenericObjectFileSymbolInfo(ES, **Obj); +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp index 96833ea02c90..306fac9f77e7 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -24,6 +24,7 @@ #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/MachOPlatform.h" +#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h" #include "llvm/MC/MCAsmInfo.h" @@ -637,34 +638,23 @@ static std::unique_ptr createMemoryManager() { return ExitOnErr(InProcessMemoryManager::Create()); } -LLVMJITLinkObjectLinkingLayer::LLVMJITLinkObjectLinkingLayer( - Session &S, JITLinkMemoryManager &MemMgr) - : ObjectLinkingLayer(S.ES, MemMgr), S(S) {} +static Expected +getTestObjectFileInterface(Session &S, MemoryBufferRef O) { -Error LLVMJITLinkObjectLinkingLayer::add(ResourceTrackerSP RT, - std::unique_ptr O) { - - if (S.HarnessFiles.empty() || S.HarnessFiles.count(O->getBufferIdentifier())) - return ObjectLinkingLayer::add(std::move(RT), std::move(O)); - - // Use getObjectSymbolInfo to compute the init symbol, but ignore - // the symbols field. We'll handle that manually to include promotion. - auto ObjInterface = - getObjectInterface(getExecutionSession(), O->getMemBufferRef()); - - if (!ObjInterface) - return ObjInterface.takeError(); + // Get the standard interface for this object, but ignore the symbols field. + // We'll handle that manually to include promotion. + auto I = getObjectFileInterface(S.ES, O); + if (!I) + return I.takeError(); + I->SymbolFlags.clear(); // If creating an object file was going to fail it would have happened above, // so we can 'cantFail' this. - auto Obj = - cantFail(object::ObjectFile::createObjectFile(O->getMemBufferRef())); - - ObjInterface->SymbolFlags.clear(); + auto Obj = cantFail(object::ObjectFile::createObjectFile(O)); // The init symbol must be included in the SymbolFlags map if present. - if (ObjInterface->InitSymbol) - ObjInterface->SymbolFlags[ObjInterface->InitSymbol] = + if (I->InitSymbol) + I->SymbolFlags[I->InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly; for (auto &Sym : Obj->symbols()) { @@ -698,7 +688,7 @@ Error LLVMJITLinkObjectLinkingLayer::add(ResourceTrackerSP RT, // that we've seen) or discard it. if (S.HarnessDefinitions.count(*Name) || S.CanonicalWeakDefs.count(*Name)) continue; - S.CanonicalWeakDefs[*Name] = O->getBufferIdentifier(); + S.CanonicalWeakDefs[*Name] = O.getBufferIdentifier(); *SymFlags &= ~JITSymbolFlags::Weak; if (!S.HarnessExternals.count(*Name)) *SymFlags &= ~JITSymbolFlags::Exported; @@ -709,14 +699,10 @@ Error LLVMJITLinkObjectLinkingLayer::add(ResourceTrackerSP RT, continue; auto InternedName = S.ES.intern(*Name); - ObjInterface->SymbolFlags[InternedName] = std::move(*SymFlags); + I->SymbolFlags[InternedName] = std::move(*SymFlags); } - auto MU = std::make_unique( - *this, std::move(O), std::move(*ObjInterface)); - - auto &JD = RT->getJITDylib(); - return JD.define(std::move(MU), std::move(RT)); + return I; } static Error loadProcessSymbols(Session &S) { @@ -954,7 +940,7 @@ Session::~Session() { Session::Session(std::unique_ptr EPC, Error &Err) : ES(std::move(EPC)), - ObjLayer(*this, ES.getExecutorProcessControl().getMemMgr()) { + ObjLayer(ES, ES.getExecutorProcessControl().getMemMgr()) { /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the /// Session. @@ -1034,7 +1020,7 @@ Session::Session(std::unique_ptr EPC, Error &Err) ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(HarnessFile))); auto ObjInterface = - ExitOnErr(getObjectInterface(ES, ObjBuffer->getMemBufferRef())); + ExitOnErr(getObjectFileInterface(ES, ObjBuffer->getMemBufferRef())); for (auto &KV : ObjInterface.SymbolFlags) HarnessDefinitions.insert(*KV.first); @@ -1360,8 +1346,18 @@ static Error loadObjects(Session &S) { JD.addGenerator(ExitOnErr(StaticLibraryDefinitionGenerator::Load( S.ObjLayer, InputFile.c_str(), S.ES.getExecutorProcessControl().getTargetTriple()))); - else - ExitOnErr(S.ObjLayer.add(JD, std::move(ObjBuffer))); + else { + if (S.HarnessFiles.empty()) + ExitOnErr(S.ObjLayer.add(JD, std::move(ObjBuffer))); + else { + // We're in -harness mode. Use a custom interface for this + // test object. + auto ObjInterface = ExitOnErr( + getTestObjectFileInterface(S, ObjBuffer->getMemBufferRef())); + ExitOnErr( + S.ObjLayer.add(JD, std::move(ObjBuffer), std::move(ObjInterface))); + } + } } // Define absolute symbols. diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.h b/llvm/tools/llvm-jitlink/llvm-jitlink.h index 7d58cd4ac62f..7873bcaa13d4 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.h +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.h @@ -31,25 +31,10 @@ namespace llvm { struct Session; -/// ObjectLinkingLayer with additional support for symbol promotion. -class LLVMJITLinkObjectLinkingLayer : public orc::ObjectLinkingLayer { -public: - using orc::ObjectLinkingLayer::add; - - LLVMJITLinkObjectLinkingLayer(Session &S, - jitlink::JITLinkMemoryManager &MemMgr); - - Error add(orc::ResourceTrackerSP RT, - std::unique_ptr O) override; - -private: - Session &S; -}; - struct Session { orc::ExecutionSession ES; orc::JITDylib *MainJD = nullptr; - LLVMJITLinkObjectLinkingLayer ObjLayer; + orc::ObjectLinkingLayer ObjLayer; orc::JITDylibSearchOrder JDSearchOrder; ~Session();