1 //===--- TargetRegistry.cpp - Target registration -------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/MC/TargetRegistry.h" 10 #include "llvm/ADT/STLExtras.h" 11 #include "llvm/ADT/StringRef.h" 12 #include "llvm/Support/raw_ostream.h" 13 #include <cassert> 14 #include <vector> 15 using namespace llvm; 16 17 // Clients are responsible for avoid race conditions in registration. 18 static Target *FirstTarget = nullptr; 19 20 iterator_range<TargetRegistry::iterator> TargetRegistry::targets() { 21 return make_range(iterator(FirstTarget), iterator()); 22 } 23 24 const Target *TargetRegistry::lookupTarget(StringRef ArchName, 25 Triple &TheTriple, 26 std::string &Error) { 27 // Allocate target machine. First, check whether the user has explicitly 28 // specified an architecture to compile for. If so we have to look it up by 29 // name, because it might be a backend that has no mapping to a target triple. 30 const Target *TheTarget = nullptr; 31 if (!ArchName.empty()) { 32 auto I = find_if(targets(), 33 [&](const Target &T) { return ArchName == T.getName(); }); 34 35 if (I == targets().end()) { 36 Error = ("invalid target '" + ArchName + "'.\n").str(); 37 return nullptr; 38 } 39 40 TheTarget = &*I; 41 42 // Adjust the triple to match (if known), otherwise stick with the 43 // given triple. 44 Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); 45 if (Type != Triple::UnknownArch) 46 TheTriple.setArch(Type); 47 } else { 48 // Get the target specific parser. 49 std::string TempError; 50 TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError); 51 if (!TheTarget) { 52 Error = "unable to get target for '" + TheTriple.getTriple() + 53 "', see --version and --triple."; 54 return nullptr; 55 } 56 } 57 58 return TheTarget; 59 } 60 61 const Target *TargetRegistry::lookupTarget(StringRef TT, std::string &Error) { 62 // Provide special warning when no targets are initialized. 63 if (targets().begin() == targets().end()) { 64 Error = "Unable to find target for this triple (no targets are registered)"; 65 return nullptr; 66 } 67 Triple::ArchType Arch = Triple(TT).getArch(); 68 auto ArchMatch = [&](const Target &T) { return T.ArchMatchFn(Arch); }; 69 auto I = find_if(targets(), ArchMatch); 70 71 if (I == targets().end()) { 72 Error = ("No available targets are compatible with triple \"" + TT + "\"") 73 .str(); 74 return nullptr; 75 } 76 77 auto J = std::find_if(std::next(I), targets().end(), ArchMatch); 78 if (J != targets().end()) { 79 Error = std::string("Cannot choose between targets \"") + I->Name + 80 "\" and \"" + J->Name + "\""; 81 return nullptr; 82 } 83 84 return &*I; 85 } 86 87 void TargetRegistry::RegisterTarget(Target &T, const char *Name, 88 const char *ShortDesc, 89 const char *BackendName, 90 Target::ArchMatchFnTy ArchMatchFn, 91 bool HasJIT) { 92 assert(Name && ShortDesc && ArchMatchFn && 93 "Missing required target information!"); 94 95 // Check if this target has already been initialized, we allow this as a 96 // convenience to some clients. 97 if (T.Name) 98 return; 99 100 // Add to the list of targets. 101 T.Next = FirstTarget; 102 FirstTarget = &T; 103 104 T.Name = Name; 105 T.ShortDesc = ShortDesc; 106 T.BackendName = BackendName; 107 T.ArchMatchFn = ArchMatchFn; 108 T.HasJIT = HasJIT; 109 } 110 111 static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS, 112 const std::pair<StringRef, const Target *> *RHS) { 113 return LHS->first.compare(RHS->first); 114 } 115 116 void TargetRegistry::printRegisteredTargetsForVersion(raw_ostream &OS) { 117 std::vector<std::pair<StringRef, const Target*> > Targets; 118 size_t Width = 0; 119 for (const auto &T : TargetRegistry::targets()) { 120 Targets.push_back(std::make_pair(T.getName(), &T)); 121 Width = std::max(Width, Targets.back().first.size()); 122 } 123 array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn); 124 125 OS << "\n"; 126 OS << " Registered Targets:\n"; 127 for (const auto &Target : Targets) { 128 OS << " " << Target.first; 129 OS.indent(Width - Target.first.size()) 130 << " - " << Target.second->getShortDescription() << '\n'; 131 } 132 if (Targets.empty()) 133 OS << " (none)\n"; 134 } 135