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