summaryrefslogtreecommitdiff
path: root/lib/Support/TargetRegistry.cpp
blob: 77cf2dd72cf3a2720f6bdca715ede3b35480331b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//===--- TargetRegistry.cpp - Target registration -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetRegistry.h"
#include <cassert>
using namespace llvm;

// Clients are responsible for avoid race conditions in registration.
static Target *FirstTarget = 0;

const Target *
TargetRegistry::getClosestStaticTargetForTriple(const std::string &TT,
                                                std::string &Error) {
  Target *Best = 0, *EquallyBest = 0;
  unsigned BestQuality = 0;
  // FIXME: Use iterator.
  for (Target *i = FirstTarget; i; i = i->Next) {
    if (unsigned Qual = i->TripleMatchQualityFn(TT)) {
      if (!Best || Qual > BestQuality) {
        Best = i;
        EquallyBest = 0;
        BestQuality = Qual;
      } else if (Qual == BestQuality)
        EquallyBest = i;
    }
  }

  if (!Best) {
    Error = "No available targets are compatible with this module";
    return 0;
  }

  // Otherwise, take the best target, but make sure we don't have two equally
  // good best targets.
  if (EquallyBest) {
    Error = std::string("Cannot choose between targets \"") +
      Best->Name  + "\" and \"" + EquallyBest->Name + "\"";
    return 0;
  }

  return Best;
}

const Target *
TargetRegistry::getClosestStaticTargetForModule(const Module &M,
                                                std::string &Error) {
  Target *Best = 0, *EquallyBest = 0;
  unsigned BestQuality = 0;
  // FIXME: Use iterator.
  for (Target *i = FirstTarget; i; i = i->Next) {
    if (unsigned Qual = i->ModuleMatchQualityFn(M)) {
      if (!Best || Qual > BestQuality) {
        Best = i;
        EquallyBest = 0;
        BestQuality = Qual;
      } else if (Qual == BestQuality)
        EquallyBest = i;
    }
  }

  if (!Best) {
    Error = "No available targets are compatible with this module";
    return 0;
  }

  // Otherwise, take the best target, but make sure we don't have two equally
  // good best targets.
  if (EquallyBest) {
    Error = std::string("Cannot choose between targets \"") +
      Best->Name  + "\" and \"" + EquallyBest->Name + "\"";
    return 0;
  }

  return Best;
}

const Target *
TargetRegistry::getClosestTargetForJIT(std::string &Error) {
  Target *Best = 0, *EquallyBest = 0;
  unsigned BestQuality = 0;
  // FIXME: Use iterator.
  for (Target *i = FirstTarget; i; i = i->Next) {
    if (unsigned Qual = i->JITMatchQualityFn()) {
      if (!Best || Qual > BestQuality) {
        Best = i;
        EquallyBest = 0;
        BestQuality = Qual;
      } else if (Qual == BestQuality)
        EquallyBest = i;
    }
  }

  if (!Best) {
    Error = "No JIT is available for this host";
    return 0;
  }

  // Return the best, ignoring ties.
  return Best;
}

void TargetRegistry::RegisterTarget(Target &T,
                                    const char *Name,
                                    const char *ShortDesc,
                                    Target::TripleMatchQualityFnTy TQualityFn,
                                    Target::ModuleMatchQualityFnTy MQualityFn,
                                    Target::JITMatchQualityFnTy JITQualityFn) {
  assert(Name && ShortDesc && TQualityFn && MQualityFn && JITQualityFn &&
         "Missing required target information!");

  // Check if this target has already been initialized, we allow this as a
  // convenience to some clients.
  if (T.Name)
    return;
         
  // Add to the list of targets.
  T.Next = FirstTarget;
  FirstTarget = &T;

  T.Name = Name;
  T.ShortDesc = ShortDesc;
  T.TripleMatchQualityFn = TQualityFn;
  T.ModuleMatchQualityFn = MQualityFn;
  T.JITMatchQualityFn = JITQualityFn;
}