Coverage Report

Created: 2019-07-24 05:18

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