1bd5abe19SDimitry Andric //===-- TargetSelect.cpp - Target Chooser Code ----------------------------===//
2bd5abe19SDimitry Andric //
3bd5abe19SDimitry Andric // The LLVM Compiler Infrastructure
4bd5abe19SDimitry Andric //
5bd5abe19SDimitry Andric // This file is distributed under the University of Illinois Open Source
6bd5abe19SDimitry Andric // License. See LICENSE.TXT for details.
7bd5abe19SDimitry Andric //
8bd5abe19SDimitry Andric //===----------------------------------------------------------------------===//
9bd5abe19SDimitry Andric //
10dff0c46cSDimitry Andric // This just asks the TargetRegistry for the appropriate target to use, and
11dff0c46cSDimitry Andric // allows the user to specify a specific one on the commandline with -march=x,
12dff0c46cSDimitry Andric // -mcpu=y, and -mattr=a,-b,+c. Clients should initialize targets prior to
13dff0c46cSDimitry Andric // calling selectTarget().
14bd5abe19SDimitry Andric //
15bd5abe19SDimitry Andric //===----------------------------------------------------------------------===//
16bd5abe19SDimitry Andric
17bd5abe19SDimitry Andric #include "llvm/ADT/Triple.h"
183ca95b02SDimitry Andric #include "llvm/ExecutionEngine/ExecutionEngine.h"
19139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
2017a519f9SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
216122f3e6SDimitry Andric #include "llvm/Support/Host.h"
226122f3e6SDimitry Andric #include "llvm/Support/TargetRegistry.h"
23139f7f9bSDimitry Andric #include "llvm/Target/TargetMachine.h"
24dff0c46cSDimitry Andric
25bd5abe19SDimitry Andric using namespace llvm;
26bd5abe19SDimitry Andric
selectTarget()27dff0c46cSDimitry Andric TargetMachine *EngineBuilder::selectTarget() {
283861d79fSDimitry Andric Triple TT;
293861d79fSDimitry Andric
303861d79fSDimitry Andric // MCJIT can generate code for remote targets, but the old JIT and Interpreter
313861d79fSDimitry Andric // must use the host architecture.
3239d628a0SDimitry Andric if (WhichEngine != EngineKind::Interpreter && M)
333861d79fSDimitry Andric TT.setTriple(M->getTargetTriple());
34139f7f9bSDimitry Andric
35dff0c46cSDimitry Andric return selectTarget(TT, MArch, MCPU, MAttrs);
36dff0c46cSDimitry Andric }
37dff0c46cSDimitry Andric
38bd5abe19SDimitry Andric /// selectTarget - Pick a target either via -march or by guessing the native
39bd5abe19SDimitry Andric /// arch. Add any CPU features specified via -mcpu or -mattr.
selectTarget(const Triple & TargetTriple,StringRef MArch,StringRef MCPU,const SmallVectorImpl<std::string> & MAttrs)40dff0c46cSDimitry Andric TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple,
41bd5abe19SDimitry Andric StringRef MArch,
42bd5abe19SDimitry Andric StringRef MCPU,
43dff0c46cSDimitry Andric const SmallVectorImpl<std::string>& MAttrs) {
44dff0c46cSDimitry Andric Triple TheTriple(TargetTriple);
45bd5abe19SDimitry Andric if (TheTriple.getTriple().empty())
46139f7f9bSDimitry Andric TheTriple.setTriple(sys::getProcessTriple());
47bd5abe19SDimitry Andric
48bd5abe19SDimitry Andric // Adjust the triple to match what the user requested.
4991bc56edSDimitry Andric const Target *TheTarget = nullptr;
50bd5abe19SDimitry Andric if (!MArch.empty()) {
51d88c1a5aSDimitry Andric auto I = find_if(TargetRegistry::targets(),
52ff0cc061SDimitry Andric [&](const Target &T) { return MArch == T.getName(); });
53bd5abe19SDimitry Andric
54ff0cc061SDimitry Andric if (I == TargetRegistry::targets().end()) {
557ae0e2c9SDimitry Andric if (ErrorStr)
56bd5abe19SDimitry Andric *ErrorStr = "No available targets are compatible with this -march, "
57bd5abe19SDimitry Andric "see -version for the available targets.\n";
5891bc56edSDimitry Andric return nullptr;
59bd5abe19SDimitry Andric }
60bd5abe19SDimitry Andric
61ff0cc061SDimitry Andric TheTarget = &*I;
62ff0cc061SDimitry Andric
63bd5abe19SDimitry Andric // Adjust the triple to match (if known), otherwise stick with the
64dff0c46cSDimitry Andric // requested/host triple.
65bd5abe19SDimitry Andric Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch);
66bd5abe19SDimitry Andric if (Type != Triple::UnknownArch)
67bd5abe19SDimitry Andric TheTriple.setArch(Type);
68bd5abe19SDimitry Andric } else {
69bd5abe19SDimitry Andric std::string Error;
70bd5abe19SDimitry Andric TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
7191bc56edSDimitry Andric if (!TheTarget) {
72bd5abe19SDimitry Andric if (ErrorStr)
73bd5abe19SDimitry Andric *ErrorStr = Error;
7491bc56edSDimitry Andric return nullptr;
75bd5abe19SDimitry Andric }
76bd5abe19SDimitry Andric }
77bd5abe19SDimitry Andric
78bd5abe19SDimitry Andric // Package up features to be passed to target/subtarget
79bd5abe19SDimitry Andric std::string FeaturesStr;
8017a519f9SDimitry Andric if (!MAttrs.empty()) {
81bd5abe19SDimitry Andric SubtargetFeatures Features;
82bd5abe19SDimitry Andric for (unsigned i = 0; i != MAttrs.size(); ++i)
83bd5abe19SDimitry Andric Features.AddFeature(MAttrs[i]);
84bd5abe19SDimitry Andric FeaturesStr = Features.getString();
85bd5abe19SDimitry Andric }
86bd5abe19SDimitry Andric
87f785676fSDimitry Andric // FIXME: non-iOS ARM FastISel is broken with MCJIT.
8839d628a0SDimitry Andric if (TheTriple.getArch() == Triple::arm &&
89f785676fSDimitry Andric !TheTriple.isiOS() &&
90f785676fSDimitry Andric OptLevel == CodeGenOpt::None) {
91f785676fSDimitry Andric OptLevel = CodeGenOpt::Less;
92f785676fSDimitry Andric }
93f785676fSDimitry Andric
94bd5abe19SDimitry Andric // Allocate a target...
952cab237bSDimitry Andric TargetMachine *Target =
962cab237bSDimitry Andric TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr,
972cab237bSDimitry Andric Options, RelocModel, CMModel, OptLevel,
982cab237bSDimitry Andric /*JIT*/ true);
992cab237bSDimitry Andric Target->Options.EmulatedTLS = EmulatedTLS;
100*4ba319b5SDimitry Andric Target->Options.ExplicitEmulatedTLS = true;
101*4ba319b5SDimitry Andric
102bd5abe19SDimitry Andric assert(Target && "Could not allocate target machine!");
103bd5abe19SDimitry Andric return Target;
104bd5abe19SDimitry Andric }
105