1f4a2713aSLionel Sambuc //===--- TargetRegistry.cpp - Target registration -------------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc 
10f4a2713aSLionel Sambuc #include "llvm/Support/TargetRegistry.h"
11f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h"
12f4a2713aSLionel Sambuc #include "llvm/ADT/StringRef.h"
13f4a2713aSLionel Sambuc #include "llvm/Support/Host.h"
14f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
15f4a2713aSLionel Sambuc #include <cassert>
16f4a2713aSLionel Sambuc #include <vector>
17f4a2713aSLionel Sambuc using namespace llvm;
18f4a2713aSLionel Sambuc 
19f4a2713aSLionel Sambuc // Clients are responsible for avoid race conditions in registration.
20*0a6a1f1dSLionel Sambuc static Target *FirstTarget = nullptr;
21f4a2713aSLionel Sambuc 
begin()22f4a2713aSLionel Sambuc TargetRegistry::iterator TargetRegistry::begin() {
23f4a2713aSLionel Sambuc   return iterator(FirstTarget);
24f4a2713aSLionel Sambuc }
25f4a2713aSLionel Sambuc 
lookupTarget(const std::string & ArchName,Triple & TheTriple,std::string & Error)26f4a2713aSLionel Sambuc const Target *TargetRegistry::lookupTarget(const std::string &ArchName,
27f4a2713aSLionel Sambuc                                            Triple &TheTriple,
28f4a2713aSLionel Sambuc                                            std::string &Error) {
29f4a2713aSLionel Sambuc   // Allocate target machine.  First, check whether the user has explicitly
30f4a2713aSLionel Sambuc   // specified an architecture to compile for. If so we have to look it up by
31f4a2713aSLionel Sambuc   // name, because it might be a backend that has no mapping to a target triple.
32*0a6a1f1dSLionel Sambuc   const Target *TheTarget = nullptr;
33f4a2713aSLionel Sambuc   if (!ArchName.empty()) {
34f4a2713aSLionel Sambuc     for (TargetRegistry::iterator it = TargetRegistry::begin(),
35f4a2713aSLionel Sambuc            ie = TargetRegistry::end(); it != ie; ++it) {
36f4a2713aSLionel Sambuc       if (ArchName == it->getName()) {
37f4a2713aSLionel Sambuc         TheTarget = &*it;
38f4a2713aSLionel Sambuc         break;
39f4a2713aSLionel Sambuc       }
40f4a2713aSLionel Sambuc     }
41f4a2713aSLionel Sambuc 
42f4a2713aSLionel Sambuc     if (!TheTarget) {
43f4a2713aSLionel Sambuc       Error = "error: invalid target '" + ArchName + "'.\n";
44*0a6a1f1dSLionel Sambuc       return nullptr;
45f4a2713aSLionel Sambuc     }
46f4a2713aSLionel Sambuc 
47f4a2713aSLionel Sambuc     // Adjust the triple to match (if known), otherwise stick with the
48f4a2713aSLionel Sambuc     // given triple.
49f4a2713aSLionel Sambuc     Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
50f4a2713aSLionel Sambuc     if (Type != Triple::UnknownArch)
51f4a2713aSLionel Sambuc       TheTriple.setArch(Type);
52f4a2713aSLionel Sambuc   } else {
53f4a2713aSLionel Sambuc     // Get the target specific parser.
54f4a2713aSLionel Sambuc     std::string TempError;
55f4a2713aSLionel Sambuc     TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError);
56*0a6a1f1dSLionel Sambuc     if (!TheTarget) {
57f4a2713aSLionel Sambuc       Error = ": error: unable to get target for '"
58f4a2713aSLionel Sambuc             + TheTriple.getTriple()
59f4a2713aSLionel Sambuc             + "', see --version and --triple.\n";
60*0a6a1f1dSLionel Sambuc       return nullptr;
61f4a2713aSLionel Sambuc     }
62f4a2713aSLionel Sambuc   }
63f4a2713aSLionel Sambuc 
64f4a2713aSLionel Sambuc   return TheTarget;
65f4a2713aSLionel Sambuc }
66f4a2713aSLionel Sambuc 
lookupTarget(const std::string & TT,std::string & Error)67f4a2713aSLionel Sambuc const Target *TargetRegistry::lookupTarget(const std::string &TT,
68f4a2713aSLionel Sambuc                                            std::string &Error) {
69f4a2713aSLionel Sambuc   // Provide special warning when no targets are initialized.
70f4a2713aSLionel Sambuc   if (begin() == end()) {
71f4a2713aSLionel Sambuc     Error = "Unable to find target for this triple (no targets are registered)";
72*0a6a1f1dSLionel Sambuc     return nullptr;
73f4a2713aSLionel Sambuc   }
74*0a6a1f1dSLionel Sambuc   const Target *Matching = nullptr;
75*0a6a1f1dSLionel Sambuc   Triple::ArchType Arch =  Triple(TT).getArch();
76f4a2713aSLionel Sambuc   for (iterator it = begin(), ie = end(); it != ie; ++it) {
77*0a6a1f1dSLionel Sambuc     if (it->ArchMatchFn(Arch)) {
78*0a6a1f1dSLionel Sambuc       if (Matching) {
79*0a6a1f1dSLionel Sambuc         Error = std::string("Cannot choose between targets \"") +
80*0a6a1f1dSLionel Sambuc           Matching->Name  + "\" and \"" + it->Name + "\"";
81*0a6a1f1dSLionel Sambuc         return nullptr;
82*0a6a1f1dSLionel Sambuc       }
83*0a6a1f1dSLionel Sambuc       Matching = &*it;
84f4a2713aSLionel Sambuc     }
85f4a2713aSLionel Sambuc   }
86f4a2713aSLionel Sambuc 
87*0a6a1f1dSLionel Sambuc   if (!Matching) {
88f4a2713aSLionel Sambuc     Error = "No available targets are compatible with this triple, "
89f4a2713aSLionel Sambuc       "see -version for the available targets.";
90*0a6a1f1dSLionel Sambuc     return nullptr;
91f4a2713aSLionel Sambuc   }
92f4a2713aSLionel Sambuc 
93*0a6a1f1dSLionel Sambuc   return Matching;
94f4a2713aSLionel Sambuc }
95f4a2713aSLionel Sambuc 
RegisterTarget(Target & T,const char * Name,const char * ShortDesc,Target::ArchMatchFnTy ArchMatchFn,bool HasJIT)96f4a2713aSLionel Sambuc void TargetRegistry::RegisterTarget(Target &T,
97f4a2713aSLionel Sambuc                                     const char *Name,
98f4a2713aSLionel Sambuc                                     const char *ShortDesc,
99*0a6a1f1dSLionel Sambuc                                     Target::ArchMatchFnTy ArchMatchFn,
100f4a2713aSLionel Sambuc                                     bool HasJIT) {
101*0a6a1f1dSLionel Sambuc   assert(Name && ShortDesc && ArchMatchFn &&
102f4a2713aSLionel Sambuc          "Missing required target information!");
103f4a2713aSLionel Sambuc 
104f4a2713aSLionel Sambuc   // Check if this target has already been initialized, we allow this as a
105f4a2713aSLionel Sambuc   // convenience to some clients.
106f4a2713aSLionel Sambuc   if (T.Name)
107f4a2713aSLionel Sambuc     return;
108f4a2713aSLionel Sambuc 
109f4a2713aSLionel Sambuc   // Add to the list of targets.
110f4a2713aSLionel Sambuc   T.Next = FirstTarget;
111f4a2713aSLionel Sambuc   FirstTarget = &T;
112f4a2713aSLionel Sambuc 
113f4a2713aSLionel Sambuc   T.Name = Name;
114f4a2713aSLionel Sambuc   T.ShortDesc = ShortDesc;
115*0a6a1f1dSLionel Sambuc   T.ArchMatchFn = ArchMatchFn;
116f4a2713aSLionel Sambuc   T.HasJIT = HasJIT;
117f4a2713aSLionel Sambuc }
118f4a2713aSLionel Sambuc 
TargetArraySortFn(const std::pair<StringRef,const Target * > * LHS,const std::pair<StringRef,const Target * > * RHS)119f4a2713aSLionel Sambuc static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS,
120f4a2713aSLionel Sambuc                              const std::pair<StringRef, const Target *> *RHS) {
121f4a2713aSLionel Sambuc   return LHS->first.compare(RHS->first);
122f4a2713aSLionel Sambuc }
123f4a2713aSLionel Sambuc 
printRegisteredTargetsForVersion()124f4a2713aSLionel Sambuc void TargetRegistry::printRegisteredTargetsForVersion() {
125f4a2713aSLionel Sambuc   std::vector<std::pair<StringRef, const Target*> > Targets;
126f4a2713aSLionel Sambuc   size_t Width = 0;
127f4a2713aSLionel Sambuc   for (TargetRegistry::iterator I = TargetRegistry::begin(),
128f4a2713aSLionel Sambuc        E = TargetRegistry::end();
129f4a2713aSLionel Sambuc        I != E; ++I) {
130f4a2713aSLionel Sambuc     Targets.push_back(std::make_pair(I->getName(), &*I));
131f4a2713aSLionel Sambuc     Width = std::max(Width, Targets.back().first.size());
132f4a2713aSLionel Sambuc   }
133f4a2713aSLionel Sambuc   array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn);
134f4a2713aSLionel Sambuc 
135f4a2713aSLionel Sambuc   raw_ostream &OS = outs();
136f4a2713aSLionel Sambuc   OS << "  Registered Targets:\n";
137f4a2713aSLionel Sambuc   for (unsigned i = 0, e = Targets.size(); i != e; ++i) {
138f4a2713aSLionel Sambuc     OS << "    " << Targets[i].first;
139f4a2713aSLionel Sambuc     OS.indent(Width - Targets[i].first.size()) << " - "
140f4a2713aSLionel Sambuc       << Targets[i].second->getShortDescription() << '\n';
141f4a2713aSLionel Sambuc   }
142f4a2713aSLionel Sambuc   if (Targets.empty())
143f4a2713aSLionel Sambuc     OS << "    (none)\n";
144f4a2713aSLionel Sambuc }
145