[ORC] Extract and tidy up JITTargetMachineBuilder, add unit test.

(1) Adds comments for the API.

(2) Removes the setArch method: This is redundant: the setArchStr method on the
    triple should be used instead.

(3) Turns EmulatedTLS on by default. This matches EngineBuilder's behavior.

llvm-svn: 343423
This commit is contained in:
Lang Hames 2018-09-30 19:12:23 +00:00
parent 0f8f0d6d1d
commit d435ce4343
11 changed files with 238 additions and 86 deletions

View File

@ -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"

View File

@ -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 <algorithm>
#include <cstdint>
#include <string>
@ -39,48 +38,6 @@ class Value;
namespace orc {
/// A utility class for building TargetMachines for JITs.
class JITTargetMachineBuilder {
public:
JITTargetMachineBuilder(Triple TT);
static Expected<JITTargetMachineBuilder> detectHost();
Expected<std::unique_ptr<TargetMachine>> 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<Reloc::Model> RM) {
this->RM = std::move(RM);
return *this;
}
JITTargetMachineBuilder &setCodeModel(Optional<CodeModel::Model> CM) {
this->CM = std::move(CM);
return *this;
}
JITTargetMachineBuilder &
addFeatures(const std::vector<std::string> &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<Reloc::Model> RM;
Optional<CodeModel::Model> 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.
///

View File

@ -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 <memory>
#include <string>
#include <vector>
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<JITTargetMachineBuilder> 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<std::unique_ptr<TargetMachine>> createTargetMachine();
/// Set the CPU string.
JITTargetMachineBuilder &setCPU(std::string CPU) {
this->CPU = std::move(CPU);
return *this;
}
/// Set the relocation model.
JITTargetMachineBuilder &setRelocationModel(Optional<Reloc::Model> RM) {
this->RM = std::move(RM);
return *this;
}
/// Set the code model.
JITTargetMachineBuilder &setCodeModel(Optional<CodeModel::Model> 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<std::string> &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<Reloc::Model> RM;
Optional<CodeModel::Model> CM;
CodeGenOpt::Level OptLevel = CodeGenOpt::None;
};
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_JITTARGETMACHINEBUILDER_H

View File

@ -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);

View File

@ -5,6 +5,7 @@ add_llvm_library(LLVMOrcJIT
IndirectionUtils.cpp
IRCompileLayer.cpp
IRTransformLayer.cpp
JITTargetMachineBuilder.cpp
LazyReexports.cpp
Legacy.cpp
Layer.cpp

View File

@ -19,45 +19,6 @@
namespace llvm {
namespace orc {
JITTargetMachineBuilder::JITTargetMachineBuilder(Triple TT)
: TT(std::move(TT)) {}
Expected<JITTargetMachineBuilder> JITTargetMachineBuilder::detectHost() {
return JITTargetMachineBuilder(Triple(sys::getProcessTriple()));
}
Expected<std::unique_ptr<TargetMachine>>
JITTargetMachineBuilder::createTargetMachine() {
if (!Arch.empty()) {
Triple::ArchType Type = Triple::getArchTypeForLLVMName(Arch);
if (Type == Triple::UnknownArch)
return make_error<StringError>(std::string("Unknown arch: ") + Arch,
inconvertibleErrorCode());
}
std::string ErrMsg;
auto *TheTarget = TargetRegistry::lookupTarget(TT.getTriple(), ErrMsg);
if (!TheTarget)
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
auto *TM =
TheTarget->createTargetMachine(TT.getTriple(), CPU, Features.getString(),
Options, RM, CM, OptLevel, /*JIT*/ true);
if (!TM)
return make_error<StringError>("Could not allocate target machine",
inconvertibleErrorCode());
return std::unique_ptr<TargetMachine>(TM);
}
JITTargetMachineBuilder &JITTargetMachineBuilder::addFeatures(
const std::vector<std::string> &FeatureVec) {
for (const auto &F : FeatureVec)
Features.AddFeature(F);
return *this;
}
CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
: InitList(
GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),

View File

@ -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> 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<std::unique_ptr<TargetMachine>>
JITTargetMachineBuilder::createTargetMachine() {
std::string ErrMsg;
auto *TheTarget = TargetRegistry::lookupTarget(TT.getTriple(), ErrMsg);
if (!TheTarget)
return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
auto *TM =
TheTarget->createTargetMachine(TT.getTriple(), CPU, Features.getString(),
Options, RM, CM, OptLevel, /*JIT*/ true);
if (!TM)
return make_error<StringError>("Could not allocate target machine",
inconvertibleErrorCode());
return std::unique_ptr<TargetMachine>(TM);
}
JITTargetMachineBuilder &JITTargetMachineBuilder::addFeatures(
const std::vector<std::string> &FeatureVec) {
for (const auto &F : FeatureVec)
Features.AddFeature(F);
return *this;
}
} // End namespace orc.
} // End namespace llvm.

View File

@ -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<Reloc::Model>(RelocModel)
@ -782,6 +785,7 @@ int runOrcLazyJIT(const char *ProgName) {
.setCodeModel(CMModel.getNumOccurrences()
? Optional<CodeModel::Model>(CMModel)
: None);
DataLayout DL("");
{
// Create a throwaway TargetMachine to get the data layout.

View File

@ -14,6 +14,7 @@ add_llvm_unittest(OrcJITTests
CoreAPIsTest.cpp
IndirectionUtilsTest.cpp
GlobalMappingLayerTest.cpp
JITTargetMachineBuilderTest.cpp
LazyCallThroughAndReexportsTest.cpp
LazyEmittingLayerTest.cpp
LegacyAPIInteropTest.cpp

View File

@ -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<std::string>());
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

View File

@ -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"