diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h --- a/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/llvm/include/llvm/CodeGen/CommandFlags.h @@ -28,6 +28,7 @@ class AttrBuilder; class Function; class Triple; +class TargetMachine; namespace codegen { @@ -186,6 +187,14 @@ /// Should value-tracking variable locations / instruction referencing be /// enabled by default for this triple? bool getDefaultValueTrackingVariableLocations(const llvm::Triple &T); + +/// Creates a TargetMachine instance with the options defined on the command +/// line. This can be used for tools that do not need further customization of +/// the TargetOptions. +Expected> createTargetMachineForTriple( + StringRef TargetTriple, + CodeGenOptLevel OptLevel = CodeGenOptLevel::Default); + } // namespace codegen } // namespace llvm diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -18,8 +18,10 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCTargetOptionsCommandFlags.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/TargetParser/Host.h" #include "llvm/TargetParser/SubtargetFeature.h" #include "llvm/TargetParser/Triple.h" @@ -732,3 +734,24 @@ for (Function &F : M) setFunctionAttributes(CPU, Features, F); } + +Expected> +codegen::createTargetMachineForTriple(StringRef TargetTriple, + CodeGenOptLevel OptLevel) { + Triple TheTriple(TargetTriple); + std::string Error; + const auto *TheTarget = + TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error); + if (!TheTarget) + return createStringError(inconvertibleErrorCode(), Error); + auto *Target = TheTarget->createTargetMachine( + TheTriple.getTriple(), codegen::getCPUStr(), codegen::getFeaturesStr(), + codegen::InitTargetOptionsFromCodeGenFlags(TheTriple), + codegen::getExplicitRelocModel(), codegen::getExplicitCodeModel(), + OptLevel); + if (!Target) + return createStringError(inconvertibleErrorCode(), + Twine("could not allocate target machine for ") + + TargetTriple); + return std::unique_ptr(Target); +} diff --git a/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp b/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp --- a/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp +++ b/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp @@ -129,20 +129,7 @@ exit(1); } - Triple TheTriple = Triple(Triple::normalize(TargetTriple)); - - // Get the target specific parser. - std::string Error; - const Target *TheTarget = - TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error); - if (!TheTarget) { - errs() << argv[0] << ": " << Error; - return 1; - } - // Set up the pipeline like llc does. - std::string CPUStr = codegen::getCPUStr(), - FeaturesStr = codegen::getFeaturesStr(); CodeGenOptLevel OLvl; if (auto Level = CodeGenOpt::parseLevel(OptLevel)) { @@ -151,11 +138,8 @@ errs() << argv[0] << ": invalid optimization level.\n"; return 1; } - - TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(TheTriple); - TM.reset(TheTarget->createTargetMachine( - TheTriple.getTriple(), CPUStr, FeaturesStr, Options, - codegen::getExplicitRelocModel(), codegen::getExplicitCodeModel(), OLvl)); + ExitOnError ExitOnErr(std::string(*argv[0]) + ": error:"); + TM = ExitOnErr(codegen::createTargetMachineForTriple(TargetTriple, OLvl)); assert(TM && "Could not allocate target machine!"); // Make sure we print the summary and the current unit when LLVM errors out. diff --git a/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp b/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp --- a/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp +++ b/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp @@ -198,23 +198,9 @@ errs() << *argv[0] << ": -mtriple must be specified\n"; exit(1); } - Triple TargetTriple = Triple(Triple::normalize(TargetTripleStr)); - - std::string Error; - const Target *TheTarget = - TargetRegistry::lookupTarget(codegen::getMArch(), TargetTriple, Error); - if (!TheTarget) { - errs() << *argv[0] << ": " << Error; - exit(1); - } - - TargetOptions Options = - codegen::InitTargetOptionsFromCodeGenFlags(TargetTriple); - TM.reset(TheTarget->createTargetMachine( - TargetTriple.getTriple(), codegen::getCPUStr(), codegen::getFeaturesStr(), - Options, codegen::getExplicitRelocModel(), - codegen::getExplicitCodeModel(), CodeGenOptLevel::Default)); - assert(TM && "Could not allocate target machine!"); + ExitOnError ExitOnErr(std::string(*argv[0]) + ": error:"); + TM = ExitOnErr(codegen::createTargetMachineForTriple( + Triple::normalize(TargetTripleStr))); // Check that pass pipeline is specified and correct // diff --git a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp --- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp +++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp @@ -764,31 +764,17 @@ auto SetDataLayout = [&](StringRef DataLayoutTargetTriple, StringRef OldDLStr) -> std::optional { - // If we are supposed to override the target triple, do so now. + // NB: We always call createTargetMachineForTriple() even if an explicit + // DataLayout is already set in the module since we want to use this + // callback to setup the TargetMachine rather than doing it later. std::string IRTargetTriple = DataLayoutTargetTriple.str(); if (!TargetTriple.empty()) IRTargetTriple = Triple::normalize(TargetTriple); TheTriple = Triple(IRTargetTriple); if (TheTriple.getTriple().empty()) TheTriple.setTriple(sys::getDefaultTargetTriple()); - - std::string Error; - const Target *TheTarget = - TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error); - if (!TheTarget) { - WithColor::error(errs(), ToolName) << Error; - exit(1); - } - - // Hopefully the MIR parsing doesn't depend on any options. - TargetOptions Options; - std::optional RM = codegen::getExplicitRelocModel(); - std::string CPUStr = codegen::getCPUStr(); - std::string FeaturesStr = codegen::getFeaturesStr(); - TM = std::unique_ptr(TheTarget->createTargetMachine( - TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM, - codegen::getExplicitCodeModel(), CodeGenOptLevel::Default)); - assert(TM && "Could not allocate target machine!"); + ExitOnError ExitOnErr(std::string(ToolName) + ": error: "); + TM = ExitOnErr(codegen::createTargetMachineForTriple(TheTriple.str())); return TM->createDataLayout().getStringRepresentation(); }; diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp --- a/llvm/tools/opt/opt.cpp +++ b/llvm/tools/opt/opt.cpp @@ -286,24 +286,6 @@ return static_cast(unsigned(CodeGenOptLevelCL)); } -// Returns the TargetMachine instance or zero if no triple is provided. -static TargetMachine* GetTargetMachine(Triple TheTriple, StringRef CPUStr, - StringRef FeaturesStr, - const TargetOptions &Options) { - std::string Error; - const Target *TheTarget = - TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error); - // Some modules don't specify a triple, and this is okay. - if (!TheTarget) { - return nullptr; - } - - return TheTarget->createTargetMachine( - TheTriple.getTriple(), codegen::getCPUStr(), codegen::getFeaturesStr(), - Options, codegen::getExplicitRelocModel(), - codegen::getExplicitCodeModel(), GetCodeGenOptLevel()); -} - struct TimeTracerRAII { TimeTracerRAII(StringRef ProgramName) { if (TimeTrace) @@ -410,6 +392,7 @@ // int main(int argc, char **argv) { InitLLVM X(argc, argv); + ExitOnError ExitOnErr(std::string(argv[0]) + ": error: "); // Enable debug stream buffering. EnableDebugBuffering = true; @@ -611,14 +594,12 @@ Triple ModuleTriple(M->getTargetTriple()); std::string CPUStr, FeaturesStr; - TargetMachine *Machine = nullptr; - const TargetOptions Options = - codegen::InitTargetOptionsFromCodeGenFlags(ModuleTriple); - + std::unique_ptr TM; if (ModuleTriple.getArch()) { CPUStr = codegen::getCPUStr(); FeaturesStr = codegen::getFeaturesStr(); - Machine = GetTargetMachine(ModuleTriple, CPUStr, FeaturesStr, Options); + TM = ExitOnErr(codegen::createTargetMachineForTriple(ModuleTriple.str(), + GetCodeGenOptLevel())); } else if (ModuleTriple.getArchName() != "unknown" && ModuleTriple.getArchName() != "") { errs() << argv[0] << ": unrecognized architecture '" @@ -626,8 +607,6 @@ return 1; } - std::unique_ptr TM(Machine); - // Override function attributes based on CPUStr, FeaturesStr, and command line // flags. codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M);