X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FTargetRegistry.cpp;h=f6918835f74bed5833cfb1edfc3a09c9bd696069;hb=9c23685dd25370a9a255052e44fa609b8ce455c0;hp=258431a9372886b443604815ebfb7335da8b818d;hpb=73b3ec41349511dbf28c18997e3f64761ff0f114;p=oota-llvm.git diff --git a/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp index 258431a9372..f6918835f74 100644 --- a/lib/Support/TargetRegistry.cpp +++ b/lib/Support/TargetRegistry.cpp @@ -7,128 +7,138 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Target/TargetRegistry.h" +#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 +#include using namespace llvm; // Clients are responsible for avoid race conditions in registration. -static Target *FirstTarget = 0; - -const Target * -TargetRegistry::getClosestStaticTargetForTriple(const std::string &TT, - std::string &Error) { - Target *Best = 0, *EquallyBest = 0; - unsigned BestQuality = 0; - // FIXME: Use iterator. - for (Target *i = FirstTarget; i; i = i->Next) { - if (unsigned Qual = i->TripleMatchQualityFn(TT)) { - if (!Best || Qual > BestQuality) { - Best = i; - EquallyBest = 0; - BestQuality = Qual; - } else if (Qual == BestQuality) - EquallyBest = i; - } - } +static Target *FirstTarget = nullptr; - if (!Best) { - Error = "No available targets are compatible with this module"; - 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; +TargetRegistry::iterator TargetRegistry::begin() { + return iterator(FirstTarget); } -const Target * -TargetRegistry::getClosestStaticTargetForModule(const Module &M, - std::string &Error) { - Target *Best = 0, *EquallyBest = 0; - unsigned BestQuality = 0; - // FIXME: Use iterator. - for (Target *i = FirstTarget; i; i = i->Next) { - if (unsigned Qual = i->ModuleMatchQualityFn(M)) { - if (!Best || Qual > BestQuality) { - Best = i; - EquallyBest = 0; - BestQuality = Qual; - } else if (Qual == BestQuality) - EquallyBest = i; +const Target *TargetRegistry::lookupTarget(const std::string &ArchName, + Triple &TheTriple, + std::string &Error) { + // Allocate target machine. First, check whether the user has explicitly + // specified an architecture to compile for. If so we have to look it up by + // name, because it might be a backend that has no mapping to a target triple. + const Target *TheTarget = nullptr; + if (!ArchName.empty()) { + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + if (ArchName == it->getName()) { + TheTarget = &*it; + break; + } } - } - if (!Best) { - Error = "No available targets are compatible with this module"; - return 0; - } + if (!TheTarget) { + Error = "error: invalid target '" + ArchName + "'.\n"; + return nullptr; + } - // 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; + // Adjust the triple to match (if known), otherwise stick with the + // given triple. + Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); + if (Type != Triple::UnknownArch) + TheTriple.setArch(Type); + } else { + // Get the target specific parser. + std::string TempError; + TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError); + if (!TheTarget) { + Error = ": error: unable to get target for '" + + TheTriple.getTriple() + + "', see --version and --triple.\n"; + return nullptr; + } } - return Best; + return TheTarget; } -const Target * -TargetRegistry::getClosestTargetForJIT(std::string &Error) { - Target *Best = 0, *EquallyBest = 0; - unsigned BestQuality = 0; - // FIXME: Use iterator. - for (Target *i = FirstTarget; i; i = i->Next) { - if (unsigned Qual = i->JITMatchQualityFn()) { - if (!Best || Qual > BestQuality) { - Best = i; - EquallyBest = 0; - BestQuality = Qual; - } else if (Qual == BestQuality) - EquallyBest = i; +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 nullptr; + } + const Target *Matching = nullptr; + Triple::ArchType Arch = Triple(TT).getArch(); + for (iterator it = begin(), ie = end(); it != ie; ++it) { + if (it->ArchMatchFn(Arch)) { + if (Matching) { + Error = std::string("Cannot choose between targets \"") + + Matching->Name + "\" and \"" + it->Name + "\""; + return nullptr; + } + Matching = &*it; } } - if (!Best) { - Error = "No JIT is available for this host"; - return 0; + if (!Matching) { + Error = "No available targets are compatible with this triple, " + "see -version for the available targets."; + return nullptr; } - // Return the best, ignoring ties. - return Best; + return Matching; } void TargetRegistry::RegisterTarget(Target &T, const char *Name, const char *ShortDesc, - Target::TripleMatchQualityFnTy TQualityFn, - Target::ModuleMatchQualityFnTy MQualityFn, - Target::JITMatchQualityFnTy JITQualityFn) { - // Note that we don't require the constructor functions already be defined, in - // case a module happens to initialize the optional functionality before the - // target. - assert(!T.Next && !T.Name && !T.ShortDesc && !T.TripleMatchQualityFn && - !T.ModuleMatchQualityFn && !T.JITMatchQualityFn && - "This Target already registered!"); - - assert(Name && ShortDesc && TQualityFn && MQualityFn && JITQualityFn && + Target::ArchMatchFnTy ArchMatchFn, + bool HasJIT) { + assert(Name && ShortDesc && ArchMatchFn && "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.Next; + FirstTarget = &T; T.Name = Name; T.ShortDesc = ShortDesc; - T.TripleMatchQualityFn = TQualityFn; - T.ModuleMatchQualityFn = MQualityFn; - T.JITMatchQualityFn = JITQualityFn; + T.ArchMatchFn = ArchMatchFn; + T.HasJIT = HasJIT; +} + +static int TargetArraySortFn(const std::pair *LHS, + const std::pair *RHS) { + return LHS->first.compare(RHS->first); } +void TargetRegistry::printRegisteredTargetsForVersion() { + std::vector > 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"; +}