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