diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h index 213a59124c85..3d02f9d05e49 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h @@ -16,7 +16,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/ObjectCache.h" -#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index 6a9731655b77..5c58d4b36062 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -21,7 +21,6 @@ #include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Support/DynamicLibrary.h" -#include "llvm/Target/TargetOptions.h" #include #include #include @@ -39,48 +38,6 @@ class Value; namespace orc { -/// A utility class for building TargetMachines for JITs. -class JITTargetMachineBuilder { -public: - JITTargetMachineBuilder(Triple TT); - static Expected detectHost(); - Expected> createTargetMachine(); - - JITTargetMachineBuilder &setArch(std::string Arch) { - this->Arch = std::move(Arch); - return *this; - } - JITTargetMachineBuilder &setCPU(std::string CPU) { - this->CPU = std::move(CPU); - return *this; - } - JITTargetMachineBuilder &setRelocationModel(Optional RM) { - this->RM = std::move(RM); - return *this; - } - JITTargetMachineBuilder &setCodeModel(Optional CM) { - this->CM = std::move(CM); - return *this; - } - JITTargetMachineBuilder & - addFeatures(const std::vector &FeatureVec); - SubtargetFeatures &getFeatures() { return Features; } - TargetOptions &getOptions() { return Options; } - - Triple& getTargetTriple() { return TT; } - const Triple& getTargetTriple() const { return TT; } - -private: - Triple TT; - std::string Arch; - std::string CPU; - SubtargetFeatures Features; - TargetOptions Options; - Optional RM; - Optional CM; - CodeGenOpt::Level OptLevel = CodeGenOpt::Default; -}; - /// This iterator provides a convenient way to iterate over the elements /// of an llvm.global_ctors/llvm.global_dtors instance. /// diff --git a/llvm/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h b/llvm/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h new file mode 100644 index 000000000000..327941d52fe2 --- /dev/null +++ b/llvm/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h @@ -0,0 +1,118 @@ +//===- JITTargetMachineBuilder.h - Build TargetMachines for JIT -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A utitily for building TargetMachines for JITs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_JITTARGETMACHINEBUILDER_H +#define LLVM_EXECUTIONENGINE_ORC_JITTARGETMACHINEBUILDER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Error.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include +#include +#include + +namespace llvm { +namespace orc { + +/// A utility class for building TargetMachines for JITs. +class JITTargetMachineBuilder { +public: + /// Create a JITTargetMachineBuilder based on the given triple. + /// + /// Note: TargetOptions is default-constructed, then EmulatedTLS and + /// ExplicitEmulatedTLS are set to true. If EmulatedTLS is not + /// required, these values should be reset before calling + /// createTargetMachine. + JITTargetMachineBuilder(Triple TT); + + /// Create a JITTargetMachineBuilder for the host system. + /// + /// Note: TargetOptions is default-constructed, then EmulatedTLS and + /// ExplicitEmulatedTLS are set to true. If EmulatedTLS is not + /// required, these values should be reset before calling + /// createTargetMachine. + static Expected detectHost(); + + /// Create a TargetMachine. + /// + /// This operation will fail if the requested target is not registered, + /// in which case see llvm/Support/TargetSelect.h. To JIT IR the Target and + /// the target's AsmPrinter must both be registered. To JIT assembly + /// (including inline and module level assembly) the target's AsmParser must + /// also be registered. + Expected> createTargetMachine(); + + /// Set the CPU string. + JITTargetMachineBuilder &setCPU(std::string CPU) { + this->CPU = std::move(CPU); + return *this; + } + + /// Set the relocation model. + JITTargetMachineBuilder &setRelocationModel(Optional RM) { + this->RM = std::move(RM); + return *this; + } + + /// Set the code model. + JITTargetMachineBuilder &setCodeModel(Optional CM) { + this->CM = std::move(CM); + return *this; + } + + /// Set the LLVM CodeGen optimization level. + JITTargetMachineBuilder &setCodeGenOptLevel(CodeGenOpt::Level OptLevel) { + this->OptLevel = OptLevel; + return *this; + } + + /// Add subtarget features. + JITTargetMachineBuilder & + addFeatures(const std::vector &FeatureVec); + + /// Access subtarget features. + SubtargetFeatures &getFeatures() { return Features; } + + /// Access subtarget features. + const SubtargetFeatures &getFeatures() const { return Features; } + + /// Access TargetOptions. + TargetOptions &getOptions() { return Options; } + + /// Access TargetOptions. + const TargetOptions &getOptions() const { return Options; } + + /// Access Triple. + Triple &getTargetTriple() { return TT; } + + /// Access Triple. + const Triple &getTargetTriple() const { return TT; } + +private: + Triple TT; + std::string CPU; + SubtargetFeatures Features; + TargetOptions Options; + Optional RM; + Optional CM; + CodeGenOpt::Level OptLevel = CodeGenOpt::None; +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_JITTARGETMACHINEBUILDER_H diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h index 7e113b8ace38..01dae538b8e2 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h @@ -19,6 +19,7 @@ #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" @@ -51,6 +52,8 @@ public: /// Convenience method for defining an absolute symbol. Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address); + /// Convenience method for defining an + /// Adds an IR module to the given JITDylib. Error addIRModule(JITDylib &JD, ThreadSafeModule TSM); diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt index 680ede23568c..9ca409f81cd3 100644 --- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -5,6 +5,7 @@ add_llvm_library(LLVMOrcJIT IndirectionUtils.cpp IRCompileLayer.cpp IRTransformLayer.cpp + JITTargetMachineBuilder.cpp LazyReexports.cpp Legacy.cpp Layer.cpp diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp index bb32b3d82e6d..e9e27453c320 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -19,45 +19,6 @@ namespace llvm { namespace orc { -JITTargetMachineBuilder::JITTargetMachineBuilder(Triple TT) - : TT(std::move(TT)) {} - -Expected JITTargetMachineBuilder::detectHost() { - return JITTargetMachineBuilder(Triple(sys::getProcessTriple())); -} - -Expected> -JITTargetMachineBuilder::createTargetMachine() { - if (!Arch.empty()) { - Triple::ArchType Type = Triple::getArchTypeForLLVMName(Arch); - - if (Type == Triple::UnknownArch) - return make_error(std::string("Unknown arch: ") + Arch, - inconvertibleErrorCode()); - } - - std::string ErrMsg; - auto *TheTarget = TargetRegistry::lookupTarget(TT.getTriple(), ErrMsg); - if (!TheTarget) - return make_error(std::move(ErrMsg), inconvertibleErrorCode()); - - auto *TM = - TheTarget->createTargetMachine(TT.getTriple(), CPU, Features.getString(), - Options, RM, CM, OptLevel, /*JIT*/ true); - if (!TM) - return make_error("Could not allocate target machine", - inconvertibleErrorCode()); - - return std::unique_ptr(TM); -} - -JITTargetMachineBuilder &JITTargetMachineBuilder::addFeatures( - const std::vector &FeatureVec) { - for (const auto &F : FeatureVec) - Features.AddFeature(F); - return *this; -} - CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End) : InitList( GV ? dyn_cast_or_null(GV->getInitializer()) : nullptr), diff --git a/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp b/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp new file mode 100644 index 000000000000..4af09d196ff9 --- /dev/null +++ b/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp @@ -0,0 +1,55 @@ +//===----- JITTargetMachineBuilder.cpp - Build TargetMachines for JIT -----===// +// +// 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/JITTargetMachineBuilder.h" + +#include "llvm/Support/TargetRegistry.h" + +namespace llvm { +namespace orc { + +JITTargetMachineBuilder::JITTargetMachineBuilder(Triple TT) + : TT(std::move(TT)) { + Options.EmulatedTLS = true; + Options.ExplicitEmulatedTLS = true; +} + +Expected JITTargetMachineBuilder::detectHost() { + // FIXME: getProcessTriple is bogus. It returns the host LLVM was compiled on, + // rather than a valid triple for the current process. + return JITTargetMachineBuilder(Triple(sys::getProcessTriple())); +} + +Expected> +JITTargetMachineBuilder::createTargetMachine() { + + std::string ErrMsg; + auto *TheTarget = TargetRegistry::lookupTarget(TT.getTriple(), ErrMsg); + if (!TheTarget) + return make_error(std::move(ErrMsg), inconvertibleErrorCode()); + + auto *TM = + TheTarget->createTargetMachine(TT.getTriple(), CPU, Features.getString(), + Options, RM, CM, OptLevel, /*JIT*/ true); + if (!TM) + return make_error("Could not allocate target machine", + inconvertibleErrorCode()); + + return std::unique_ptr(TM); +} + +JITTargetMachineBuilder &JITTargetMachineBuilder::addFeatures( + const std::vector &FeatureVec) { + for (const auto &F : FeatureVec) + Features.AddFeature(F); + return *this; +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp index 18cb661b9ef7..9b3c7478b412 100644 --- a/llvm/tools/lli/lli.cpp +++ b/llvm/tools/lli/lli.cpp @@ -26,6 +26,7 @@ #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h" #include "llvm/ExecutionEngine/OrcMCJITReplacement.h" @@ -773,8 +774,10 @@ int runOrcLazyJIT(const char *ProgName) { TT.empty() ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost()) : orc::JITTargetMachineBuilder(Triple(TT)); - JTMB.setArch(MArch) - .setCPU(getCPUStr()) + if (!MArch.empty()) + JTMB.getTargetTriple().setArchName(MArch); + + JTMB.setCPU(getCPUStr()) .addFeatures(getFeatureList()) .setRelocationModel(RelocModel.getNumOccurrences() ? Optional(RelocModel) @@ -782,6 +785,7 @@ int runOrcLazyJIT(const char *ProgName) { .setCodeModel(CMModel.getNumOccurrences() ? Optional(CMModel) : None); + DataLayout DL(""); { // Create a throwaway TargetMachine to get the data layout. diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt index 3a47bfa20bf3..8b0d5fc24354 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt @@ -14,6 +14,7 @@ add_llvm_unittest(OrcJITTests CoreAPIsTest.cpp IndirectionUtilsTest.cpp GlobalMappingLayerTest.cpp + JITTargetMachineBuilderTest.cpp LazyCallThroughAndReexportsTest.cpp LazyEmittingLayerTest.cpp LegacyAPIInteropTest.cpp diff --git a/llvm/unittests/ExecutionEngine/Orc/JITTargetMachineBuilderTest.cpp b/llvm/unittests/ExecutionEngine/Orc/JITTargetMachineBuilderTest.cpp new file mode 100644 index 000000000000..f978a90efb3d --- /dev/null +++ b/llvm/unittests/ExecutionEngine/Orc/JITTargetMachineBuilderTest.cpp @@ -0,0 +1,52 @@ +//===----------- CoreAPIsTest.cpp - Unit tests for Core ORC APIs ----------===// +// +// 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/JITTargetMachineBuilder.h" +#include "OrcTestCommon.h" + +using namespace llvm; +using namespace llvm::orc; + +namespace { + +TEST(ExecutionUtilsTest, JITTargetMachineBuilder) { + // Tests basic API usage. + // Bails out on error, as it is valid to run this test without any targets + // built. + + // Make sure LLVM has been initialized. + OrcNativeTarget::initialize(); + + auto JTMB = cantFail(JITTargetMachineBuilder::detectHost()); + + // Test API by performing a bunch of no-ops. + JTMB.setCPU(""); + JTMB.setRelocationModel(None); + JTMB.setCodeModel(None); + JTMB.setCodeGenOptLevel(CodeGenOpt::None); + JTMB.addFeatures(std::vector()); + SubtargetFeatures &STF = JTMB.getFeatures(); + (void)STF; + TargetOptions &TO = JTMB.getOptions(); + (void)TO; + Triple &TT = JTMB.getTargetTriple(); + (void)TT; + + auto TM = JTMB.createTargetMachine(); + + if (!TM) + consumeError(TM.takeError()); + else { + EXPECT_NE(TM.get(), nullptr) + << "JITTargetMachineBuilder should return a non-null TargetMachine " + "on success"; + } +} + +} // namespace diff --git a/llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp index 7caaa767242e..c3c5703f54ba 100644 --- a/llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp @@ -1,5 +1,5 @@ #include "OrcTestCommon.h" -#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LazyReexports.h" #include "gtest/gtest.h"