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