TargetRegistry.cpp 4.7 KB

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