xref: /src/contrib/llvm-project/llvm/lib/ExecutionEngine/TargetSelect.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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