1223013Sdim//===-- TargetSelect.cpp - Target Chooser Code ----------------------------===//
2223013Sdim//
3223013Sdim//                     The LLVM Compiler Infrastructure
4223013Sdim//
5223013Sdim// This file is distributed under the University of Illinois Open Source
6223013Sdim// License. See LICENSE.TXT for details.
7223013Sdim//
8223013Sdim//===----------------------------------------------------------------------===//
9223013Sdim//
10234353Sdim// This just asks the TargetRegistry for the appropriate target to use, and
11234353Sdim// allows the user to specify a specific one on the commandline with -march=x,
12234353Sdim// -mcpu=y, and -mattr=a,-b,+c. Clients should initialize targets prior to
13234353Sdim// calling selectTarget().
14223013Sdim//
15223013Sdim//===----------------------------------------------------------------------===//
16223013Sdim
17223013Sdim#include "llvm/ExecutionEngine/ExecutionEngine.h"
18223013Sdim#include "llvm/ADT/Triple.h"
19249423Sdim#include "llvm/IR/Module.h"
20224145Sdim#include "llvm/MC/SubtargetFeature.h"
21223013Sdim#include "llvm/Support/CommandLine.h"
22226633Sdim#include "llvm/Support/Host.h"
23226633Sdim#include "llvm/Support/TargetRegistry.h"
24249423Sdim#include "llvm/Target/TargetMachine.h"
25234353Sdim
26223013Sdimusing namespace llvm;
27223013Sdim
28234353SdimTargetMachine *EngineBuilder::selectTarget() {
29243830Sdim  Triple TT;
30243830Sdim
31243830Sdim  // MCJIT can generate code for remote targets, but the old JIT and Interpreter
32243830Sdim  // must use the host architecture.
33280031Sdim  if (WhichEngine != EngineKind::Interpreter && M)
34243830Sdim    TT.setTriple(M->getTargetTriple());
35249423Sdim
36234353Sdim  return selectTarget(TT, MArch, MCPU, MAttrs);
37234353Sdim}
38234353Sdim
39223013Sdim/// selectTarget - Pick a target either via -march or by guessing the native
40223013Sdim/// arch.  Add any CPU features specified via -mcpu or -mattr.
41234353SdimTargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple,
42223013Sdim                              StringRef MArch,
43223013Sdim                              StringRef MCPU,
44234353Sdim                              const SmallVectorImpl<std::string>& MAttrs) {
45234353Sdim  Triple TheTriple(TargetTriple);
46223013Sdim  if (TheTriple.getTriple().empty())
47249423Sdim    TheTriple.setTriple(sys::getProcessTriple());
48223013Sdim
49223013Sdim  // Adjust the triple to match what the user requested.
50276479Sdim  const Target *TheTarget = nullptr;
51223013Sdim  if (!MArch.empty()) {
52288943Sdim    auto I = std::find_if(
53288943Sdim        TargetRegistry::targets().begin(), TargetRegistry::targets().end(),
54288943Sdim        [&](const Target &T) { return MArch == T.getName(); });
55223013Sdim
56288943Sdim    if (I == TargetRegistry::targets().end()) {
57239462Sdim      if (ErrorStr)
58239462Sdim        *ErrorStr = "No available targets are compatible with this -march, "
59239462Sdim                    "see -version for the available targets.\n";
60276479Sdim      return nullptr;
61223013Sdim    }
62223013Sdim
63288943Sdim    TheTarget = &*I;
64288943Sdim
65223013Sdim    // Adjust the triple to match (if known), otherwise stick with the
66234353Sdim    // requested/host triple.
67223013Sdim    Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch);
68223013Sdim    if (Type != Triple::UnknownArch)
69223013Sdim      TheTriple.setArch(Type);
70223013Sdim  } else {
71223013Sdim    std::string Error;
72223013Sdim    TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
73276479Sdim    if (!TheTarget) {
74223013Sdim      if (ErrorStr)
75223013Sdim        *ErrorStr = Error;
76276479Sdim      return nullptr;
77223013Sdim    }
78223013Sdim  }
79223013Sdim
80223013Sdim  // Package up features to be passed to target/subtarget
81223013Sdim  std::string FeaturesStr;
82224145Sdim  if (!MAttrs.empty()) {
83223013Sdim    SubtargetFeatures Features;
84223013Sdim    for (unsigned i = 0; i != MAttrs.size(); ++i)
85223013Sdim      Features.AddFeature(MAttrs[i]);
86223013Sdim    FeaturesStr = Features.getString();
87223013Sdim  }
88223013Sdim
89261991Sdim  // FIXME: non-iOS ARM FastISel is broken with MCJIT.
90280031Sdim  if (TheTriple.getArch() == Triple::arm &&
91261991Sdim      !TheTriple.isiOS() &&
92261991Sdim      OptLevel == CodeGenOpt::None) {
93261991Sdim    OptLevel = CodeGenOpt::Less;
94261991Sdim  }
95261991Sdim
96223013Sdim  // Allocate a target...
97226633Sdim  TargetMachine *Target = TheTarget->createTargetMachine(TheTriple.getTriple(),
98226633Sdim                                                         MCPU, FeaturesStr,
99234353Sdim                                                         Options,
100234353Sdim                                                         RelocModel, CMModel,
101234353Sdim                                                         OptLevel);
102223013Sdim  assert(Target && "Could not allocate target machine!");
103223013Sdim  return Target;
104223013Sdim}
105