1cf099d11SDimitry Andric //===-- TargetSelect.cpp - Target Chooser Code ----------------------------===//
2cf099d11SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cf099d11SDimitry Andric //
7cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
8cf099d11SDimitry Andric //
963faed5bSDimitry Andric // This just asks the TargetRegistry for the appropriate target to use, and
1063faed5bSDimitry Andric // allows the user to specify a specific one on the commandline with -march=x,
1163faed5bSDimitry Andric // -mcpu=y, and -mattr=a,-b,+c. Clients should initialize targets prior to
1263faed5bSDimitry Andric // calling selectTarget().
13cf099d11SDimitry Andric //
14cf099d11SDimitry Andric //===----------------------------------------------------------------------===//
15cf099d11SDimitry Andric
1601095a5dSDimitry Andric #include "llvm/ExecutionEngine/ExecutionEngine.h"
174a16efa3SDimitry Andric #include "llvm/IR/Module.h"
18c0981da4SDimitry Andric #include "llvm/MC/TargetRegistry.h"
194a16efa3SDimitry Andric #include "llvm/Target/TargetMachine.h"
207fa27ce4SDimitry Andric #include "llvm/TargetParser/Host.h"
217fa27ce4SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
227fa27ce4SDimitry Andric #include "llvm/TargetParser/Triple.h"
2363faed5bSDimitry Andric
24cf099d11SDimitry Andric using namespace llvm;
25cf099d11SDimitry Andric
selectTarget()2663faed5bSDimitry Andric TargetMachine *EngineBuilder::selectTarget() {
27522600a2SDimitry Andric Triple TT;
28522600a2SDimitry Andric
29522600a2SDimitry Andric // MCJIT can generate code for remote targets, but the old JIT and Interpreter
30522600a2SDimitry Andric // must use the host architecture.
3167c32a98SDimitry Andric if (WhichEngine != EngineKind::Interpreter && M)
32522600a2SDimitry Andric TT.setTriple(M->getTargetTriple());
334a16efa3SDimitry Andric
3463faed5bSDimitry Andric return selectTarget(TT, MArch, MCPU, MAttrs);
3563faed5bSDimitry Andric }
3663faed5bSDimitry Andric
37cf099d11SDimitry Andric /// selectTarget - Pick a target either via -march or by guessing the native
38cf099d11SDimitry Andric /// arch. Add any CPU features specified via -mcpu or -mattr.
selectTarget(const Triple & TargetTriple,StringRef MArch,StringRef MCPU,const SmallVectorImpl<std::string> & MAttrs)3963faed5bSDimitry Andric TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple,
40cf099d11SDimitry Andric StringRef MArch,
41cf099d11SDimitry Andric StringRef MCPU,
4263faed5bSDimitry Andric const SmallVectorImpl<std::string>& MAttrs) {
4363faed5bSDimitry Andric Triple TheTriple(TargetTriple);
44cf099d11SDimitry Andric if (TheTriple.getTriple().empty())
454a16efa3SDimitry Andric TheTriple.setTriple(sys::getProcessTriple());
46cf099d11SDimitry Andric
47cf099d11SDimitry Andric // Adjust the triple to match what the user requested.
485ca98fd9SDimitry Andric const Target *TheTarget = nullptr;
49cf099d11SDimitry Andric if (!MArch.empty()) {
50b915e9e0SDimitry Andric auto I = find_if(TargetRegistry::targets(),
515a5ac124SDimitry Andric [&](const Target &T) { return MArch == T.getName(); });
52cf099d11SDimitry Andric
535a5ac124SDimitry Andric if (I == TargetRegistry::targets().end()) {
5458b69754SDimitry Andric if (ErrorStr)
55cf099d11SDimitry Andric *ErrorStr = "No available targets are compatible with this -march, "
56cf099d11SDimitry Andric "see -version for the available targets.\n";
575ca98fd9SDimitry Andric return nullptr;
58cf099d11SDimitry Andric }
59cf099d11SDimitry Andric
605a5ac124SDimitry Andric TheTarget = &*I;
615a5ac124SDimitry Andric
62cf099d11SDimitry Andric // Adjust the triple to match (if known), otherwise stick with the
6363faed5bSDimitry Andric // requested/host triple.
64cf099d11SDimitry Andric Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch);
65cf099d11SDimitry Andric if (Type != Triple::UnknownArch)
66cf099d11SDimitry Andric TheTriple.setArch(Type);
67cf099d11SDimitry Andric } else {
68cf099d11SDimitry Andric std::string Error;
69cf099d11SDimitry Andric TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
705ca98fd9SDimitry Andric if (!TheTarget) {
71cf099d11SDimitry Andric if (ErrorStr)
72cf099d11SDimitry Andric *ErrorStr = Error;
735ca98fd9SDimitry Andric return nullptr;
74cf099d11SDimitry Andric }
75cf099d11SDimitry Andric }
76cf099d11SDimitry Andric
77cf099d11SDimitry Andric // Package up features to be passed to target/subtarget
78cf099d11SDimitry Andric std::string FeaturesStr;
79411bd29eSDimitry Andric if (!MAttrs.empty()) {
80cf099d11SDimitry Andric SubtargetFeatures Features;
81cf099d11SDimitry Andric for (unsigned i = 0; i != MAttrs.size(); ++i)
82cf099d11SDimitry Andric Features.AddFeature(MAttrs[i]);
83cf099d11SDimitry Andric FeaturesStr = Features.getString();
84cf099d11SDimitry Andric }
85cf099d11SDimitry Andric
86cf099d11SDimitry Andric // Allocate a target...
87044eb2f6SDimitry Andric TargetMachine *Target =
88044eb2f6SDimitry Andric TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr,
89044eb2f6SDimitry Andric Options, RelocModel, CMModel, OptLevel,
90044eb2f6SDimitry Andric /*JIT*/ true);
91044eb2f6SDimitry Andric Target->Options.EmulatedTLS = EmulatedTLS;
92eb11fae6SDimitry Andric
93cf099d11SDimitry Andric assert(Target && "Could not allocate target machine!");
94cf099d11SDimitry Andric return Target;
95cf099d11SDimitry Andric }
96