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