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. 20dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic Target *FirstTarget = nullptr; 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. 32dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const Target *TheTarget = nullptr; 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"; 44dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 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); 56dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!TheTarget) { 579ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby Error = ": error: unable to get target for '" 589ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby + TheTriple.getTriple() 599ed9e5d0f994c7721185eba963ea9b907dabcde6Kevin Enderby + "', see --version and --triple.\n"; 60dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 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)"; 72dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 737df0c07dbcd60e2f07220852e60f0f97c80e94d6Daniel Dunbar } 74dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const Target *Matching = nullptr; 7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Triple::ArchType Arch = Triple(TT).getArch(); 76603bea32743dc9914a1d32ae36fc64fe497af801Daniel Dunbar for (iterator it = begin(), ie = end(); it != ie; ++it) { 7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (it->ArchMatchFn(Arch)) { 7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Matching) { 7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Error = std::string("Cannot choose between targets \"") + 8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Matching->Name + "\" and \"" + it->Name + "\""; 81dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Matching = &*it; 84bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar } 85bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar } 86bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!Matching) { 880247656d0aaaee69ab20ff0ad56536bff38b3715Daniel Dunbar Error = "No available targets are compatible with this triple, " 890247656d0aaaee69ab20ff0ad56536bff38b3715Daniel Dunbar "see -version for the available targets."; 90dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 91bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar } 92bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Matching; 94bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar} 95bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 96bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbarvoid TargetRegistry::RegisterTarget(Target &T, 97bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar const char *Name, 98bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar const char *ShortDesc, 9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Target::ArchMatchFnTy ArchMatchFn, 100d6fd377f3333922c4e928019cdfa124ff7f4dd2eDaniel Dunbar bool HasJIT) { 10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(Name && ShortDesc && ArchMatchFn && 102bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar "Missing required target information!"); 10351b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar 10451b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar // Check if this target has already been initialized, we allow this as a 10551b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar // convenience to some clients. 10651b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar if (T.Name) 10751b198af83cb0080c2709b04c129a3d774c07765Daniel Dunbar return; 108bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 109bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar // Add to the list of targets. 110bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar T.Next = FirstTarget; 111f23d4930bdd5ee00354883f8756388573fa43e88Daniel Dunbar FirstTarget = &T; 112bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 113bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar T.Name = Name; 114bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar T.ShortDesc = ShortDesc; 11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines T.ArchMatchFn = ArchMatchFn; 116d6fd377f3333922c4e928019cdfa124ff7f4dd2eDaniel Dunbar T.HasJIT = HasJIT; 117bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar} 118bb061291406b1b9f0c976e9845f69f9faf985606Daniel Dunbar 1190d293e45b66c742fdbc3998209bb20ed6c5806bfBenjamin Kramerstatic int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS, 1200d293e45b66c742fdbc3998209bb20ed6c5806bfBenjamin Kramer const std::pair<StringRef, const Target *> *RHS) { 1210d293e45b66c742fdbc3998209bb20ed6c5806bfBenjamin Kramer return LHS->first.compare(RHS->first); 122077c40871780136f7016a496703b20ebea9c0978Chandler Carruth} 123077c40871780136f7016a496703b20ebea9c0978Chandler Carruth 124077c40871780136f7016a496703b20ebea9c0978Chandler Carruthvoid TargetRegistry::printRegisteredTargetsForVersion() { 125077c40871780136f7016a496703b20ebea9c0978Chandler Carruth std::vector<std::pair<StringRef, const Target*> > Targets; 126077c40871780136f7016a496703b20ebea9c0978Chandler Carruth size_t Width = 0; 127077c40871780136f7016a496703b20ebea9c0978Chandler Carruth for (TargetRegistry::iterator I = TargetRegistry::begin(), 128077c40871780136f7016a496703b20ebea9c0978Chandler Carruth E = TargetRegistry::end(); 129077c40871780136f7016a496703b20ebea9c0978Chandler Carruth I != E; ++I) { 130077c40871780136f7016a496703b20ebea9c0978Chandler Carruth Targets.push_back(std::make_pair(I->getName(), &*I)); 131077c40871780136f7016a496703b20ebea9c0978Chandler Carruth Width = std::max(Width, Targets.back().first.size()); 132077c40871780136f7016a496703b20ebea9c0978Chandler Carruth } 133077c40871780136f7016a496703b20ebea9c0978Chandler Carruth array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn); 134077c40871780136f7016a496703b20ebea9c0978Chandler Carruth 135077c40871780136f7016a496703b20ebea9c0978Chandler Carruth raw_ostream &OS = outs(); 136077c40871780136f7016a496703b20ebea9c0978Chandler Carruth OS << " Registered Targets:\n"; 137077c40871780136f7016a496703b20ebea9c0978Chandler Carruth for (unsigned i = 0, e = Targets.size(); i != e; ++i) { 138077c40871780136f7016a496703b20ebea9c0978Chandler Carruth OS << " " << Targets[i].first; 139077c40871780136f7016a496703b20ebea9c0978Chandler Carruth OS.indent(Width - Targets[i].first.size()) << " - " 140077c40871780136f7016a496703b20ebea9c0978Chandler Carruth << Targets[i].second->getShortDescription() << '\n'; 141077c40871780136f7016a496703b20ebea9c0978Chandler Carruth } 142077c40871780136f7016a496703b20ebea9c0978Chandler Carruth if (Targets.empty()) 143077c40871780136f7016a496703b20ebea9c0978Chandler Carruth OS << " (none)\n"; 144077c40871780136f7016a496703b20ebea9c0978Chandler Carruth} 145