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