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