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 { @@ -180,6 +181,15 @@ /// 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. For example, "opt" uses this functon to infer the default +/// DataLayout for a given triple. +Expected> +createTargetMachineForTriple(StringRef TargetTriple, + CodeGenOpt::Level OptLevel = CodeGenOpt::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 @@ -20,9 +20,11 @@ #include "llvm/IR/Module.h" #include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Target/TargetMachine.h" #include using namespace llvm; @@ -716,3 +718,24 @@ for (Function &F : M) setFunctionAttributes(CPU, Features, F); } + +Expected> +codegen::createTargetMachineForTriple(StringRef TargetTriple, + CodeGenOpt::Level 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(); CodeGenOpt::Level OLvl = CodeGenOpt::Default; switch (OptLevel) { @@ -155,11 +142,8 @@ case '2': OLvl = CodeGenOpt::Default; break; case '3': OLvl = CodeGenOpt::Aggressive; break; } - - 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 @@ -212,23 +212,8 @@ 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(), CodeGenOpt::Default)); - assert(TM && "Could not allocate target machine!"); + ExitOnError ExitOnErr(std::string(*argv[0]) + ": error:"); + TM = ExitOnErr(codegen::createTargetMachineForTriple(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 @@ -408,32 +408,18 @@ createMIRParser(std::move(FileOrErr.get()), Ctxt); auto SetDataLayout = - [&](StringRef DataLayoutTargetTriple) -> std::optional { - // If we are supposed to override the target triple, do so now. + [&](StringRef DataLayoutTargetTriple) -> Optional { + // 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(), CodeGenOpt::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 @@ -296,24 +296,6 @@ return static_cast(unsigned(CodeGenOptLevel)); } -// 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()); -} - #ifdef BUILD_EXAMPLES void initializeExampleIRTransforms(llvm::PassRegistry &Registry); #endif @@ -406,6 +388,7 @@ // int main(int argc, char **argv) { InitLLVM X(argc, argv); + ExitOnError ExitOnErr(std::string(argv[0]) + ": error: "); // Enable debug stream buffering. EnableDebugBuffering = true; @@ -610,14 +593,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 '" @@ -625,8 +606,6 @@ return 1; } - std::unique_ptr TM(Machine); - // Override function attributes based on CPUStr, FeaturesStr, and command line // flags. codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M);