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