| //===--- TargetRegistry.cpp - Target registration -------------------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Support/TargetRegistry.h" | |
| #include "llvm/ADT/STLExtras.h" | |
| #include "llvm/ADT/StringRef.h" | |
| #include "llvm/Support/Host.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include <cassert> | |
| #include <vector> | |
| using namespace llvm; | |
| // Clients are responsible for avoid race conditions in registration. | |
| static Target *FirstTarget = 0; | |
| TargetRegistry::iterator TargetRegistry::begin() { | |
| return iterator(FirstTarget); | |
| } | |
| const Target *TargetRegistry::lookupTarget(const std::string &TT, | |
| std::string &Error) { | |
| // Provide special warning when no targets are initialized. | |
| if (begin() == end()) { | |
| Error = "Unable to find target for this triple (no targets are registered)"; | |
| return 0; | |
| } | |
| const Target *Best = 0, *EquallyBest = 0; | |
| unsigned BestQuality = 0; | |
| for (iterator it = begin(), ie = end(); it != ie; ++it) { | |
| if (unsigned Qual = it->TripleMatchQualityFn(TT)) { | |
| if (!Best || Qual > BestQuality) { | |
| Best = &*it; | |
| EquallyBest = 0; | |
| BestQuality = Qual; | |
| } else if (Qual == BestQuality) | |
| EquallyBest = &*it; | |
| } | |
| } | |
| if (!Best) { | |
| Error = "No available targets are compatible with this triple, " | |
| "see -version for the available targets."; | |
| return 0; | |
| } | |
| // Otherwise, take the best target, but make sure we don't have two equally | |
| // good best targets. | |
| if (EquallyBest) { | |
| Error = std::string("Cannot choose between targets \"") + | |
| Best->Name + "\" and \"" + EquallyBest->Name + "\""; | |
| return 0; | |
| } | |
| return Best; | |
| } | |
| void TargetRegistry::RegisterTarget(Target &T, | |
| const char *Name, | |
| const char *ShortDesc, | |
| Target::TripleMatchQualityFnTy TQualityFn, | |
| bool HasJIT) { | |
| assert(Name && ShortDesc && TQualityFn && | |
| "Missing required target information!"); | |
| // Check if this target has already been initialized, we allow this as a | |
| // convenience to some clients. | |
| if (T.Name) | |
| return; | |
| // Add to the list of targets. | |
| T.Next = FirstTarget; | |
| FirstTarget = &T; | |
| T.Name = Name; | |
| T.ShortDesc = ShortDesc; | |
| T.TripleMatchQualityFn = TQualityFn; | |
| T.HasJIT = HasJIT; | |
| } | |
| const Target *TargetRegistry::getClosestTargetForJIT(std::string &Error) { | |
| const Target *TheTarget = lookupTarget(sys::getHostTriple(), Error); | |
| if (TheTarget && !TheTarget->hasJIT()) { | |
| Error = "No JIT compatible target available for this host"; | |
| return 0; | |
| } | |
| return TheTarget; | |
| } | |
| static int TargetArraySortFn(const void *LHS, const void *RHS) { | |
| typedef std::pair<StringRef, const Target*> pair_ty; | |
| return ((const pair_ty*)LHS)->first.compare(((const pair_ty*)RHS)->first); | |
| } | |
| void TargetRegistry::printRegisteredTargetsForVersion() { | |
| std::vector<std::pair<StringRef, const Target*> > Targets; | |
| size_t Width = 0; | |
| for (TargetRegistry::iterator I = TargetRegistry::begin(), | |
| E = TargetRegistry::end(); | |
| I != E; ++I) { | |
| Targets.push_back(std::make_pair(I->getName(), &*I)); | |
| Width = std::max(Width, Targets.back().first.size()); | |
| } | |
| array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn); | |
| raw_ostream &OS = outs(); | |
| OS << " Registered Targets:\n"; | |
| for (unsigned i = 0, e = Targets.size(); i != e; ++i) { | |
| OS << " " << Targets[i].first; | |
| OS.indent(Width - Targets[i].first.size()) << " - " | |
| << Targets[i].second->getShortDescription() << '\n'; | |
| } | |
| if (Targets.empty()) | |
| OS << " (none)\n"; | |
| } |