10b57cec5SDimitry Andric //===-- TargetSelect.cpp - Target Chooser Code ----------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This just asks the TargetRegistry for the appropriate target to use, and
100b57cec5SDimitry Andric // allows the user to specify a specific one on the commandline with -march=x,
110b57cec5SDimitry Andric // -mcpu=y, and -mattr=a,-b,+c. Clients should initialize targets prior to
120b57cec5SDimitry Andric // calling selectTarget().
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric #include "llvm/ExecutionEngine/ExecutionEngine.h"
170b57cec5SDimitry Andric #include "llvm/IR/Module.h"
18349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
190b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
20*06c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
21*06c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
22*06c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric
selectTarget()260b57cec5SDimitry Andric TargetMachine *EngineBuilder::selectTarget() {
270b57cec5SDimitry Andric Triple TT;
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric // MCJIT can generate code for remote targets, but the old JIT and Interpreter
300b57cec5SDimitry Andric // must use the host architecture.
310b57cec5SDimitry Andric if (WhichEngine != EngineKind::Interpreter && M)
320b57cec5SDimitry Andric TT.setTriple(M->getTargetTriple());
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric return selectTarget(TT, MArch, MCPU, MAttrs);
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric /// selectTarget - Pick a target either via -march or by guessing the native
380b57cec5SDimitry Andric /// arch. Add any CPU features specified via -mcpu or -mattr.
selectTarget(const Triple & TargetTriple,StringRef MArch,StringRef MCPU,const SmallVectorImpl<std::string> & MAttrs)390b57cec5SDimitry Andric TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple,
400b57cec5SDimitry Andric StringRef MArch,
410b57cec5SDimitry Andric StringRef MCPU,
420b57cec5SDimitry Andric const SmallVectorImpl<std::string>& MAttrs) {
430b57cec5SDimitry Andric Triple TheTriple(TargetTriple);
440b57cec5SDimitry Andric if (TheTriple.getTriple().empty())
450b57cec5SDimitry Andric TheTriple.setTriple(sys::getProcessTriple());
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric // Adjust the triple to match what the user requested.
480b57cec5SDimitry Andric const Target *TheTarget = nullptr;
490b57cec5SDimitry Andric if (!MArch.empty()) {
500b57cec5SDimitry Andric auto I = find_if(TargetRegistry::targets(),
510b57cec5SDimitry Andric [&](const Target &T) { return MArch == T.getName(); });
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric if (I == TargetRegistry::targets().end()) {
540b57cec5SDimitry Andric if (ErrorStr)
550b57cec5SDimitry Andric *ErrorStr = "No available targets are compatible with this -march, "
560b57cec5SDimitry Andric "see -version for the available targets.\n";
570b57cec5SDimitry Andric return nullptr;
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric TheTarget = &*I;
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric // Adjust the triple to match (if known), otherwise stick with the
630b57cec5SDimitry Andric // requested/host triple.
640b57cec5SDimitry Andric Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch);
650b57cec5SDimitry Andric if (Type != Triple::UnknownArch)
660b57cec5SDimitry Andric TheTriple.setArch(Type);
670b57cec5SDimitry Andric } else {
680b57cec5SDimitry Andric std::string Error;
690b57cec5SDimitry Andric TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
700b57cec5SDimitry Andric if (!TheTarget) {
710b57cec5SDimitry Andric if (ErrorStr)
720b57cec5SDimitry Andric *ErrorStr = Error;
730b57cec5SDimitry Andric return nullptr;
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric // Package up features to be passed to target/subtarget
780b57cec5SDimitry Andric std::string FeaturesStr;
790b57cec5SDimitry Andric if (!MAttrs.empty()) {
800b57cec5SDimitry Andric SubtargetFeatures Features;
810b57cec5SDimitry Andric for (unsigned i = 0; i != MAttrs.size(); ++i)
820b57cec5SDimitry Andric Features.AddFeature(MAttrs[i]);
830b57cec5SDimitry Andric FeaturesStr = Features.getString();
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric // Allocate a target...
870b57cec5SDimitry Andric TargetMachine *Target =
880b57cec5SDimitry Andric TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr,
890b57cec5SDimitry Andric Options, RelocModel, CMModel, OptLevel,
900b57cec5SDimitry Andric /*JIT*/ true);
910b57cec5SDimitry Andric Target->Options.EmulatedTLS = EmulatedTLS;
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric assert(Target && "Could not allocate target machine!");
940b57cec5SDimitry Andric return Target;
950b57cec5SDimitry Andric }
96