brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.5 KiB · 9263dda Raw
217 lines · cpp
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-exception6//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>21using namespace llvm;22 23// Clients are responsible for avoid race conditions in registration.24static Target *FirstTarget = nullptr;25 26MCStreamer *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    else45      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    else53      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 82MCStreamer *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  else94    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 101iterator_range<TargetRegistry::iterator> TargetRegistry::targets() {102  return make_range(iterator(FirstTarget), iterator());103}104 105const Target *TargetRegistry::lookupTarget(StringRef ArchName,106                                           Triple &TheTriple,107                                           std::string &Error) {108  // Allocate target machine.  First, check whether the user has explicitly109  // specified an architecture to compile for. If so we have to look it up by110  // 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 the124    // 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 142const 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 169void 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 a178  // 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 193static 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 198void 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