1*0b57cec5SDimitry Andric //===-- TargetSelect.cpp - Target Chooser Code ----------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This just asks the TargetRegistry for the appropriate target to use, and
10*0b57cec5SDimitry Andric // allows the user to specify a specific one on the commandline with -march=x,
11*0b57cec5SDimitry Andric // -mcpu=y, and -mattr=a,-b,+c. Clients should initialize targets prior to
12*0b57cec5SDimitry Andric // calling selectTarget().
13*0b57cec5SDimitry Andric //
14*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
15*0b57cec5SDimitry Andric
16*0b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
17*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/ExecutionEngine.h"
18*0b57cec5SDimitry Andric #include "llvm/IR/Module.h"
19*0b57cec5SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
20*0b57cec5SDimitry Andric #include "llvm/Support/Host.h"
21*0b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
22*0b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
23*0b57cec5SDimitry Andric
24*0b57cec5SDimitry Andric using namespace llvm;
25*0b57cec5SDimitry Andric
selectTarget()26*0b57cec5SDimitry Andric TargetMachine *EngineBuilder::selectTarget() {
27*0b57cec5SDimitry Andric Triple TT;
28*0b57cec5SDimitry Andric
29*0b57cec5SDimitry Andric // MCJIT can generate code for remote targets, but the old JIT and Interpreter
30*0b57cec5SDimitry Andric // must use the host architecture.
31*0b57cec5SDimitry Andric if (WhichEngine != EngineKind::Interpreter && M)
32*0b57cec5SDimitry Andric TT.setTriple(M->getTargetTriple());
33*0b57cec5SDimitry Andric
34*0b57cec5SDimitry Andric return selectTarget(TT, MArch, MCPU, MAttrs);
35*0b57cec5SDimitry Andric }
36*0b57cec5SDimitry Andric
37*0b57cec5SDimitry Andric /// selectTarget - Pick a target either via -march or by guessing the native
38*0b57cec5SDimitry Andric /// arch. Add any CPU features specified via -mcpu or -mattr.
selectTarget(const Triple & TargetTriple,StringRef MArch,StringRef MCPU,const SmallVectorImpl<std::string> & MAttrs)39*0b57cec5SDimitry Andric TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple,
40*0b57cec5SDimitry Andric StringRef MArch,
41*0b57cec5SDimitry Andric StringRef MCPU,
42*0b57cec5SDimitry Andric const SmallVectorImpl<std::string>& MAttrs) {
43*0b57cec5SDimitry Andric Triple TheTriple(TargetTriple);
44*0b57cec5SDimitry Andric if (TheTriple.getTriple().empty())
45*0b57cec5SDimitry Andric TheTriple.setTriple(sys::getProcessTriple());
46*0b57cec5SDimitry Andric
47*0b57cec5SDimitry Andric // Adjust the triple to match what the user requested.
48*0b57cec5SDimitry Andric const Target *TheTarget = nullptr;
49*0b57cec5SDimitry Andric if (!MArch.empty()) {
50*0b57cec5SDimitry Andric auto I = find_if(TargetRegistry::targets(),
51*0b57cec5SDimitry Andric [&](const Target &T) { return MArch == T.getName(); });
52*0b57cec5SDimitry Andric
53*0b57cec5SDimitry Andric if (I == TargetRegistry::targets().end()) {
54*0b57cec5SDimitry Andric if (ErrorStr)
55*0b57cec5SDimitry Andric *ErrorStr = "No available targets are compatible with this -march, "
56*0b57cec5SDimitry Andric "see -version for the available targets.\n";
57*0b57cec5SDimitry Andric return nullptr;
58*0b57cec5SDimitry Andric }
59*0b57cec5SDimitry Andric
60*0b57cec5SDimitry Andric TheTarget = &*I;
61*0b57cec5SDimitry Andric
62*0b57cec5SDimitry Andric // Adjust the triple to match (if known), otherwise stick with the
63*0b57cec5SDimitry Andric // requested/host triple.
64*0b57cec5SDimitry Andric Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch);
65*0b57cec5SDimitry Andric if (Type != Triple::UnknownArch)
66*0b57cec5SDimitry Andric TheTriple.setArch(Type);
67*0b57cec5SDimitry Andric } else {
68*0b57cec5SDimitry Andric std::string Error;
69*0b57cec5SDimitry Andric TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
70*0b57cec5SDimitry Andric if (!TheTarget) {
71*0b57cec5SDimitry Andric if (ErrorStr)
72*0b57cec5SDimitry Andric *ErrorStr = Error;
73*0b57cec5SDimitry Andric return nullptr;
74*0b57cec5SDimitry Andric }
75*0b57cec5SDimitry Andric }
76*0b57cec5SDimitry Andric
77*0b57cec5SDimitry Andric // Package up features to be passed to target/subtarget
78*0b57cec5SDimitry Andric std::string FeaturesStr;
79*0b57cec5SDimitry Andric if (!MAttrs.empty()) {
80*0b57cec5SDimitry Andric SubtargetFeatures Features;
81*0b57cec5SDimitry Andric for (unsigned i = 0; i != MAttrs.size(); ++i)
82*0b57cec5SDimitry Andric Features.AddFeature(MAttrs[i]);
83*0b57cec5SDimitry Andric FeaturesStr = Features.getString();
84*0b57cec5SDimitry Andric }
85*0b57cec5SDimitry Andric
86*0b57cec5SDimitry Andric // Allocate a target...
87*0b57cec5SDimitry Andric TargetMachine *Target =
88*0b57cec5SDimitry Andric TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr,
89*0b57cec5SDimitry Andric Options, RelocModel, CMModel, OptLevel,
90*0b57cec5SDimitry Andric /*JIT*/ true);
91*0b57cec5SDimitry Andric Target->Options.EmulatedTLS = EmulatedTLS;
92*0b57cec5SDimitry Andric Target->Options.ExplicitEmulatedTLS = true;
93*0b57cec5SDimitry Andric
94*0b57cec5SDimitry Andric assert(Target && "Could not allocate target machine!");
95*0b57cec5SDimitry Andric return Target;
96*0b57cec5SDimitry Andric }
97*0b57cec5SDimitry Andric