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/MC/MCAsmBackend.h" 13 #include "llvm/MC/MCCodeEmitter.h" 14 #include "llvm/MC/MCContext.h" 15 #include "llvm/MC/MCInstPrinter.h" 16 #include "llvm/MC/MCObjectStreamer.h" 17 #include "llvm/MC/MCObjectWriter.h" 18 #include "llvm/Support/raw_ostream.h" 19 #include <cassert> 20 #include <vector> 21 using namespace llvm; 22 23 // Clients are responsible for avoid race conditions in registration. 24 static Target *FirstTarget = nullptr; 25 26 MCStreamer *Target::createMCObjectStreamer( 27 const Triple &T, MCContext &Ctx, std::unique_ptr<MCAsmBackend> TAB, 28 std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, 29 const MCSubtargetInfo &STI) const { 30 MCStreamer *S = nullptr; 31 switch (T.getObjectFormat()) { 32 case Triple::UnknownObjectFormat: 33 llvm_unreachable("Unknown object format"); 34 case Triple::COFF: 35 assert((T.isOSWindows() || T.isUEFI()) && 36 "only Windows and UEFI COFF are supported"); 37 S = COFFStreamerCtorFn(Ctx, std::move(TAB), std::move(OW), 38 std::move(Emitter)); 39 break; 40 case Triple::MachO: 41 if (MachOStreamerCtorFn) 42 S = MachOStreamerCtorFn(Ctx, std::move(TAB), std::move(OW), 43 std::move(Emitter)); 44 else 45 S = createMachOStreamer(Ctx, std::move(TAB), std::move(OW), 46 std::move(Emitter), false); 47 break; 48 case Triple::ELF: 49 if (ELFStreamerCtorFn) 50 S = ELFStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW), 51 std::move(Emitter)); 52 else 53 S = createELFStreamer(Ctx, std::move(TAB), std::move(OW), 54 std::move(Emitter)); 55 break; 56 case Triple::Wasm: 57 S = createWasmStreamer(Ctx, std::move(TAB), std::move(OW), 58 std::move(Emitter)); 59 break; 60 case Triple::GOFF: 61 S = createGOFFStreamer(Ctx, std::move(TAB), std::move(OW), 62 std::move(Emitter)); 63 break; 64 case Triple::XCOFF: 65 S = XCOFFStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW), 66 std::move(Emitter)); 67 break; 68 case Triple::SPIRV: 69 S = createSPIRVStreamer(Ctx, std::move(TAB), std::move(OW), 70 std::move(Emitter)); 71 break; 72 case Triple::DXContainer: 73 S = createDXContainerStreamer(Ctx, std::move(TAB), std::move(OW), 74 std::move(Emitter)); 75 break; 76 } 77 if (ObjectTargetStreamerCtorFn) 78 ObjectTargetStreamerCtorFn(*S, STI); 79 return S; 80 } 81 82 MCStreamer *Target::createAsmStreamer(MCContext &Ctx, 83 std::unique_ptr<formatted_raw_ostream> OS, 84 std::unique_ptr<MCInstPrinter> IP, 85 std::unique_ptr<MCCodeEmitter> CE, 86 std::unique_ptr<MCAsmBackend> TAB) const { 87 MCInstPrinter *Printer = IP.get(); 88 formatted_raw_ostream &OSRef = *OS; 89 MCStreamer *S; 90 if (AsmStreamerCtorFn) 91 S = AsmStreamerCtorFn(Ctx, std::move(OS), std::move(IP), std::move(CE), 92 std::move(TAB)); 93 else 94 S = llvm::createAsmStreamer(Ctx, std::move(OS), std::move(IP), 95 std::move(CE), std::move(TAB)); 96 97 createAsmTargetStreamer(*S, OSRef, Printer); 98 return S; 99 } 100 101 iterator_range<TargetRegistry::iterator> TargetRegistry::targets() { 102 return make_range(iterator(FirstTarget), iterator()); 103 } 104 105 const Target *TargetRegistry::lookupTarget(StringRef ArchName, 106 Triple &TheTriple, 107 std::string &Error) { 108 // Allocate target machine. First, check whether the user has explicitly 109 // specified an architecture to compile for. If so we have to look it up by 110 // name, because it might be a backend that has no mapping to a target triple. 111 const Target *TheTarget = nullptr; 112 if (!ArchName.empty()) { 113 auto I = find_if(targets(), 114 [&](const Target &T) { return ArchName == T.getName(); }); 115 116 if (I == targets().end()) { 117 Error = ("invalid target '" + ArchName + "'.").str(); 118 return nullptr; 119 } 120 121 TheTarget = &*I; 122 123 // Adjust the triple to match (if known), otherwise stick with the 124 // given triple. 125 Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); 126 if (Type != Triple::UnknownArch) 127 TheTriple.setArch(Type); 128 } else { 129 // Get the target specific parser. 130 std::string TempError; 131 TheTarget = TargetRegistry::lookupTarget(TheTriple, TempError); 132 if (!TheTarget) { 133 Error = "unable to get target for '" + TheTriple.getTriple() + 134 "', see --version and --triple."; 135 return nullptr; 136 } 137 } 138 139 return TheTarget; 140 } 141 142 const Target *TargetRegistry::lookupTarget(const Triple &TT, 143 std::string &Error) { 144 // Provide special warning when no targets are initialized. 145 if (targets().begin() == targets().end()) { 146 Error = "Unable to find target for this triple (no targets are registered)"; 147 return nullptr; 148 } 149 Triple::ArchType Arch = TT.getArch(); 150 auto ArchMatch = [&](const Target &T) { return T.ArchMatchFn(Arch); }; 151 auto I = find_if(targets(), ArchMatch); 152 153 if (I == targets().end()) { 154 Error = 155 "No available targets are compatible with triple \"" + TT.str() + "\""; 156 return nullptr; 157 } 158 159 auto J = std::find_if(std::next(I), targets().end(), ArchMatch); 160 if (J != targets().end()) { 161 Error = std::string("Cannot choose between targets \"") + I->Name + 162 "\" and \"" + J->Name + "\""; 163 return nullptr; 164 } 165 166 return &*I; 167 } 168 169 void TargetRegistry::RegisterTarget(Target &T, const char *Name, 170 const char *ShortDesc, 171 const char *BackendName, 172 Target::ArchMatchFnTy ArchMatchFn, 173 bool HasJIT) { 174 assert(Name && ShortDesc && ArchMatchFn && 175 "Missing required target information!"); 176 177 // Check if this target has already been initialized, we allow this as a 178 // convenience to some clients. 179 if (T.Name) 180 return; 181 182 // Add to the list of targets. 183 T.Next = FirstTarget; 184 FirstTarget = &T; 185 186 T.Name = Name; 187 T.ShortDesc = ShortDesc; 188 T.BackendName = BackendName; 189 T.ArchMatchFn = ArchMatchFn; 190 T.HasJIT = HasJIT; 191 } 192 193 static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS, 194 const std::pair<StringRef, const Target *> *RHS) { 195 return LHS->first.compare(RHS->first); 196 } 197 198 void TargetRegistry::printRegisteredTargetsForVersion(raw_ostream &OS) { 199 std::vector<std::pair<StringRef, const Target*> > Targets; 200 size_t Width = 0; 201 for (const auto &T : TargetRegistry::targets()) { 202 Targets.push_back(std::make_pair(T.getName(), &T)); 203 Width = std::max(Width, Targets.back().first.size()); 204 } 205 array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn); 206 207 OS << "\n"; 208 OS << " Registered Targets:\n"; 209 for (const auto &Target : Targets) { 210 OS << " " << Target.first; 211 OS.indent(Width - Target.first.size()) 212 << " - " << Target.second->getShortDescription() << '\n'; 213 } 214 if (Targets.empty()) 215 OS << " (none)\n"; 216 } 217