blob: 16a745cdc6bd28005a7805d2c6ba2cd9486dabf8 [file] [log] [blame]
Chris Lattner4b009652007-07-25 00:24:17 +00001//===--- TargetInfo.cpp - Information about Target machine ----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner959e5be2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Chris Lattner4b009652007-07-25 00:24:17 +00007//
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"
Chris Lattner858eece2007-09-22 18:29:59 +000017#include "llvm/ADT/APFloat.h"
Anders Carlsson49dadd62007-11-25 00:25:21 +000018#include "llvm/ADT/STLExtras.h"
Chris Lattner5c81ea02008-04-06 04:02:29 +000019#include <cstdlib>
Chris Lattner4b009652007-07-25 00:24:17 +000020using namespace clang;
21
Chris Lattner3b74cac2008-03-08 08:59:43 +000022// 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 WCharWidth = WCharAlign = 32;
27 FloatFormat = &llvm::APFloat::IEEEsingle;
28 DoubleFormat = &llvm::APFloat::IEEEdouble;
29 LongDoubleFormat = &llvm::APFloat::IEEEdouble;
30}
31
Chris Lattner0fb8d852008-03-08 08:24:01 +000032// Out of line virtual dtor for TargetInfo.
33TargetInfo::~TargetInfo() {}
Chris Lattner4b009652007-07-25 00:24:17 +000034
Chris Lattner858eece2007-09-22 18:29:59 +000035//===----------------------------------------------------------------------===//
Chris Lattner858eece2007-09-22 18:29:59 +000036
Chris Lattner4b009652007-07-25 00:24:17 +000037
Chris Lattnerfc457002008-03-05 01:18:20 +000038static void removeGCCRegisterPrefix(const char *&Name) {
Anders Carlsson74385982008-02-06 00:11:32 +000039 if (Name[0] == '%' || Name[0] == '#')
40 Name++;
41}
42
Anders Carlsson7dd1c952007-11-24 23:38:12 +000043/// isValidGCCRegisterName - Returns whether the passed in string
44/// is a valid register name according to GCC. This is used by Sema for
45/// inline asm statements.
46bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
Anders Carlsson49dadd62007-11-25 00:25:21 +000047 const char * const *Names;
48 unsigned NumNames;
49
50 // Get rid of any register prefix.
Anders Carlsson74385982008-02-06 00:11:32 +000051 removeGCCRegisterPrefix(Name);
52
Anders Carlsson49dadd62007-11-25 00:25:21 +000053
54 if (strcmp(Name, "memory") == 0 ||
55 strcmp(Name, "cc") == 0)
56 return true;
57
Chris Lattner0fb8d852008-03-08 08:24:01 +000058 getGCCRegNames(Names, NumNames);
Anders Carlsson49dadd62007-11-25 00:25:21 +000059
60 // If we have a number it maps to an entry in the register name array.
61 if (isdigit(Name[0])) {
62 char *End;
63 int n = (int)strtol(Name, &End, 0);
64 if (*End == 0)
65 return n >= 0 && (unsigned)n < NumNames;
66 }
67
68 // Check register names.
69 for (unsigned i = 0; i < NumNames; i++) {
70 if (strcmp(Name, Names[i]) == 0)
71 return true;
72 }
73
74 // Now check aliases.
Chris Lattner0fb8d852008-03-08 08:24:01 +000075 const GCCRegAlias *Aliases;
Anders Carlsson49dadd62007-11-25 00:25:21 +000076 unsigned NumAliases;
77
Chris Lattner0fb8d852008-03-08 08:24:01 +000078 getGCCRegAliases(Aliases, NumAliases);
Anders Carlsson49dadd62007-11-25 00:25:21 +000079 for (unsigned i = 0; i < NumAliases; i++) {
80 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
81 if (!Aliases[i].Aliases[j])
82 break;
83 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
84 return true;
85 }
86 }
87
Anders Carlsson7dd1c952007-11-24 23:38:12 +000088 return false;
89}
Anders Carlsson4ce42302007-11-27 04:11:28 +000090
Chris Lattner0fb8d852008-03-08 08:24:01 +000091const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
Anders Carlsson4ce42302007-11-27 04:11:28 +000092 assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
93
Anders Carlsson74385982008-02-06 00:11:32 +000094 removeGCCRegisterPrefix(Name);
Anders Carlsson3fb39b12008-02-05 23:30:20 +000095
Anders Carlsson4ce42302007-11-27 04:11:28 +000096 const char * const *Names;
97 unsigned NumNames;
98
Chris Lattner0fb8d852008-03-08 08:24:01 +000099 getGCCRegNames(Names, NumNames);
Anders Carlsson4ce42302007-11-27 04:11:28 +0000100
101 // First, check if we have a number.
102 if (isdigit(Name[0])) {
103 char *End;
104 int n = (int)strtol(Name, &End, 0);
105 if (*End == 0) {
106 assert(n >= 0 && (unsigned)n < NumNames &&
107 "Out of bounds register number!");
108 return Names[n];
109 }
110 }
111
112 // Now check aliases.
Chris Lattner0fb8d852008-03-08 08:24:01 +0000113 const GCCRegAlias *Aliases;
Anders Carlsson4ce42302007-11-27 04:11:28 +0000114 unsigned NumAliases;
115
Chris Lattner0fb8d852008-03-08 08:24:01 +0000116 getGCCRegAliases(Aliases, NumAliases);
Anders Carlsson4ce42302007-11-27 04:11:28 +0000117 for (unsigned i = 0; i < NumAliases; i++) {
118 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
119 if (!Aliases[i].Aliases[j])
120 break;
121 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
122 return Aliases[i].Register;
123 }
124 }
125
126 return Name;
127}
128
129bool TargetInfo::validateOutputConstraint(const char *Name,
130 ConstraintInfo &info) const
131{
132 // An output constraint must start with '=' or '+'
133 if (*Name != '=' && *Name != '+')
134 return false;
135
136 if (*Name == '+')
137 info = CI_ReadWrite;
138 else
139 info = CI_None;
140
141 Name++;
142 while (*Name) {
143 switch (*Name) {
144 default:
Chris Lattner0fb8d852008-03-08 08:24:01 +0000145 if (!validateAsmConstraint(*Name, info)) {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000146 // FIXME: This assert is in place temporarily
147 // so we can add more constraints as we hit it.
148 // Eventually, an unknown constraint should just be treated as 'g'.
149 assert(0 && "Unknown output constraint type!");
150 }
151 case '&': // early clobber.
152 break;
153 case 'r': // general register.
154 info = (ConstraintInfo)(info|CI_AllowsRegister);
155 break;
156 case 'm': // memory operand.
157 info = (ConstraintInfo)(info|CI_AllowsMemory);
158 break;
159 case 'g': // general register, memory operand or immediate integer.
160 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
161 break;
162 }
163
164 Name++;
165 }
166
167 return true;
168}
169
170bool TargetInfo::validateInputConstraint(const char *Name,
171 unsigned NumOutputs,
Chris Lattner0fb8d852008-03-08 08:24:01 +0000172 ConstraintInfo &info) const {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000173 while (*Name) {
174 switch (*Name) {
175 default:
176 // Check if we have a matching constraint
177 if (*Name >= '0' && *Name <= '9') {
178 unsigned i = *Name - '0';
179
180 // Check if matching constraint is out of bounds.
181 if (i >= NumOutputs)
182 return false;
Chris Lattner0fb8d852008-03-08 08:24:01 +0000183 } else if (!validateAsmConstraint(*Name, info)) {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000184 // FIXME: This assert is in place temporarily
185 // so we can add more constraints as we hit it.
186 // Eventually, an unknown constraint should just be treated as 'g'.
187 assert(0 && "Unknown input constraint type!");
188 }
Anders Carlsson333052c2007-12-08 19:32:57 +0000189 case '%': // commutative
190 // FIXME: Fail if % is used with the last operand.
191 break;
Anders Carlsson4ce42302007-11-27 04:11:28 +0000192 case 'i': // immediate integer.
Anders Carlssonf8e50d92008-02-18 17:00:25 +0000193 case 'I':
Anders Carlssonbdb0e2b2008-03-09 06:02:02 +0000194 case 'n': // immediate integer with a known value.
Anders Carlsson4ce42302007-11-27 04:11:28 +0000195 break;
196 case 'r': // general register.
197 info = (ConstraintInfo)(info|CI_AllowsRegister);
198 break;
199 case 'm': // memory operand.
200 info = (ConstraintInfo)(info|CI_AllowsMemory);
201 break;
202 case 'g': // general register, memory operand or immediate integer.
203 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
204 break;
205 }
206
207 Name++;
208 }
209
210 return true;
211}