1bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar//===--- TargetRegistry.cpp - Target registration -------------------------===//
2bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar//
3bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar//                     The LLVM Compiler Infrastructure
4bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar//
5bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar// This file is distributed under the University of Illinois Open Source
6bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar// License. See LICENSE.TXT for details.
7bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar//
8bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar//===----------------------------------------------------------------------===//
9bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
103e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h"
11077c40871780136f7016a496703b20ebea9c0978Chandler Carruth#include "llvm/ADT/STLExtras.h"
12077c40871780136f7016a496703b20ebea9c0978Chandler Carruth#include "llvm/ADT/StringRef.h"
131f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Host.h"
14077c40871780136f7016a496703b20ebea9c0978Chandler Carruth#include "llvm/Support/raw_ostream.h"
15bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar#include <cassert>
16077c40871780136f7016a496703b20ebea9c0978Chandler Carruth#include <vector>
17bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbarusing namespace llvm;
18bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
1973b3ec41349511dbf28c18997e3f64761ff0f114Daniel Dunbar// Clients are responsible for avoid race conditions in registration.
20bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbarstatic Target *FirstTarget = 0;
21bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
22603bea32743dc9914a1d32ae36fc64fe497af801Daniel DunbarTargetRegistry::iterator TargetRegistry::begin() {
23603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar  return iterator(FirstTarget);
24603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar}
25603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar
269ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderbyconst Target *TargetRegistry::lookupTarget(const std::string &ArchName,
279ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby                                           Triple &TheTriple,
289ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby                                           std::string &Error) {
299ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  // Allocate target machine.  First, check whether the user has explicitly
309ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  // specified an architecture to compile for. If so we have to look it up by
319ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  // name, because it might be a backend that has no mapping to a target triple.
329ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  const Target *TheTarget = 0;
339ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  if (!ArchName.empty()) {
349ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    for (TargetRegistry::iterator it = TargetRegistry::begin(),
359ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby           ie = TargetRegistry::end(); it != ie; ++it) {
369ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby      if (ArchName == it->getName()) {
379ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby        TheTarget = &*it;
389ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby        break;
399ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby      }
409ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    }
419ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby
429ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    if (!TheTarget) {
439ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby      Error = "error: invalid target '" + ArchName + "'.\n";
449ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby      return 0;
459ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    }
469ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby
479ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    // Adjust the triple to match (if known), otherwise stick with the
489ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    // given triple.
499ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
509ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    if (Type != Triple::UnknownArch)
519ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby      TheTriple.setArch(Type);
529ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  } else {
539ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    // Get the target specific parser.
549ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    std::string TempError;
559ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError);
569ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    if (TheTarget == 0) {
579ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby      Error = ": error: unable to get target for '"
589ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby            + TheTriple.getTriple()
599ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby            + "', see --version and --triple.\n";
609ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby      return 0;
619ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby    }
629ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  }
639ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby
649ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby  return TheTarget;
659ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby}
669ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby
67a5881e3060aee9f82aef3747a97650e5eafe893aDaniel Dunbarconst Target *TargetRegistry::lookupTarget(const std::string &TT,
68a5881e3060aee9f82aef3747a97650e5eafe893aDaniel Dunbar                                           std::string &Error) {
697df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar  // Provide special warning when no targets are initialized.
707df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar  if (begin() == end()) {
717df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar    Error = "Unable to find target for this triple (no targets are registered)";
727df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar    return 0;
737df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar  }
74603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar  const Target *Best = 0, *EquallyBest = 0;
75bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  unsigned BestQuality = 0;
76603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar  for (iterator it = begin(), ie = end(); it != ie; ++it) {
77a5881e3060aee9f82aef3747a97650e5eafe893aDaniel Dunbar    if (unsigned Qual = it->TripleMatchQualityFn(TT)) {
78bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar      if (!Best || Qual > BestQuality) {
79603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar        Best = &*it;
80bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar        EquallyBest = 0;
81bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar        BestQuality = Qual;
82bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar      } else if (Qual == BestQuality)
83603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar        EquallyBest = &*it;
84bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar    }
85bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  }
86bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
87bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  if (!Best) {
880247656d0aaaee69ab20ff0ad56536bff38b3715Daniel Dunbar    Error = "No available targets are compatible with this triple, "
890247656d0aaaee69ab20ff0ad56536bff38b3715Daniel Dunbar      "see -version for the available targets.";
90a5881e3060aee9f82aef3747a97650e5eafe893aDaniel Dunbar    return 0;
91bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  }
92bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
93bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  // Otherwise, take the best target, but make sure we don't have two equally
94bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  // good best targets.
95bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  if (EquallyBest) {
96bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar    Error = std::string("Cannot choose between targets \"") +
97bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar      Best->Name  + "\" and \"" + EquallyBest->Name + "\"";
98bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar    return 0;
99bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  }
100bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
101bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  return Best;
102bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar}
103bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
104bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbarvoid TargetRegistry::RegisterTarget(Target &T,
105bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar                                    const char *Name,
106bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar                                    const char *ShortDesc,
107bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar                                    Target::TripleMatchQualityFnTy TQualityFn,
108d6fd377f3333922c4e928019cdfa124ff7f4dd2eDaniel Dunbar                                    bool HasJIT) {
109fa27ff296d3694a68e7abb3b6b7629588def3e58Daniel Dunbar  assert(Name && ShortDesc && TQualityFn &&
110bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar         "Missing required target information!");
11151b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar
11251b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar  // Check if this target has already been initialized, we allow this as a
11351b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar  // convenience to some clients.
11451b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar  if (T.Name)
11551b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar    return;
116bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
117bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  // Add to the list of targets.
118bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  T.Next = FirstTarget;
119f23d4930bdd5ee00354883f8756388573fa43e88Daniel Dunbar  FirstTarget = &T;
120bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
121bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  T.Name = Name;
122bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  T.ShortDesc = ShortDesc;
123bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  T.TripleMatchQualityFn = TQualityFn;
124d6fd377f3333922c4e928019cdfa124ff7f4dd2eDaniel Dunbar  T.HasJIT = HasJIT;
125bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar}
126bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
1274bd03abe593222b26e84066223feb321bf738625Daniel Dunbarconst Target *TargetRegistry::getClosestTargetForJIT(std::string &Error) {
1286e9b5eb51bb623995c90295d265a7682277653a1Sebastian Pop  const Target *TheTarget = lookupTarget(sys::getDefaultTargetTriple(), Error);
1294bd03abe593222b26e84066223feb321bf738625Daniel Dunbar
1304bd03abe593222b26e84066223feb321bf738625Daniel Dunbar  if (TheTarget && !TheTarget->hasJIT()) {
1314bd03abe593222b26e84066223feb321bf738625Daniel Dunbar    Error = "No JIT compatible target available for this host";
1324bd03abe593222b26e84066223feb321bf738625Daniel Dunbar    return 0;
1334bd03abe593222b26e84066223feb321bf738625Daniel Dunbar  }
1344bd03abe593222b26e84066223feb321bf738625Daniel Dunbar
1354bd03abe593222b26e84066223feb321bf738625Daniel Dunbar  return TheTarget;
1364bd03abe593222b26e84066223feb321bf738625Daniel Dunbar}
1374bd03abe593222b26e84066223feb321bf738625Daniel Dunbar
138077c40871780136f7016a496703b20ebea9c0978Chandler Carruthstatic int TargetArraySortFn(const void *LHS, const void *RHS) {
139077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  typedef std::pair<StringRef, const Target*> pair_ty;
140077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  return ((const pair_ty*)LHS)->first.compare(((const pair_ty*)RHS)->first);
141077c40871780136f7016a496703b20ebea9c0978Chandler Carruth}
142077c40871780136f7016a496703b20ebea9c0978Chandler Carruth
143077c40871780136f7016a496703b20ebea9c0978Chandler Carruthvoid TargetRegistry::printRegisteredTargetsForVersion() {
144077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  std::vector<std::pair<StringRef, const Target*> > Targets;
145077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  size_t Width = 0;
146077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  for (TargetRegistry::iterator I = TargetRegistry::begin(),
147077c40871780136f7016a496703b20ebea9c0978Chandler Carruth       E = TargetRegistry::end();
148077c40871780136f7016a496703b20ebea9c0978Chandler Carruth       I != E; ++I) {
149077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    Targets.push_back(std::make_pair(I->getName(), &*I));
150077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    Width = std::max(Width, Targets.back().first.size());
151077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  }
152077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn);
153077c40871780136f7016a496703b20ebea9c0978Chandler Carruth
154077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  raw_ostream &OS = outs();
155077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  OS << "  Registered Targets:\n";
156077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  for (unsigned i = 0, e = Targets.size(); i != e; ++i) {
157077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    OS << "    " << Targets[i].first;
158077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    OS.indent(Width - Targets[i].first.size()) << " - "
159077c40871780136f7016a496703b20ebea9c0978Chandler Carruth      << Targets[i].second->getShortDescription() << '\n';
160077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  }
161077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  if (Targets.empty())
162077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    OS << "    (none)\n";
163077c40871780136f7016a496703b20ebea9c0978Chandler Carruth}
164