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