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//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/TargetRegistry.h"
105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace 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,
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    Target::TripleMatchQualityFnTy pQualityFn) {
21f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pTarget.Name = pName;
22f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pTarget.TripleMatchQualityFn = pQualityFn;
23f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
24f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  s_TargetList.push_back(&pTarget);
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst Target* TargetRegistry::lookupTarget(const std::string& pTriple,
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                           std::string& pError) {
29f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (empty()) {
30f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pError = "Unable to find target for this triple (no target are registered)";
31f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return NULL;
32f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
33f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
34f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::Triple triple(pTriple);
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Target* best = NULL, * ambiguity = NULL;
36f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  unsigned int highest = 0;
37f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
38f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (iterator target = begin(), ie = end(); target != ie; ++target) {
39f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    unsigned int quality = (*target)->getTripleQuality(triple);
40f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (quality > 0) {
4137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (best == NULL || highest < quality) {
42f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        highest = quality;
43f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        best = *target;
44f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        ambiguity = NULL;
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      } else if (highest == quality) {
46f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        ambiguity = *target;
47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (best == NULL) {
52f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pError = "No availaible targets are compatible with this triple.";
53f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return NULL;
54f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
55f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
56f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (NULL != ambiguity) {
5737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    pError = std::string("Ambiguous targets: \"") + best->name() + "\" and \"" +
5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines             ambiguity->name() + "\"";
59d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return NULL;
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
61d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
62f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return best;
635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesconst Target* TargetRegistry::lookupTarget(const std::string& pArchName,
66f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                           llvm::Triple& pTriple,
6737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                           std::string& pError) {
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const Target* result = NULL;
69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (!pArchName.empty()) {
70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    for (mcld::TargetRegistry::iterator it = mcld::TargetRegistry::begin(),
7137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                        ie = mcld::TargetRegistry::end();
7237b74a387bb3993387029859c2d9d051c41c724eStephen Hines         it != ie;
7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines         ++it) {
74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (pArchName == (*it)->name()) {
75f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        result = *it;
76f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
77f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
78f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
79f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (result == NULL) {
81f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pError = std::string("invalid target '") + pArchName + "'.\n";
82f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return NULL;
83f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
84f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
85f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // Adjust the triple to match (if known), otherwise stick with the
86f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // module/host triple.
87f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    llvm::Triple::ArchType type =
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        llvm::Triple::getArchTypeForLLVMName(pArchName);
89f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (llvm::Triple::UnknownArch != type)
90f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pTriple.setArch(type);
9137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
92f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    std::string error;
93f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    result = lookupTarget(pTriple.getTriple(), error);
9437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (result == NULL) {
9537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pError = std::string("unable to get target for `") + pTriple.getTriple() +
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines               "'\n" + "(Detail: " + error + ")\n";
97f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return NULL;
98f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
99f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
100f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return result;
101f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
10237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
10337b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
104