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 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   pTarget.Name = pName;
     22   pTarget.TripleMatchQualityFn = pQualityFn;
     23 
     24   s_TargetList.push_back(&pTarget);
     25 }
     26 
     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 
     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