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 using 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 {
22 pTarget.Name = pName;
23 pTarget.TripleMatchQualityFn = pQualityFn;
24
25 s_TargetList.push_back(&pTarget);
26 }
27
lookupTarget(const std::string & pTriple,std::string & pError)28 const Target* TargetRegistry::lookupTarget(const std::string &pTriple,
29 std::string &pError)
30 {
31 if (empty()) {
32 pError = "Unable to find target for this triple (no target are registered)";
33 return NULL;
34 }
35
36 llvm::Triple triple(pTriple);
37 Target* best = NULL, *ambiguity = NULL;
38 unsigned int highest = 0;
39
40 for (iterator target = begin(), ie = end(); target != ie; ++target) {
41 unsigned int quality = (*target)->getTripleQuality(triple);
42 if (quality > 0) {
43 if (NULL == best || highest < quality) {
44 highest = quality;
45 best = *target;
46 ambiguity = NULL;
47 }
48 else if (highest == quality) {
49 ambiguity = *target;
50 }
51 }
52 }
53
54 if (NULL == best) {
55 pError = "No availaible targets are compatible with this triple.";
56 return NULL;
57 }
58
59 if (NULL != ambiguity) {
60 pError = std::string("Ambiguous targets: \"") +
61 best->name() + "\" and \"" + ambiguity->name() + "\"";
62 return NULL;
63 }
64
65 return best;
66 }
67
lookupTarget(const std::string & pArchName,llvm::Triple & pTriple,std::string & pError)68 const Target* TargetRegistry::lookupTarget(const std::string& pArchName,
69 llvm::Triple& pTriple,
70 std::string& pError)
71 {
72 const Target* result = NULL;
73 if (!pArchName.empty()) {
74 for (mcld::TargetRegistry::iterator it = mcld::TargetRegistry::begin(),
75 ie = mcld::TargetRegistry::end(); it != ie; ++it) {
76 if (pArchName == (*it)->name()) {
77 result = *it;
78 break;
79 }
80 }
81
82 if (NULL == result) {
83 pError = std::string("invalid target '") + pArchName + "'.\n";
84 return NULL;
85 }
86
87 // Adjust the triple to match (if known), otherwise stick with the
88 // module/host triple.
89 llvm::Triple::ArchType type =
90 llvm::Triple::getArchTypeForLLVMName(pArchName);
91 if (llvm::Triple::UnknownArch != type)
92 pTriple.setArch(type);
93 }
94 else {
95 std::string error;
96 result = lookupTarget(pTriple.getTriple(), error);
97 if (NULL == result) {
98 pError = std::string("unable to get target for `") +
99 pTriple.getTriple() + "'\n" +
100 "(Detail: " + error + ")\n";
101 return NULL;
102 }
103 }
104 return result;
105 }
106