TargetRegistry.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. #include "llvm/MC/TargetRegistry.h"
  9. #include "llvm/ADT/STLExtras.h"
  10. #include "llvm/ADT/StringRef.h"
  11. #include "llvm/Support/raw_ostream.h"
  12. #include <cassert>
  13. #include <vector>
  14. using namespace llvm;
  15. // Clients are responsible for avoid race conditions in registration.
  16. static Target *FirstTarget = nullptr;
  17. iterator_range<TargetRegistry::iterator> TargetRegistry::targets() {
  18. return make_range(iterator(FirstTarget), iterator());
  19. }
  20. const Target *TargetRegistry::lookupTarget(const std::string &ArchName,
  21. Triple &TheTriple,
  22. std::string &Error) {
  23. // Allocate target machine. First, check whether the user has explicitly
  24. // specified an architecture to compile for. If so we have to look it up by
  25. // name, because it might be a backend that has no mapping to a target triple.
  26. const Target *TheTarget = nullptr;
  27. if (!ArchName.empty()) {
  28. auto I = find_if(targets(),
  29. [&](const Target &T) { return ArchName == T.getName(); });
  30. if (I == targets().end()) {
  31. Error = "invalid target '" + ArchName + "'.\n";
  32. return nullptr;
  33. }
  34. TheTarget = &*I;
  35. // Adjust the triple to match (if known), otherwise stick with the
  36. // given triple.
  37. Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
  38. if (Type != Triple::UnknownArch)
  39. TheTriple.setArch(Type);
  40. } else {
  41. // Get the target specific parser.
  42. std::string TempError;
  43. TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError);
  44. if (!TheTarget) {
  45. Error = "unable to get target for '"
  46. + TheTriple.getTriple()
  47. + "', see --version and --triple.\n";
  48. return nullptr;
  49. }
  50. }
  51. return TheTarget;
  52. }
  53. const Target *TargetRegistry::lookupTarget(const std::string &TT,
  54. std::string &Error) {
  55. // Provide special warning when no targets are initialized.
  56. if (targets().begin() == targets().end()) {
  57. Error = "Unable to find target for this triple (no targets are registered)";
  58. return nullptr;
  59. }
  60. Triple::ArchType Arch = Triple(TT).getArch();
  61. auto ArchMatch = [&](const Target &T) { return T.ArchMatchFn(Arch); };
  62. auto I = find_if(targets(), ArchMatch);
  63. if (I == targets().end()) {
  64. Error = "No available targets are compatible with triple \"" + TT + "\"";
  65. return nullptr;
  66. }
  67. auto J = std::find_if(std::next(I), targets().end(), ArchMatch);
  68. if (J != targets().end()) {
  69. Error = std::string("Cannot choose between targets \"") + I->Name +
  70. "\" and \"" + J->Name + "\"";
  71. return nullptr;
  72. }
  73. return &*I;
  74. }
  75. void TargetRegistry::RegisterTarget(Target &T, const char *Name,
  76. const char *ShortDesc,
  77. const char *BackendName,
  78. Target::ArchMatchFnTy ArchMatchFn,
  79. bool HasJIT) {
  80. assert(Name && ShortDesc && ArchMatchFn &&
  81. "Missing required target information!");
  82. // Check if this target has already been initialized, we allow this as a
  83. // convenience to some clients.
  84. if (T.Name)
  85. return;
  86. // Add to the list of targets.
  87. T.Next = FirstTarget;
  88. FirstTarget = &T;
  89. T.Name = Name;
  90. T.ShortDesc = ShortDesc;
  91. T.BackendName = BackendName;
  92. T.ArchMatchFn = ArchMatchFn;
  93. T.HasJIT = HasJIT;
  94. }
  95. static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS,
  96. const std::pair<StringRef, const Target *> *RHS) {
  97. return LHS->first.compare(RHS->first);
  98. }
  99. void TargetRegistry::printRegisteredTargetsForVersion(raw_ostream &OS) {
  100. std::vector<std::pair<StringRef, const Target*> > Targets;
  101. size_t Width = 0;
  102. for (const auto &T : TargetRegistry::targets()) {
  103. Targets.push_back(std::make_pair(T.getName(), &T));
  104. Width = std::max(Width, Targets.back().first.size());
  105. }
  106. array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn);
  107. OS << "\n";
  108. OS << " Registered Targets:\n";
  109. for (const auto &Target : Targets) {
  110. OS << " " << Target.first;
  111. OS.indent(Width - Target.first.size())
  112. << " - " << Target.second->getShortDescription() << '\n';
  113. }
  114. if (Targets.empty())
  115. OS << " (none)\n";
  116. }