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