Home | History | Annotate | Download | only in Support
      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 //===----------------------------------------------------------------------===//
     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 
     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 
     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