LLVM API Documentation

TargetRegistry.cpp
Go to the documentation of this file.
00001 //===--- TargetRegistry.cpp - Target registration -------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "llvm/Support/TargetRegistry.h"
00011 #include "llvm/ADT/STLExtras.h"
00012 #include "llvm/ADT/StringRef.h"
00013 #include "llvm/Support/Host.h"
00014 #include "llvm/Support/raw_ostream.h"
00015 #include <cassert>
00016 #include <vector>
00017 using namespace llvm;
00018 
00019 // Clients are responsible for avoid race conditions in registration.
00020 static Target *FirstTarget = nullptr;
00021 
00022 TargetRegistry::iterator TargetRegistry::begin() {
00023   return iterator(FirstTarget);
00024 }
00025 
00026 const Target *TargetRegistry::lookupTarget(const std::string &ArchName,
00027                                            Triple &TheTriple,
00028                                            std::string &Error) {
00029   // Allocate target machine.  First, check whether the user has explicitly
00030   // specified an architecture to compile for. If so we have to look it up by
00031   // name, because it might be a backend that has no mapping to a target triple.
00032   const Target *TheTarget = nullptr;
00033   if (!ArchName.empty()) {
00034     for (TargetRegistry::iterator it = TargetRegistry::begin(),
00035            ie = TargetRegistry::end(); it != ie; ++it) {
00036       if (ArchName == it->getName()) {
00037         TheTarget = &*it;
00038         break;
00039       }
00040     }
00041 
00042     if (!TheTarget) {
00043       Error = "error: invalid target '" + ArchName + "'.\n";
00044       return nullptr;
00045     }
00046 
00047     // Adjust the triple to match (if known), otherwise stick with the
00048     // given triple.
00049     Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
00050     if (Type != Triple::UnknownArch)
00051       TheTriple.setArch(Type);
00052   } else {
00053     // Get the target specific parser.
00054     std::string TempError;
00055     TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError);
00056     if (!TheTarget) {
00057       Error = ": error: unable to get target for '"
00058             + TheTriple.getTriple()
00059             + "', see --version and --triple.\n";
00060       return nullptr;
00061     }
00062   }
00063 
00064   return TheTarget;
00065 }
00066 
00067 const Target *TargetRegistry::lookupTarget(const std::string &TT,
00068                                            std::string &Error) {
00069   // Provide special warning when no targets are initialized.
00070   if (begin() == end()) {
00071     Error = "Unable to find target for this triple (no targets are registered)";
00072     return nullptr;
00073   }
00074   const Target *Matching = nullptr;
00075   Triple::ArchType Arch =  Triple(TT).getArch();
00076   for (iterator it = begin(), ie = end(); it != ie; ++it) {
00077     if (it->ArchMatchFn(Arch)) {
00078       if (Matching) {
00079         Error = std::string("Cannot choose between targets \"") +
00080           Matching->Name  + "\" and \"" + it->Name + "\"";
00081         return nullptr;
00082       }
00083       Matching = &*it;
00084     }
00085   }
00086 
00087   if (!Matching) {
00088     Error = "No available targets are compatible with this triple, "
00089       "see -version for the available targets.";
00090     return nullptr;
00091   }
00092 
00093   return Matching;
00094 }
00095 
00096 void TargetRegistry::RegisterTarget(Target &T,
00097                                     const char *Name,
00098                                     const char *ShortDesc,
00099                                     Target::ArchMatchFnTy ArchMatchFn,
00100                                     bool HasJIT) {
00101   assert(Name && ShortDesc && ArchMatchFn &&
00102          "Missing required target information!");
00103 
00104   // Check if this target has already been initialized, we allow this as a
00105   // convenience to some clients.
00106   if (T.Name)
00107     return;
00108          
00109   // Add to the list of targets.
00110   T.Next = FirstTarget;
00111   FirstTarget = &T;
00112 
00113   T.Name = Name;
00114   T.ShortDesc = ShortDesc;
00115   T.ArchMatchFn = ArchMatchFn;
00116   T.HasJIT = HasJIT;
00117 }
00118 
00119 static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS,
00120                              const std::pair<StringRef, const Target *> *RHS) {
00121   return LHS->first.compare(RHS->first);
00122 }
00123 
00124 void TargetRegistry::printRegisteredTargetsForVersion() {
00125   std::vector<std::pair<StringRef, const Target*> > Targets;
00126   size_t Width = 0;
00127   for (TargetRegistry::iterator I = TargetRegistry::begin(),
00128        E = TargetRegistry::end();
00129        I != E; ++I) {
00130     Targets.push_back(std::make_pair(I->getName(), &*I));
00131     Width = std::max(Width, Targets.back().first.size());
00132   }
00133   array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn);
00134 
00135   raw_ostream &OS = outs();
00136   OS << "  Registered Targets:\n";
00137   for (unsigned i = 0, e = Targets.size(); i != e; ++i) {
00138     OS << "    " << Targets[i].first;
00139     OS.indent(Width - Targets[i].first.size()) << " - "
00140       << Targets[i].second->getShortDescription() << '\n';
00141   }
00142   if (Targets.empty())
00143     OS << "    (none)\n";
00144 }