1 //===- TargetRegistry.cpp -------------------------------------------------===//
2 //
3 // The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "mcld/Support/TargetRegistry.h"
10
11 namespace mcld {
12
13 TargetRegistry::TargetListTy mcld::TargetRegistry::s_TargetList;
14
15 //===----------------------------------------------------------------------===//
16 // TargetRegistry
17 //===----------------------------------------------------------------------===//
RegisterTarget(Target & pTarget,const char * pName,Target::TripleMatchQualityFnTy pQualityFn)18 void TargetRegistry::RegisterTarget(Target& pTarget,
19 const char* pName,
20 Target::TripleMatchQualityFnTy pQualityFn) {
21 pTarget.Name = pName;
22 pTarget.TripleMatchQualityFn = pQualityFn;
23
24 s_TargetList.push_back(&pTarget);
25 }
26
lookupTarget(const std::string & pTriple,std::string & pError)27 const Target* TargetRegistry::lookupTarget(const std::string& pTriple,
28 std::string& pError) {
29 if (empty()) {
30 pError = "Unable to find target for this triple (no target are registered)";
31 return NULL;
32 }
33
34 llvm::Triple triple(pTriple);
35 Target* best = NULL, * ambiguity = NULL;
36 unsigned int highest = 0;
37
38 for (iterator target = begin(), ie = end(); target != ie; ++target) {
39 unsigned int quality = (*target)->getTripleQuality(triple);
40 if (quality > 0) {
41 if (best == NULL || highest < quality) {
42 highest = quality;
43 best = *target;
44 ambiguity = NULL;
45 } else if (highest == quality) {
46 ambiguity = *target;
47 }
48 }
49 }
50
51 if (best == NULL) {
52 pError = "No availaible targets are compatible with this triple.";
53 return NULL;
54 }
55
56 if (NULL != ambiguity) {
57 pError = std::string("Ambiguous targets: \"") + best->name() + "\" and \"" +
58 ambiguity->name() + "\"";
59 return NULL;
60 }
61
62 return best;
63 }
64
lookupTarget(const std::string & pArchName,llvm::Triple & pTriple,std::string & pError)65 const Target* TargetRegistry::lookupTarget(const std::string& pArchName,
66 llvm::Triple& pTriple,
67 std::string& pError) {
68 const Target* result = NULL;
69 if (!pArchName.empty()) {
70 for (mcld::TargetRegistry::iterator it = mcld::TargetRegistry::begin(),
71 ie = mcld::TargetRegistry::end();
72 it != ie;
73 ++it) {
74 if (pArchName == (*it)->name()) {
75 result = *it;
76 break;
77 }
78 }
79
80 if (result == NULL) {
81 pError = std::string("invalid target '") + pArchName + "'.\n";
82 return NULL;
83 }
84
85 // Adjust the triple to match (if known), otherwise stick with the
86 // module/host triple.
87 llvm::Triple::ArchType type =
88 llvm::Triple::getArchTypeForLLVMName(pArchName);
89 if (llvm::Triple::UnknownArch != type)
90 pTriple.setArch(type);
91 } else {
92 std::string error;
93 result = lookupTarget(pTriple.getTriple(), error);
94 if (result == NULL) {
95 pError = std::string("unable to get target for `") + pTriple.getTriple() +
96 "'\n" + "(Detail: " + error + ")\n";
97 return NULL;
98 }
99 }
100 return result;
101 }
102
103 } // namespace mcld
104