1349cc55cSDimitry Andric //===--- TargetRegistry.cpp - Target registration -------------------------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric 9349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 10349cc55cSDimitry Andric #include "llvm/ADT/STLExtras.h" 11349cc55cSDimitry Andric #include "llvm/ADT/StringRef.h" 12*0fca6ea1SDimitry Andric #include "llvm/MC/MCAsmBackend.h" 13*0fca6ea1SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 14*0fca6ea1SDimitry Andric #include "llvm/MC/MCContext.h" 15*0fca6ea1SDimitry Andric #include "llvm/MC/MCObjectStreamer.h" 16*0fca6ea1SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 17349cc55cSDimitry Andric #include "llvm/Support/raw_ostream.h" 18349cc55cSDimitry Andric #include <cassert> 19349cc55cSDimitry Andric #include <vector> 20349cc55cSDimitry Andric using namespace llvm; 21349cc55cSDimitry Andric 22349cc55cSDimitry Andric // Clients are responsible for avoid race conditions in registration. 23349cc55cSDimitry Andric static Target *FirstTarget = nullptr; 24349cc55cSDimitry Andric 25*0fca6ea1SDimitry Andric MCStreamer *Target::createMCObjectStreamer( 26*0fca6ea1SDimitry Andric const Triple &T, MCContext &Ctx, std::unique_ptr<MCAsmBackend> TAB, 27*0fca6ea1SDimitry Andric std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, 28*0fca6ea1SDimitry Andric const MCSubtargetInfo &STI) const { 29*0fca6ea1SDimitry Andric MCStreamer *S = nullptr; 30*0fca6ea1SDimitry Andric switch (T.getObjectFormat()) { 31*0fca6ea1SDimitry Andric case Triple::UnknownObjectFormat: 32*0fca6ea1SDimitry Andric llvm_unreachable("Unknown object format"); 33*0fca6ea1SDimitry Andric case Triple::COFF: 34*0fca6ea1SDimitry Andric assert((T.isOSWindows() || T.isUEFI()) && 35*0fca6ea1SDimitry Andric "only Windows and UEFI COFF are supported"); 36*0fca6ea1SDimitry Andric S = COFFStreamerCtorFn(Ctx, std::move(TAB), std::move(OW), 37*0fca6ea1SDimitry Andric std::move(Emitter)); 38*0fca6ea1SDimitry Andric break; 39*0fca6ea1SDimitry Andric case Triple::MachO: 40*0fca6ea1SDimitry Andric if (MachOStreamerCtorFn) 41*0fca6ea1SDimitry Andric S = MachOStreamerCtorFn(Ctx, std::move(TAB), std::move(OW), 42*0fca6ea1SDimitry Andric std::move(Emitter)); 43*0fca6ea1SDimitry Andric else 44*0fca6ea1SDimitry Andric S = createMachOStreamer(Ctx, std::move(TAB), std::move(OW), 45*0fca6ea1SDimitry Andric std::move(Emitter), false); 46*0fca6ea1SDimitry Andric break; 47*0fca6ea1SDimitry Andric case Triple::ELF: 48*0fca6ea1SDimitry Andric if (ELFStreamerCtorFn) 49*0fca6ea1SDimitry Andric S = ELFStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW), 50*0fca6ea1SDimitry Andric std::move(Emitter)); 51*0fca6ea1SDimitry Andric else 52*0fca6ea1SDimitry Andric S = createELFStreamer(Ctx, std::move(TAB), std::move(OW), 53*0fca6ea1SDimitry Andric std::move(Emitter)); 54*0fca6ea1SDimitry Andric break; 55*0fca6ea1SDimitry Andric case Triple::Wasm: 56*0fca6ea1SDimitry Andric S = createWasmStreamer(Ctx, std::move(TAB), std::move(OW), 57*0fca6ea1SDimitry Andric std::move(Emitter)); 58*0fca6ea1SDimitry Andric break; 59*0fca6ea1SDimitry Andric case Triple::GOFF: 60*0fca6ea1SDimitry Andric S = createGOFFStreamer(Ctx, std::move(TAB), std::move(OW), 61*0fca6ea1SDimitry Andric std::move(Emitter)); 62*0fca6ea1SDimitry Andric break; 63*0fca6ea1SDimitry Andric case Triple::XCOFF: 64*0fca6ea1SDimitry Andric S = XCOFFStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW), 65*0fca6ea1SDimitry Andric std::move(Emitter)); 66*0fca6ea1SDimitry Andric break; 67*0fca6ea1SDimitry Andric case Triple::SPIRV: 68*0fca6ea1SDimitry Andric S = createSPIRVStreamer(Ctx, std::move(TAB), std::move(OW), 69*0fca6ea1SDimitry Andric std::move(Emitter)); 70*0fca6ea1SDimitry Andric break; 71*0fca6ea1SDimitry Andric case Triple::DXContainer: 72*0fca6ea1SDimitry Andric S = createDXContainerStreamer(Ctx, std::move(TAB), std::move(OW), 73*0fca6ea1SDimitry Andric std::move(Emitter)); 74*0fca6ea1SDimitry Andric break; 75*0fca6ea1SDimitry Andric } 76*0fca6ea1SDimitry Andric if (ObjectTargetStreamerCtorFn) 77*0fca6ea1SDimitry Andric ObjectTargetStreamerCtorFn(*S, STI); 78*0fca6ea1SDimitry Andric return S; 79*0fca6ea1SDimitry Andric } 80*0fca6ea1SDimitry Andric 81*0fca6ea1SDimitry Andric MCStreamer *Target::createMCObjectStreamer( 82*0fca6ea1SDimitry Andric const Triple &T, MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, 83*0fca6ea1SDimitry Andric std::unique_ptr<MCObjectWriter> &&OW, 84*0fca6ea1SDimitry Andric std::unique_ptr<MCCodeEmitter> &&Emitter, const MCSubtargetInfo &STI, bool, 85*0fca6ea1SDimitry Andric bool, bool) const { 86*0fca6ea1SDimitry Andric return createMCObjectStreamer(T, Ctx, std::move(TAB), std::move(OW), 87*0fca6ea1SDimitry Andric std::move(Emitter), STI); 88*0fca6ea1SDimitry Andric } 89*0fca6ea1SDimitry Andric 90*0fca6ea1SDimitry Andric MCStreamer *Target::createAsmStreamer(MCContext &Ctx, 91*0fca6ea1SDimitry Andric std::unique_ptr<formatted_raw_ostream> OS, 92*0fca6ea1SDimitry Andric MCInstPrinter *IP, 93*0fca6ea1SDimitry Andric std::unique_ptr<MCCodeEmitter> CE, 94*0fca6ea1SDimitry Andric std::unique_ptr<MCAsmBackend> TAB) const { 95*0fca6ea1SDimitry Andric formatted_raw_ostream &OSRef = *OS; 96*0fca6ea1SDimitry Andric MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IP, 97*0fca6ea1SDimitry Andric std::move(CE), std::move(TAB)); 98*0fca6ea1SDimitry Andric createAsmTargetStreamer(*S, OSRef, IP); 99*0fca6ea1SDimitry Andric return S; 100*0fca6ea1SDimitry Andric } 101*0fca6ea1SDimitry Andric 102*0fca6ea1SDimitry Andric MCStreamer *Target::createAsmStreamer(MCContext &Ctx, 103*0fca6ea1SDimitry Andric std::unique_ptr<formatted_raw_ostream> OS, 104*0fca6ea1SDimitry Andric bool IsVerboseAsm, bool UseDwarfDirectory, 105*0fca6ea1SDimitry Andric MCInstPrinter *IP, 106*0fca6ea1SDimitry Andric std::unique_ptr<MCCodeEmitter> &&CE, 107*0fca6ea1SDimitry Andric std::unique_ptr<MCAsmBackend> &&TAB, 108*0fca6ea1SDimitry Andric bool ShowInst) const { 109*0fca6ea1SDimitry Andric return createAsmStreamer(Ctx, std::move(OS), IP, std::move(CE), 110*0fca6ea1SDimitry Andric std::move(TAB)); 111*0fca6ea1SDimitry Andric } 112*0fca6ea1SDimitry Andric 113349cc55cSDimitry Andric iterator_range<TargetRegistry::iterator> TargetRegistry::targets() { 114349cc55cSDimitry Andric return make_range(iterator(FirstTarget), iterator()); 115349cc55cSDimitry Andric } 116349cc55cSDimitry Andric 11706c3fb27SDimitry Andric const Target *TargetRegistry::lookupTarget(StringRef ArchName, 118349cc55cSDimitry Andric Triple &TheTriple, 119349cc55cSDimitry Andric std::string &Error) { 120349cc55cSDimitry Andric // Allocate target machine. First, check whether the user has explicitly 121349cc55cSDimitry Andric // specified an architecture to compile for. If so we have to look it up by 122349cc55cSDimitry Andric // name, because it might be a backend that has no mapping to a target triple. 123349cc55cSDimitry Andric const Target *TheTarget = nullptr; 124349cc55cSDimitry Andric if (!ArchName.empty()) { 125349cc55cSDimitry Andric auto I = find_if(targets(), 126349cc55cSDimitry Andric [&](const Target &T) { return ArchName == T.getName(); }); 127349cc55cSDimitry Andric 128349cc55cSDimitry Andric if (I == targets().end()) { 12906c3fb27SDimitry Andric Error = ("invalid target '" + ArchName + "'.\n").str(); 130349cc55cSDimitry Andric return nullptr; 131349cc55cSDimitry Andric } 132349cc55cSDimitry Andric 133349cc55cSDimitry Andric TheTarget = &*I; 134349cc55cSDimitry Andric 135349cc55cSDimitry Andric // Adjust the triple to match (if known), otherwise stick with the 136349cc55cSDimitry Andric // given triple. 137349cc55cSDimitry Andric Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); 138349cc55cSDimitry Andric if (Type != Triple::UnknownArch) 139349cc55cSDimitry Andric TheTriple.setArch(Type); 140349cc55cSDimitry Andric } else { 141349cc55cSDimitry Andric // Get the target specific parser. 142349cc55cSDimitry Andric std::string TempError; 143349cc55cSDimitry Andric TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError); 144349cc55cSDimitry Andric if (!TheTarget) { 1455f757f3fSDimitry Andric Error = "unable to get target for '" + TheTriple.getTriple() + 1465f757f3fSDimitry Andric "', see --version and --triple."; 147349cc55cSDimitry Andric return nullptr; 148349cc55cSDimitry Andric } 149349cc55cSDimitry Andric } 150349cc55cSDimitry Andric 151349cc55cSDimitry Andric return TheTarget; 152349cc55cSDimitry Andric } 153349cc55cSDimitry Andric 15406c3fb27SDimitry Andric const Target *TargetRegistry::lookupTarget(StringRef TT, std::string &Error) { 155349cc55cSDimitry Andric // Provide special warning when no targets are initialized. 156349cc55cSDimitry Andric if (targets().begin() == targets().end()) { 157349cc55cSDimitry Andric Error = "Unable to find target for this triple (no targets are registered)"; 158349cc55cSDimitry Andric return nullptr; 159349cc55cSDimitry Andric } 160349cc55cSDimitry Andric Triple::ArchType Arch = Triple(TT).getArch(); 161349cc55cSDimitry Andric auto ArchMatch = [&](const Target &T) { return T.ArchMatchFn(Arch); }; 162349cc55cSDimitry Andric auto I = find_if(targets(), ArchMatch); 163349cc55cSDimitry Andric 164349cc55cSDimitry Andric if (I == targets().end()) { 16506c3fb27SDimitry Andric Error = ("No available targets are compatible with triple \"" + TT + "\"") 16606c3fb27SDimitry Andric .str(); 167349cc55cSDimitry Andric return nullptr; 168349cc55cSDimitry Andric } 169349cc55cSDimitry Andric 170349cc55cSDimitry Andric auto J = std::find_if(std::next(I), targets().end(), ArchMatch); 171349cc55cSDimitry Andric if (J != targets().end()) { 172349cc55cSDimitry Andric Error = std::string("Cannot choose between targets \"") + I->Name + 173349cc55cSDimitry Andric "\" and \"" + J->Name + "\""; 174349cc55cSDimitry Andric return nullptr; 175349cc55cSDimitry Andric } 176349cc55cSDimitry Andric 177349cc55cSDimitry Andric return &*I; 178349cc55cSDimitry Andric } 179349cc55cSDimitry Andric 180349cc55cSDimitry Andric void TargetRegistry::RegisterTarget(Target &T, const char *Name, 181349cc55cSDimitry Andric const char *ShortDesc, 182349cc55cSDimitry Andric const char *BackendName, 183349cc55cSDimitry Andric Target::ArchMatchFnTy ArchMatchFn, 184349cc55cSDimitry Andric bool HasJIT) { 185349cc55cSDimitry Andric assert(Name && ShortDesc && ArchMatchFn && 186349cc55cSDimitry Andric "Missing required target information!"); 187349cc55cSDimitry Andric 188349cc55cSDimitry Andric // Check if this target has already been initialized, we allow this as a 189349cc55cSDimitry Andric // convenience to some clients. 190349cc55cSDimitry Andric if (T.Name) 191349cc55cSDimitry Andric return; 192349cc55cSDimitry Andric 193349cc55cSDimitry Andric // Add to the list of targets. 194349cc55cSDimitry Andric T.Next = FirstTarget; 195349cc55cSDimitry Andric FirstTarget = &T; 196349cc55cSDimitry Andric 197349cc55cSDimitry Andric T.Name = Name; 198349cc55cSDimitry Andric T.ShortDesc = ShortDesc; 199349cc55cSDimitry Andric T.BackendName = BackendName; 200349cc55cSDimitry Andric T.ArchMatchFn = ArchMatchFn; 201349cc55cSDimitry Andric T.HasJIT = HasJIT; 202349cc55cSDimitry Andric } 203349cc55cSDimitry Andric 204349cc55cSDimitry Andric static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS, 205349cc55cSDimitry Andric const std::pair<StringRef, const Target *> *RHS) { 206349cc55cSDimitry Andric return LHS->first.compare(RHS->first); 207349cc55cSDimitry Andric } 208349cc55cSDimitry Andric 209349cc55cSDimitry Andric void TargetRegistry::printRegisteredTargetsForVersion(raw_ostream &OS) { 210349cc55cSDimitry Andric std::vector<std::pair<StringRef, const Target*> > Targets; 211349cc55cSDimitry Andric size_t Width = 0; 212349cc55cSDimitry Andric for (const auto &T : TargetRegistry::targets()) { 213349cc55cSDimitry Andric Targets.push_back(std::make_pair(T.getName(), &T)); 214349cc55cSDimitry Andric Width = std::max(Width, Targets.back().first.size()); 215349cc55cSDimitry Andric } 216349cc55cSDimitry Andric array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn); 217349cc55cSDimitry Andric 218bdd1243dSDimitry Andric OS << "\n"; 219349cc55cSDimitry Andric OS << " Registered Targets:\n"; 2200eae32dcSDimitry Andric for (const auto &Target : Targets) { 2210eae32dcSDimitry Andric OS << " " << Target.first; 2220eae32dcSDimitry Andric OS.indent(Width - Target.first.size()) 2230eae32dcSDimitry Andric << " - " << Target.second->getShortDescription() << '\n'; 224349cc55cSDimitry Andric } 225349cc55cSDimitry Andric if (Targets.empty()) 226349cc55cSDimitry Andric OS << " (none)\n"; 227349cc55cSDimitry Andric } 228