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