| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 1 | //===--- TargetRegistry.cpp - Target registration -------------------------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 |  | 
| Evan Cheng | 2bb4035 | 2011-08-24 18:08:43 +0000 | [diff] [blame] | 10 | #include "llvm/Support/TargetRegistry.h" | 
| Chandler Carruth | 2baac02 | 2011-07-22 07:50:44 +0000 | [diff] [blame] | 11 | #include "llvm/ADT/STLExtras.h" | 
|  | 12 | #include "llvm/ADT/StringRef.h" | 
| Chandler Carruth | 2baac02 | 2011-07-22 07:50:44 +0000 | [diff] [blame] | 13 | #include "llvm/Support/raw_ostream.h" | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 14 | #include <cassert> | 
| Chandler Carruth | 2baac02 | 2011-07-22 07:50:44 +0000 | [diff] [blame] | 15 | #include <vector> | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 16 | using namespace llvm; | 
|  | 17 |  | 
| Daniel Dunbar | 1c66332 | 2009-07-15 07:09:29 +0000 | [diff] [blame] | 18 | // Clients are responsible for avoid race conditions in registration. | 
| Craig Topper | c10719f | 2014-04-07 04:17:22 +0000 | [diff] [blame] | 19 | static Target *FirstTarget = nullptr; | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 20 |  | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 21 | iterator_range<TargetRegistry::iterator> TargetRegistry::targets() { | 
|  | 22 | return make_range(iterator(FirstTarget), iterator()); | 
| Daniel Dunbar | 78c8fb1 | 2009-07-16 02:06:09 +0000 | [diff] [blame] | 23 | } | 
|  | 24 |  | 
| Kevin Enderby | fe3d005 | 2012-05-08 23:38:45 +0000 | [diff] [blame] | 25 | const Target *TargetRegistry::lookupTarget(const std::string &ArchName, | 
|  | 26 | Triple &TheTriple, | 
|  | 27 | std::string &Error) { | 
|  | 28 | // Allocate target machine.  First, check whether the user has explicitly | 
|  | 29 | // specified an architecture to compile for. If so we have to look it up by | 
|  | 30 | // name, because it might be a backend that has no mapping to a target triple. | 
| Craig Topper | c10719f | 2014-04-07 04:17:22 +0000 | [diff] [blame] | 31 | const Target *TheTarget = nullptr; | 
| Kevin Enderby | fe3d005 | 2012-05-08 23:38:45 +0000 | [diff] [blame] | 32 | if (!ArchName.empty()) { | 
| David Majnemer | 562e829 | 2016-08-12 00:18:03 +0000 | [diff] [blame] | 33 | auto I = find_if(targets(), | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 34 | [&](const Target &T) { return ArchName == T.getName(); }); | 
| Kevin Enderby | fe3d005 | 2012-05-08 23:38:45 +0000 | [diff] [blame] | 35 |  | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 36 | if (I == targets().end()) { | 
| Kevin Enderby | fe3d005 | 2012-05-08 23:38:45 +0000 | [diff] [blame] | 37 | Error = "error: invalid target '" + ArchName + "'.\n"; | 
| Craig Topper | c10719f | 2014-04-07 04:17:22 +0000 | [diff] [blame] | 38 | return nullptr; | 
| Kevin Enderby | fe3d005 | 2012-05-08 23:38:45 +0000 | [diff] [blame] | 39 | } | 
|  | 40 |  | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 41 | TheTarget = &*I; | 
|  | 42 |  | 
| Kevin Enderby | fe3d005 | 2012-05-08 23:38:45 +0000 | [diff] [blame] | 43 | // Adjust the triple to match (if known), otherwise stick with the | 
|  | 44 | // given triple. | 
|  | 45 | Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); | 
|  | 46 | if (Type != Triple::UnknownArch) | 
|  | 47 | TheTriple.setArch(Type); | 
|  | 48 | } else { | 
|  | 49 | // Get the target specific parser. | 
|  | 50 | std::string TempError; | 
|  | 51 | TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError); | 
| Craig Topper | 8d399f8 | 2014-04-09 04:20:00 +0000 | [diff] [blame] | 52 | if (!TheTarget) { | 
| Kevin Enderby | fe3d005 | 2012-05-08 23:38:45 +0000 | [diff] [blame] | 53 | Error = ": error: unable to get target for '" | 
|  | 54 | + TheTriple.getTriple() | 
|  | 55 | + "', see --version and --triple.\n"; | 
| Craig Topper | c10719f | 2014-04-07 04:17:22 +0000 | [diff] [blame] | 56 | return nullptr; | 
| Kevin Enderby | fe3d005 | 2012-05-08 23:38:45 +0000 | [diff] [blame] | 57 | } | 
|  | 58 | } | 
|  | 59 |  | 
|  | 60 | return TheTarget; | 
|  | 61 | } | 
|  | 62 |  | 
| Daniel Dunbar | 47d6791 | 2009-07-26 02:12:58 +0000 | [diff] [blame] | 63 | const Target *TargetRegistry::lookupTarget(const std::string &TT, | 
| Daniel Dunbar | 47d6791 | 2009-07-26 02:12:58 +0000 | [diff] [blame] | 64 | std::string &Error) { | 
| Daniel Dunbar | 50745bf | 2009-07-17 15:50:49 +0000 | [diff] [blame] | 65 | // Provide special warning when no targets are initialized. | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 66 | if (targets().begin() == targets().end()) { | 
| Daniel Dunbar | 50745bf | 2009-07-17 15:50:49 +0000 | [diff] [blame] | 67 | Error = "Unable to find target for this triple (no targets are registered)"; | 
| Craig Topper | c10719f | 2014-04-07 04:17:22 +0000 | [diff] [blame] | 68 | return nullptr; | 
| Daniel Dunbar | 50745bf | 2009-07-17 15:50:49 +0000 | [diff] [blame] | 69 | } | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 70 | Triple::ArchType Arch = Triple(TT).getArch(); | 
|  | 71 | auto ArchMatch = [&](const Target &T) { return T.ArchMatchFn(Arch); }; | 
| David Majnemer | 562e829 | 2016-08-12 00:18:03 +0000 | [diff] [blame] | 72 | auto I = find_if(targets(), ArchMatch); | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 73 |  | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 74 | if (I == targets().end()) { | 
| JF Bastien | a1cca51 | 2018-08-23 03:40:31 +0000 | [diff] [blame] | 75 | Error = "No available targets are compatible with triple \"" + TT + "\""; | 
| Craig Topper | c10719f | 2014-04-07 04:17:22 +0000 | [diff] [blame] | 76 | return nullptr; | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 77 | } | 
|  | 78 |  | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 79 | auto J = std::find_if(std::next(I), targets().end(), ArchMatch); | 
|  | 80 | if (J != targets().end()) { | 
| Mehdi Amini | 9af9a9d | 2016-10-01 07:08:23 +0000 | [diff] [blame] | 81 | Error = std::string("Cannot choose between targets \"") + I->Name + | 
|  | 82 | "\" and \"" + J->Name + "\""; | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 83 | return nullptr; | 
|  | 84 | } | 
|  | 85 |  | 
|  | 86 | return &*I; | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 87 | } | 
|  | 88 |  | 
| Daniel Sanders | 725584e | 2017-11-15 23:55:44 +0000 | [diff] [blame] | 89 | void TargetRegistry::RegisterTarget(Target &T, const char *Name, | 
| Mehdi Amini | 9af9a9d | 2016-10-01 07:08:23 +0000 | [diff] [blame] | 90 | const char *ShortDesc, | 
| Daniel Sanders | 725584e | 2017-11-15 23:55:44 +0000 | [diff] [blame] | 91 | const char *BackendName, | 
| Rafael Espindola | dfc1470 | 2013-12-13 16:05:32 +0000 | [diff] [blame] | 92 | Target::ArchMatchFnTy ArchMatchFn, | 
| Daniel Dunbar | 691a478 | 2009-07-25 10:09:50 +0000 | [diff] [blame] | 93 | bool HasJIT) { | 
| Mehdi Amini | 9af9a9d | 2016-10-01 07:08:23 +0000 | [diff] [blame] | 94 | assert(Name && ShortDesc && ArchMatchFn && | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 95 | "Missing required target information!"); | 
| Daniel Dunbar | e833810 | 2009-07-15 20:24:03 +0000 | [diff] [blame] | 96 |  | 
|  | 97 | // Check if this target has already been initialized, we allow this as a | 
|  | 98 | // convenience to some clients. | 
| Mehdi Amini | 9af9a9d | 2016-10-01 07:08:23 +0000 | [diff] [blame] | 99 | if (T.Name) | 
| Daniel Dunbar | e833810 | 2009-07-15 20:24:03 +0000 | [diff] [blame] | 100 | return; | 
| Fangrui Song | f78650a | 2018-07-30 19:41:25 +0000 | [diff] [blame] | 101 |  | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 102 | // Add to the list of targets. | 
|  | 103 | T.Next = FirstTarget; | 
| Daniel Dunbar | 54995de | 2009-07-15 07:37:49 +0000 | [diff] [blame] | 104 | FirstTarget = &T; | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 105 |  | 
|  | 106 | T.Name = Name; | 
|  | 107 | T.ShortDesc = ShortDesc; | 
| Daniel Sanders | 725584e | 2017-11-15 23:55:44 +0000 | [diff] [blame] | 108 | T.BackendName = BackendName; | 
| Rafael Espindola | dfc1470 | 2013-12-13 16:05:32 +0000 | [diff] [blame] | 109 | T.ArchMatchFn = ArchMatchFn; | 
| Daniel Dunbar | 691a478 | 2009-07-25 10:09:50 +0000 | [diff] [blame] | 110 | T.HasJIT = HasJIT; | 
| Daniel Dunbar | 078a71e | 2009-07-15 04:24:58 +0000 | [diff] [blame] | 111 | } | 
|  | 112 |  | 
| Benjamin Kramer | adf1ea8 | 2014-03-07 21:52:38 +0000 | [diff] [blame] | 113 | static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS, | 
|  | 114 | const std::pair<StringRef, const Target *> *RHS) { | 
|  | 115 | return LHS->first.compare(RHS->first); | 
|  | 116 | } | 
|  | 117 |  | 
| Dimitry Andric | bc3feaa | 2017-06-06 21:54:04 +0000 | [diff] [blame] | 118 | void TargetRegistry::printRegisteredTargetsForVersion(raw_ostream &OS) { | 
| Chandler Carruth | 2baac02 | 2011-07-22 07:50:44 +0000 | [diff] [blame] | 119 | std::vector<std::pair<StringRef, const Target*> > Targets; | 
|  | 120 | size_t Width = 0; | 
| David Blaikie | 46c561c | 2015-05-11 22:20:48 +0000 | [diff] [blame] | 121 | for (const auto &T : TargetRegistry::targets()) { | 
|  | 122 | Targets.push_back(std::make_pair(T.getName(), &T)); | 
| Chandler Carruth | 2baac02 | 2011-07-22 07:50:44 +0000 | [diff] [blame] | 123 | Width = std::max(Width, Targets.back().first.size()); | 
|  | 124 | } | 
| Benjamin Kramer | adf1ea8 | 2014-03-07 21:52:38 +0000 | [diff] [blame] | 125 | array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn); | 
| Chandler Carruth | 2baac02 | 2011-07-22 07:50:44 +0000 | [diff] [blame] | 126 |  | 
| Chandler Carruth | 2baac02 | 2011-07-22 07:50:44 +0000 | [diff] [blame] | 127 | OS << "  Registered Targets:\n"; | 
|  | 128 | for (unsigned i = 0, e = Targets.size(); i != e; ++i) { | 
|  | 129 | OS << "    " << Targets[i].first; | 
|  | 130 | OS.indent(Width - Targets[i].first.size()) << " - " | 
|  | 131 | << Targets[i].second->getShortDescription() << '\n'; | 
|  | 132 | } | 
|  | 133 | if (Targets.empty()) | 
|  | 134 | OS << "    (none)\n"; | 
|  | 135 | } |