• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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