TargetInfo.cpp revision 927686fe8c968ca786fa44d2353eebf59c4f5b8a
1//===--- TargetInfo.cpp - Information about Target machine ----------------===//
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//
10//  This file implements the TargetInfo and TargetInfoImpl interfaces.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Basic/TargetInfo.h"
15#include "clang/Basic/Diagnostic.h"
16#include "clang/AST/Builtins.h"
17#include "llvm/ADT/APFloat.h"
18#include "llvm/ADT/STLExtras.h"
19#include <cstdlib>
20using namespace clang;
21
22// TargetInfo Constructor.
23TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
24  // Set defaults.  These should be overridden by concrete targets as needed.
25  CharIsSigned = true;
26  PointerWidth = PointerAlign = 32;
27  WCharWidth = WCharAlign = 32;
28  IntWidth = IntAlign = 32;
29  LongWidth = LongAlign = 32;
30  LongLongWidth = LongLongAlign = 64;
31  DoubleWidth = 64;
32  DoubleAlign = 32;
33  FloatFormat = &llvm::APFloat::IEEEsingle;
34  DoubleFormat = &llvm::APFloat::IEEEdouble;
35  LongDoubleFormat = &llvm::APFloat::IEEEdouble;
36}
37
38// Out of line virtual dtor for TargetInfo.
39TargetInfo::~TargetInfo() {}
40
41//===----------------------------------------------------------------------===//
42
43
44static void removeGCCRegisterPrefix(const char *&Name) {
45  if (Name[0] == '%' || Name[0] == '#')
46    Name++;
47}
48
49/// isValidGCCRegisterName - Returns whether the passed in string
50/// is a valid register name according to GCC. This is used by Sema for
51/// inline asm statements.
52bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
53  const char * const *Names;
54  unsigned NumNames;
55
56  // Get rid of any register prefix.
57  removeGCCRegisterPrefix(Name);
58
59
60  if (strcmp(Name, "memory") == 0 ||
61      strcmp(Name, "cc") == 0)
62    return true;
63
64  getGCCRegNames(Names, NumNames);
65
66  // If we have a number it maps to an entry in the register name array.
67  if (isdigit(Name[0])) {
68    char *End;
69    int n = (int)strtol(Name, &End, 0);
70    if (*End == 0)
71      return n >= 0 && (unsigned)n < NumNames;
72  }
73
74  // Check register names.
75  for (unsigned i = 0; i < NumNames; i++) {
76    if (strcmp(Name, Names[i]) == 0)
77      return true;
78  }
79
80  // Now check aliases.
81  const GCCRegAlias *Aliases;
82  unsigned NumAliases;
83
84  getGCCRegAliases(Aliases, NumAliases);
85  for (unsigned i = 0; i < NumAliases; i++) {
86    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
87      if (!Aliases[i].Aliases[j])
88        break;
89      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
90        return true;
91    }
92  }
93
94  return false;
95}
96
97const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
98  assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
99
100  removeGCCRegisterPrefix(Name);
101
102  const char * const *Names;
103  unsigned NumNames;
104
105  getGCCRegNames(Names, NumNames);
106
107  // First, check if we have a number.
108  if (isdigit(Name[0])) {
109    char *End;
110    int n = (int)strtol(Name, &End, 0);
111    if (*End == 0) {
112      assert(n >= 0 && (unsigned)n < NumNames &&
113             "Out of bounds register number!");
114      return Names[n];
115    }
116  }
117
118  // Now check aliases.
119  const GCCRegAlias *Aliases;
120  unsigned NumAliases;
121
122  getGCCRegAliases(Aliases, NumAliases);
123  for (unsigned i = 0; i < NumAliases; i++) {
124    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
125      if (!Aliases[i].Aliases[j])
126        break;
127      if (strcmp(Aliases[i].Aliases[j], Name) == 0)
128        return Aliases[i].Register;
129    }
130  }
131
132  return Name;
133}
134
135bool TargetInfo::validateOutputConstraint(const char *Name,
136                                          ConstraintInfo &info) const
137{
138  // An output constraint must start with '=' or '+'
139  if (*Name != '=' && *Name != '+')
140    return false;
141
142  if (*Name == '+')
143    info = CI_ReadWrite;
144  else
145    info = CI_None;
146
147  Name++;
148  while (*Name) {
149    switch (*Name) {
150    default:
151      if (!validateAsmConstraint(*Name, info)) {
152        // FIXME: We temporarily return false
153        // so we can add more constraints as we hit it.
154        // Eventually, an unknown constraint should just be treated as 'g'.
155        return false;
156      }
157    case '&': // early clobber.
158      break;
159    case 'r': // general register.
160      info = (ConstraintInfo)(info|CI_AllowsRegister);
161      break;
162    case 'm': // memory operand.
163      info = (ConstraintInfo)(info|CI_AllowsMemory);
164      break;
165    case 'g': // general register, memory operand or immediate integer.
166      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
167      break;
168    }
169
170    Name++;
171  }
172
173  return true;
174}
175
176bool TargetInfo::validateInputConstraint(const char *Name,
177                                         unsigned NumOutputs,
178                                         ConstraintInfo &info) const {
179  while (*Name) {
180    switch (*Name) {
181    default:
182      // Check if we have a matching constraint
183      if (*Name >= '0' && *Name <= '9') {
184        unsigned i = *Name - '0';
185
186        // Check if matching constraint is out of bounds.
187        if (i >= NumOutputs)
188          return false;
189      } else if (!validateAsmConstraint(*Name, info)) {
190        // FIXME: This assert is in place temporarily
191        // so we can add more constraints as we hit it.
192        // Eventually, an unknown constraint should just be treated as 'g'.
193        assert(0 && "Unknown input constraint type!");
194      }
195    case '%': // commutative
196      // FIXME: Fail if % is used with the last operand.
197      break;
198    case 'i': // immediate integer.
199    case 'I':
200    case 'n': // immediate integer with a known value.
201      break;
202    case 'r': // general register.
203      info = (ConstraintInfo)(info|CI_AllowsRegister);
204      break;
205    case 'm': // memory operand.
206      info = (ConstraintInfo)(info|CI_AllowsMemory);
207      break;
208    case 'g': // general register, memory operand or immediate integer.
209      info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
210      break;
211    }
212
213    Name++;
214  }
215
216  return true;
217}
218