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.
20dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic Target *FirstTarget = nullptr;
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.
32dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  const Target *TheTarget = nullptr;
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";
44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return nullptr;
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);
56dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (!TheTarget) {
579ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby      Error = ": error: unable to get target for '"
589ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby            + TheTriple.getTriple()
599ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby            + "', see --version and --triple.\n";
60dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return nullptr;
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)";
72dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
737df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar  }
74dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  const Target *Matching = nullptr;
7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  Triple::ArchType Arch =  Triple(TT).getArch();
76603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar  for (iterator it = begin(), ie = end(); it != ie; ++it) {
7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (it->ArchMatchFn(Arch)) {
7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (Matching) {
7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Error = std::string("Cannot choose between targets \"") +
8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          Matching->Name  + "\" and \"" + it->Name + "\"";
81dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return nullptr;
8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      }
8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Matching = &*it;
84bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar    }
85bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  }
86bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (!Matching) {
880247656d0aaaee69ab20ff0ad56536bff38b3715Daniel Dunbar    Error = "No available targets are compatible with this triple, "
890247656d0aaaee69ab20ff0ad56536bff38b3715Daniel Dunbar      "see -version for the available targets.";
90dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return nullptr;
91bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  }
92bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return Matching;
94bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar}
95bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
96bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbarvoid TargetRegistry::RegisterTarget(Target &T,
97bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar                                    const char *Name,
98bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar                                    const char *ShortDesc,
9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                    Target::ArchMatchFnTy ArchMatchFn,
100d6fd377f3333922c4e928019cdfa124ff7f4dd2eDaniel Dunbar                                    bool HasJIT) {
10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  assert(Name && ShortDesc && ArchMatchFn &&
102bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar         "Missing required target information!");
10351b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar
10451b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar  // Check if this target has already been initialized, we allow this as a
10551b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar  // convenience to some clients.
10651b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar  if (T.Name)
10751b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar    return;
108bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
109bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  // Add to the list of targets.
110bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  T.Next = FirstTarget;
111f23d4930bdd5ee00354883f8756388573fa43e88Daniel Dunbar  FirstTarget = &T;
112bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
113bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  T.Name = Name;
114bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar  T.ShortDesc = ShortDesc;
11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  T.ArchMatchFn = ArchMatchFn;
116d6fd377f3333922c4e928019cdfa124ff7f4dd2eDaniel Dunbar  T.HasJIT = HasJIT;
117bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar}
118bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar
1190d293e45b66c742fdbc3998209bb20ed6c5806bfBenjamin Kramerstatic int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS,
1200d293e45b66c742fdbc3998209bb20ed6c5806bfBenjamin Kramer                             const std::pair<StringRef, const Target *> *RHS) {
1210d293e45b66c742fdbc3998209bb20ed6c5806bfBenjamin Kramer  return LHS->first.compare(RHS->first);
122077c40871780136f7016a496703b20ebea9c0978Chandler Carruth}
123077c40871780136f7016a496703b20ebea9c0978Chandler Carruth
124077c40871780136f7016a496703b20ebea9c0978Chandler Carruthvoid TargetRegistry::printRegisteredTargetsForVersion() {
125077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  std::vector<std::pair<StringRef, const Target*> > Targets;
126077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  size_t Width = 0;
127077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  for (TargetRegistry::iterator I = TargetRegistry::begin(),
128077c40871780136f7016a496703b20ebea9c0978Chandler Carruth       E = TargetRegistry::end();
129077c40871780136f7016a496703b20ebea9c0978Chandler Carruth       I != E; ++I) {
130077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    Targets.push_back(std::make_pair(I->getName(), &*I));
131077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    Width = std::max(Width, Targets.back().first.size());
132077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  }
133077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn);
134077c40871780136f7016a496703b20ebea9c0978Chandler Carruth
135077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  raw_ostream &OS = outs();
136077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  OS << "  Registered Targets:\n";
137077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  for (unsigned i = 0, e = Targets.size(); i != e; ++i) {
138077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    OS << "    " << Targets[i].first;
139077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    OS.indent(Width - Targets[i].first.size()) << " - "
140077c40871780136f7016a496703b20ebea9c0978Chandler Carruth      << Targets[i].second->getShortDescription() << '\n';
141077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  }
142077c40871780136f7016a496703b20ebea9c0978Chandler Carruth  if (Targets.empty())
143077c40871780136f7016a496703b20ebea9c0978Chandler Carruth    OS << "    (none)\n";
144077c40871780136f7016a496703b20ebea9c0978Chandler Carruth}
145