1bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar//===--- TargetRegistry.cpp - Target registration -------------------------===// 2bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar// 3bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar// The LLVM Compiler Infrastructure 4bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar// 5bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar// This file is distributed under the University of Illinois Open Source 6bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar// License. See LICENSE.TXT for details. 7bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar// 8bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar//===----------------------------------------------------------------------===// 9bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 103e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h" 11077c40871780136f7016a496703b20ebea9c0978Chandler Carruth#include "llvm/ADT/STLExtras.h" 12077c40871780136f7016a496703b20ebea9c0978Chandler Carruth#include "llvm/ADT/StringRef.h" 131f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Host.h" 14077c40871780136f7016a496703b20ebea9c0978Chandler Carruth#include "llvm/Support/raw_ostream.h" 15bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar#include <cassert> 16077c40871780136f7016a496703b20ebea9c0978Chandler Carruth#include <vector> 17bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbarusing namespace llvm; 18bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 1973b3ec41349511dbf28c18997e3f64761ff0f114Daniel Dunbar// Clients are responsible for avoid race conditions in registration. 20bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbarstatic Target *FirstTarget = 0; 21bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 22603bea32743dc9914a1d32ae36fc64fe497af801Daniel DunbarTargetRegistry::iterator TargetRegistry::begin() { 23603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar return iterator(FirstTarget); 24603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar} 25603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar 269ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderbyconst Target *TargetRegistry::lookupTarget(const std::string &ArchName, 279ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby Triple &TheTriple, 289ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby std::string &Error) { 299ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby // Allocate target machine. First, check whether the user has explicitly 309ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby // specified an architecture to compile for. If so we have to look it up by 319ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby // name, because it might be a backend that has no mapping to a target triple. 329ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby const Target *TheTarget = 0; 339ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby if (!ArchName.empty()) { 349ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby for (TargetRegistry::iterator it = TargetRegistry::begin(), 359ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby ie = TargetRegistry::end(); it != ie; ++it) { 369ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby if (ArchName == it->getName()) { 379ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby TheTarget = &*it; 389ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby break; 399ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby } 409ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby } 419ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby 429ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby if (!TheTarget) { 439ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby Error = "error: invalid target '" + ArchName + "'.\n"; 449ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby return 0; 459ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby } 469ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby 479ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby // Adjust the triple to match (if known), otherwise stick with the 489ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby // given triple. 499ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); 509ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby if (Type != Triple::UnknownArch) 519ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby TheTriple.setArch(Type); 529ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby } else { 539ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby // Get the target specific parser. 549ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby std::string TempError; 559ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError); 569ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby if (TheTarget == 0) { 579ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby Error = ": error: unable to get target for '" 589ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby + TheTriple.getTriple() 599ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby + "', see --version and --triple.\n"; 609ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby return 0; 619ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby } 629ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby } 639ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby 649ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby return TheTarget; 659ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby} 669ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby 67a5881e3060aee9f82aef3747a97650e5eafe893aDaniel Dunbarconst Target *TargetRegistry::lookupTarget(const std::string &TT, 68a5881e3060aee9f82aef3747a97650e5eafe893aDaniel Dunbar std::string &Error) { 697df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar // Provide special warning when no targets are initialized. 707df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar if (begin() == end()) { 717df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar Error = "Unable to find target for this triple (no targets are registered)"; 727df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar return 0; 737df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar } 74603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar const Target *Best = 0, *EquallyBest = 0; 75bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar unsigned BestQuality = 0; 76603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar for (iterator it = begin(), ie = end(); it != ie; ++it) { 77a5881e3060aee9f82aef3747a97650e5eafe893aDaniel Dunbar if (unsigned Qual = it->TripleMatchQualityFn(TT)) { 78bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar if (!Best || Qual > BestQuality) { 79603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar Best = &*it; 80bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar EquallyBest = 0; 81bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar BestQuality = Qual; 82bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar } else if (Qual == BestQuality) 83603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar EquallyBest = &*it; 84bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar } 85bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar } 86bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 87bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar if (!Best) { 880247656d0aaaee69ab20ff0ad56536bff38b3715Daniel Dunbar Error = "No available targets are compatible with this triple, " 890247656d0aaaee69ab20ff0ad56536bff38b3715Daniel Dunbar "see -version for the available targets."; 90a5881e3060aee9f82aef3747a97650e5eafe893aDaniel Dunbar return 0; 91bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar } 92bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 93bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar // Otherwise, take the best target, but make sure we don't have two equally 94bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar // good best targets. 95bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar if (EquallyBest) { 96bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar Error = std::string("Cannot choose between targets \"") + 97bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar Best->Name + "\" and \"" + EquallyBest->Name + "\""; 98bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar return 0; 99bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar } 100bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 101bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar return Best; 102bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar} 103bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 104bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbarvoid TargetRegistry::RegisterTarget(Target &T, 105bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar const char *Name, 106bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar const char *ShortDesc, 107bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar Target::TripleMatchQualityFnTy TQualityFn, 108d6fd377f3333922c4e928019cdfa124ff7f4dd2eDaniel Dunbar bool HasJIT) { 109fa27ff296d3694a68e7abb3b6b7629588def3e58Daniel Dunbar assert(Name && ShortDesc && TQualityFn && 110bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar "Missing required target information!"); 11151b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar 11251b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar // Check if this target has already been initialized, we allow this as a 11351b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar // convenience to some clients. 11451b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar if (T.Name) 11551b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar return; 116bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 117bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar // Add to the list of targets. 118bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar T.Next = FirstTarget; 119f23d4930bdd5ee00354883f8756388573fa43e88Daniel Dunbar FirstTarget = &T; 120bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 121bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar T.Name = Name; 122bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar T.ShortDesc = ShortDesc; 123bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar T.TripleMatchQualityFn = TQualityFn; 124d6fd377f3333922c4e928019cdfa124ff7f4dd2eDaniel Dunbar T.HasJIT = HasJIT; 125bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar} 126bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 1274bd03abe593222b26e84066223feb321bf738625Daniel Dunbarconst Target *TargetRegistry::getClosestTargetForJIT(std::string &Error) { 1286e9b5eb51bb623995c90295d265a7682277653a1Sebastian Pop const Target *TheTarget = lookupTarget(sys::getDefaultTargetTriple(), Error); 1294bd03abe593222b26e84066223feb321bf738625Daniel Dunbar 1304bd03abe593222b26e84066223feb321bf738625Daniel Dunbar if (TheTarget && !TheTarget->hasJIT()) { 1314bd03abe593222b26e84066223feb321bf738625Daniel Dunbar Error = "No JIT compatible target available for this host"; 1324bd03abe593222b26e84066223feb321bf738625Daniel Dunbar return 0; 1334bd03abe593222b26e84066223feb321bf738625Daniel Dunbar } 1344bd03abe593222b26e84066223feb321bf738625Daniel Dunbar 1354bd03abe593222b26e84066223feb321bf738625Daniel Dunbar return TheTarget; 1364bd03abe593222b26e84066223feb321bf738625Daniel Dunbar} 1374bd03abe593222b26e84066223feb321bf738625Daniel Dunbar 138077c40871780136f7016a496703b20ebea9c0978Chandler Carruthstatic int TargetArraySortFn(const void *LHS, const void *RHS) { 139077c40871780136f7016a496703b20ebea9c0978Chandler Carruth typedef std::pair<StringRef, const Target*> pair_ty; 140077c40871780136f7016a496703b20ebea9c0978Chandler Carruth return ((const pair_ty*)LHS)->first.compare(((const pair_ty*)RHS)->first); 141077c40871780136f7016a496703b20ebea9c0978Chandler Carruth} 142077c40871780136f7016a496703b20ebea9c0978Chandler Carruth 143077c40871780136f7016a496703b20ebea9c0978Chandler Carruthvoid TargetRegistry::printRegisteredTargetsForVersion() { 144077c40871780136f7016a496703b20ebea9c0978Chandler Carruth std::vector<std::pair<StringRef, const Target*> > Targets; 145077c40871780136f7016a496703b20ebea9c0978Chandler Carruth size_t Width = 0; 146077c40871780136f7016a496703b20ebea9c0978Chandler Carruth for (TargetRegistry::iterator I = TargetRegistry::begin(), 147077c40871780136f7016a496703b20ebea9c0978Chandler Carruth E = TargetRegistry::end(); 148077c40871780136f7016a496703b20ebea9c0978Chandler Carruth I != E; ++I) { 149077c40871780136f7016a496703b20ebea9c0978Chandler Carruth Targets.push_back(std::make_pair(I->getName(), &*I)); 150077c40871780136f7016a496703b20ebea9c0978Chandler Carruth Width = std::max(Width, Targets.back().first.size()); 151077c40871780136f7016a496703b20ebea9c0978Chandler Carruth } 152077c40871780136f7016a496703b20ebea9c0978Chandler Carruth array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn); 153077c40871780136f7016a496703b20ebea9c0978Chandler Carruth 154077c40871780136f7016a496703b20ebea9c0978Chandler Carruth raw_ostream &OS = outs(); 155077c40871780136f7016a496703b20ebea9c0978Chandler Carruth OS << " Registered Targets:\n"; 156077c40871780136f7016a496703b20ebea9c0978Chandler Carruth for (unsigned i = 0, e = Targets.size(); i != e; ++i) { 157077c40871780136f7016a496703b20ebea9c0978Chandler Carruth OS << " " << Targets[i].first; 158077c40871780136f7016a496703b20ebea9c0978Chandler Carruth OS.indent(Width - Targets[i].first.size()) << " - " 159077c40871780136f7016a496703b20ebea9c0978Chandler Carruth << Targets[i].second->getShortDescription() << '\n'; 160077c40871780136f7016a496703b20ebea9c0978Chandler Carruth } 161077c40871780136f7016a496703b20ebea9c0978Chandler Carruth if (Targets.empty()) 162077c40871780136f7016a496703b20ebea9c0978Chandler Carruth OS << " (none)\n"; 163077c40871780136f7016a496703b20ebea9c0978Chandler Carruth} 164