15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- TargetRegistry.cpp -------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
9affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/TargetRegistry.h>
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesusing namespace mcld;
125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesTargetRegistry::TargetListTy mcld::TargetRegistry::s_TargetList;
145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
15f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
16f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// TargetRegistry
17f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
18f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesvoid TargetRegistry::RegisterTarget(Target& pTarget,
19f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                    const char* pName,
20f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                    Target::TripleMatchQualityFnTy pQualityFn)
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
22f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pTarget.Name = pName;
23f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pTarget.TripleMatchQualityFn = pQualityFn;
24f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
25f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  s_TargetList.push_back(&pTarget);
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
28f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesconst Target* TargetRegistry::lookupTarget(const std::string &pTriple,
29f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                           std::string &pError)
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
31f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (empty()) {
32f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pError = "Unable to find target for this triple (no target are registered)";
33f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return NULL;
34f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
35f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
36f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::Triple triple(pTriple);
37f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  Target* best = NULL, *ambiguity = NULL;
38f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  unsigned int highest = 0;
39f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
40f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (iterator target = begin(), ie = end(); target != ie; ++target) {
41f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    unsigned int quality = (*target)->getTripleQuality(triple);
42f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (quality > 0) {
43f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (NULL == best || highest < quality) {
44f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        highest = quality;
45f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        best = *target;
46f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        ambiguity = NULL;
47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
48f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      else if (highest == quality) {
49f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        ambiguity = *target;
50f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
54f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (NULL == best) {
55f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pError = "No availaible targets are compatible with this triple.";
56f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return NULL;
57f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
58f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
59f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (NULL != ambiguity) {
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pError = std::string("Ambiguous targets: \"") +
61f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines             best->name() + "\" and \"" + ambiguity->name() + "\"";
62d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return NULL;
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
64d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return best;
665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesconst Target* TargetRegistry::lookupTarget(const std::string& pArchName,
69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                           llvm::Triple& pTriple,
70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                           std::string& pError)
71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines{
72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const Target* result = NULL;
73f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (!pArchName.empty()) {
74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    for (mcld::TargetRegistry::iterator it = mcld::TargetRegistry::begin(),
75f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines           ie = mcld::TargetRegistry::end(); it != ie; ++it) {
76f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (pArchName == (*it)->name()) {
77f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        result = *it;
78f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
79f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
80f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
81f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
82f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (NULL == result) {
83f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pError = std::string("invalid target '") + pArchName + "'.\n";
84f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return NULL;
85f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
86f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
87f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // Adjust the triple to match (if known), otherwise stick with the
88f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // module/host triple.
89f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    llvm::Triple::ArchType type =
90f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                               llvm::Triple::getArchTypeForLLVMName(pArchName);
91f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (llvm::Triple::UnknownArch != type)
92f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pTriple.setArch(type);
93f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
94f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  else {
95f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    std::string error;
96f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    result = lookupTarget(pTriple.getTriple(), error);
97f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (NULL == result) {
98f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pError = std::string("unable to get target for `") +
99f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines               pTriple.getTriple() + "'\n" +
100f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines               "(Detail: " + error + ")\n";
101f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return NULL;
102f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
103f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
104f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return result;
105f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
106