blob: 8701b38a0f1deecaf20ba98611152aa9ad8c9658 [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/StringMap.h"
19#include "llvm/ADT/STLExtras.h"
Chris Lattner4b009652007-07-25 00:24:17 +000020#include <set>
21using namespace clang;
22
23void TargetInfoImpl::ANCHOR() {} // out-of-line virtual method for class.
24
25
Chris Lattner858eece2007-09-22 18:29:59 +000026//===----------------------------------------------------------------------===//
27// FIXME: These are temporary hacks, they should revector into the
28// TargetInfoImpl.
29
30void TargetInfo::getFloatInfo(uint64_t &Size, unsigned &Align,
31 const llvm::fltSemantics *&Format,
Ted Kremenekd7f64cd2007-12-12 22:39:36 +000032 FullSourceLoc Loc) {
Chris Lattner858eece2007-09-22 18:29:59 +000033 Align = 32; // FIXME: implement correctly.
34 Size = 32;
35 Format = &llvm::APFloat::IEEEsingle;
36}
37void TargetInfo::getDoubleInfo(uint64_t &Size, unsigned &Align,
38 const llvm::fltSemantics *&Format,
Ted Kremenekd7f64cd2007-12-12 22:39:36 +000039 FullSourceLoc Loc) {
Anders Carlssonf6db4262008-02-17 03:40:02 +000040 Size = 64; // FIXME: implement correctly.
41 Align = 32;
Chris Lattner858eece2007-09-22 18:29:59 +000042 Format = &llvm::APFloat::IEEEdouble;
43}
44void TargetInfo::getLongDoubleInfo(uint64_t &Size, unsigned &Align,
45 const llvm::fltSemantics *&Format,
Ted Kremenekd7f64cd2007-12-12 22:39:36 +000046 FullSourceLoc Loc) {
Chris Lattner36f46b82007-09-22 18:38:30 +000047 Size = Align = 64; // FIXME: implement correctly.
48 Format = &llvm::APFloat::IEEEdouble;
49 //Size = 80; Align = 32; // FIXME: implement correctly.
50 //Format = &llvm::APFloat::x87DoubleExtended;
Chris Lattner858eece2007-09-22 18:29:59 +000051}
52
53
54//===----------------------------------------------------------------------===//
55
Chris Lattner296d1c82008-03-05 00:53:34 +000056TargetInfo::~TargetInfo() {
Chris Lattnerfc457002008-03-05 01:18:20 +000057 delete Target;
Chris Lattner296d1c82008-03-05 00:53:34 +000058}
59
Ted Kremenek40499482007-12-03 22:06:55 +000060const char* TargetInfo::getTargetTriple() const {
Chris Lattnerfc457002008-03-05 01:18:20 +000061 return Target->getTargetTriple();
Ted Kremenek40499482007-12-03 22:06:55 +000062}
63
Anders Carlsson333052c2007-12-08 19:32:57 +000064const char *TargetInfo::getTargetPrefix() const {
Chris Lattnerfc457002008-03-05 01:18:20 +000065 return Target->getTargetPrefix();
Chris Lattner4b009652007-07-25 00:24:17 +000066}
67
68/// getTargetDefines - Appends the target-specific #define values for this
69/// target set to the specified buffer.
70void TargetInfo::getTargetDefines(std::vector<char> &Buffer) {
Chris Lattnerfc457002008-03-05 01:18:20 +000071 Target->getTargetDefines(Buffer);
Chris Lattner4b009652007-07-25 00:24:17 +000072}
73
74/// ComputeWCharWidth - Determine the width of the wchar_t type for the primary
75/// target, diagnosing whether this is non-portable across the secondary
76/// targets.
Ted Kremenekd7f64cd2007-12-12 22:39:36 +000077void TargetInfo::ComputeWCharInfo(FullSourceLoc Loc) {
Chris Lattnerfc457002008-03-05 01:18:20 +000078 Target->getWCharInfo(WCharWidth, WCharAlign);
Chris Lattner4b009652007-07-25 00:24:17 +000079}
80
81
82/// getTargetBuiltins - Return information about target-specific builtins for
83/// the current primary target, and info about which builtins are non-portable
84/// across the current set of primary and secondary targets.
85void TargetInfo::getTargetBuiltins(const Builtin::Info *&Records,
Chris Lattnerfc457002008-03-05 01:18:20 +000086 unsigned &NumRecords) const {
Chris Lattner4b009652007-07-25 00:24:17 +000087 // Get info about what actual builtins we will expose.
Chris Lattnerfc457002008-03-05 01:18:20 +000088 Target->getTargetBuiltins(Records, NumRecords);
Chris Lattner4b009652007-07-25 00:24:17 +000089}
90
Anders Carlsson8b58e8a2007-10-13 00:45:48 +000091/// getVAListDeclaration - Return the declaration to use for
92/// __builtin_va_list, which is target-specific.
93const char *TargetInfo::getVAListDeclaration() const {
Chris Lattnerfc457002008-03-05 01:18:20 +000094 return Target->getVAListDeclaration();
Anders Carlsson8b58e8a2007-10-13 00:45:48 +000095}
Chris Lattner4b009652007-07-25 00:24:17 +000096
Chris Lattnerfc457002008-03-05 01:18:20 +000097static void removeGCCRegisterPrefix(const char *&Name) {
Anders Carlsson74385982008-02-06 00:11:32 +000098 if (Name[0] == '%' || Name[0] == '#')
99 Name++;
100}
101
Anders Carlsson7dd1c952007-11-24 23:38:12 +0000102/// isValidGCCRegisterName - Returns whether the passed in string
103/// is a valid register name according to GCC. This is used by Sema for
104/// inline asm statements.
105bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
Anders Carlsson49dadd62007-11-25 00:25:21 +0000106 const char * const *Names;
107 unsigned NumNames;
108
109 // Get rid of any register prefix.
Anders Carlsson74385982008-02-06 00:11:32 +0000110 removeGCCRegisterPrefix(Name);
111
Anders Carlsson49dadd62007-11-25 00:25:21 +0000112
113 if (strcmp(Name, "memory") == 0 ||
114 strcmp(Name, "cc") == 0)
115 return true;
116
Chris Lattnerfc457002008-03-05 01:18:20 +0000117 Target->getGCCRegNames(Names, NumNames);
Anders Carlsson49dadd62007-11-25 00:25:21 +0000118
119 // If we have a number it maps to an entry in the register name array.
120 if (isdigit(Name[0])) {
121 char *End;
122 int n = (int)strtol(Name, &End, 0);
123 if (*End == 0)
124 return n >= 0 && (unsigned)n < NumNames;
125 }
126
127 // Check register names.
128 for (unsigned i = 0; i < NumNames; i++) {
129 if (strcmp(Name, Names[i]) == 0)
130 return true;
131 }
132
133 // Now check aliases.
134 const TargetInfoImpl::GCCRegAlias *Aliases;
135 unsigned NumAliases;
136
Chris Lattnerfc457002008-03-05 01:18:20 +0000137 Target->getGCCRegAliases(Aliases, NumAliases);
Anders Carlsson49dadd62007-11-25 00:25:21 +0000138 for (unsigned i = 0; i < NumAliases; i++) {
139 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
140 if (!Aliases[i].Aliases[j])
141 break;
142 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
143 return true;
144 }
145 }
146
Anders Carlsson7dd1c952007-11-24 23:38:12 +0000147 return false;
148}
Anders Carlsson4ce42302007-11-27 04:11:28 +0000149
150const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const
151{
152 assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
153
Anders Carlsson74385982008-02-06 00:11:32 +0000154 removeGCCRegisterPrefix(Name);
Anders Carlsson3fb39b12008-02-05 23:30:20 +0000155
Anders Carlsson4ce42302007-11-27 04:11:28 +0000156 const char * const *Names;
157 unsigned NumNames;
158
Chris Lattnerfc457002008-03-05 01:18:20 +0000159 Target->getGCCRegNames(Names, NumNames);
Anders Carlsson4ce42302007-11-27 04:11:28 +0000160
161 // First, check if we have a number.
162 if (isdigit(Name[0])) {
163 char *End;
164 int n = (int)strtol(Name, &End, 0);
165 if (*End == 0) {
166 assert(n >= 0 && (unsigned)n < NumNames &&
167 "Out of bounds register number!");
168 return Names[n];
169 }
170 }
171
172 // Now check aliases.
173 const TargetInfoImpl::GCCRegAlias *Aliases;
174 unsigned NumAliases;
175
Chris Lattnerfc457002008-03-05 01:18:20 +0000176 Target->getGCCRegAliases(Aliases, NumAliases);
Anders Carlsson4ce42302007-11-27 04:11:28 +0000177 for (unsigned i = 0; i < NumAliases; i++) {
178 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
179 if (!Aliases[i].Aliases[j])
180 break;
181 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
182 return Aliases[i].Register;
183 }
184 }
185
186 return Name;
187}
188
189bool TargetInfo::validateOutputConstraint(const char *Name,
190 ConstraintInfo &info) const
191{
192 // An output constraint must start with '=' or '+'
193 if (*Name != '=' && *Name != '+')
194 return false;
195
196 if (*Name == '+')
197 info = CI_ReadWrite;
198 else
199 info = CI_None;
200
201 Name++;
202 while (*Name) {
203 switch (*Name) {
204 default:
Chris Lattnerfc457002008-03-05 01:18:20 +0000205 if (!Target->validateAsmConstraint(*Name, info)) {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000206 // FIXME: This assert is in place temporarily
207 // so we can add more constraints as we hit it.
208 // Eventually, an unknown constraint should just be treated as 'g'.
209 assert(0 && "Unknown output constraint type!");
210 }
211 case '&': // early clobber.
212 break;
213 case 'r': // general register.
214 info = (ConstraintInfo)(info|CI_AllowsRegister);
215 break;
216 case 'm': // memory operand.
217 info = (ConstraintInfo)(info|CI_AllowsMemory);
218 break;
219 case 'g': // general register, memory operand or immediate integer.
220 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
221 break;
222 }
223
224 Name++;
225 }
226
227 return true;
228}
229
230bool TargetInfo::validateInputConstraint(const char *Name,
231 unsigned NumOutputs,
232 ConstraintInfo &info) const
233{
234 while (*Name) {
235 switch (*Name) {
236 default:
237 // Check if we have a matching constraint
238 if (*Name >= '0' && *Name <= '9') {
239 unsigned i = *Name - '0';
240
241 // Check if matching constraint is out of bounds.
242 if (i >= NumOutputs)
243 return false;
Chris Lattnerfc457002008-03-05 01:18:20 +0000244 } else if (!Target->validateAsmConstraint(*Name, info)) {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000245 // FIXME: This assert is in place temporarily
246 // so we can add more constraints as we hit it.
247 // Eventually, an unknown constraint should just be treated as 'g'.
248 assert(0 && "Unknown input constraint type!");
249 }
Anders Carlsson333052c2007-12-08 19:32:57 +0000250 case '%': // commutative
251 // FIXME: Fail if % is used with the last operand.
252 break;
Anders Carlsson4ce42302007-11-27 04:11:28 +0000253 case 'i': // immediate integer.
Anders Carlssonf8e50d92008-02-18 17:00:25 +0000254 case 'I':
Anders Carlsson4ce42302007-11-27 04:11:28 +0000255 break;
256 case 'r': // general register.
257 info = (ConstraintInfo)(info|CI_AllowsRegister);
258 break;
259 case 'm': // memory operand.
260 info = (ConstraintInfo)(info|CI_AllowsMemory);
261 break;
262 case 'g': // general register, memory operand or immediate integer.
263 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
264 break;
265 }
266
267 Name++;
268 }
269
270 return true;
271}
272
Lauro Ramos Venanciobb37a042008-02-26 18:33:46 +0000273std::string TargetInfo::convertConstraint(const char Constraint) const {
Chris Lattnerfc457002008-03-05 01:18:20 +0000274 return Target->convertConstraint(Constraint);
Lauro Ramos Venanciobb37a042008-02-26 18:33:46 +0000275}
276
Chris Lattnerfc457002008-03-05 01:18:20 +0000277const char *TargetInfo::getClobbers() const {
278 return Target->getClobbers();
Anders Carlsson4ce42302007-11-27 04:11:28 +0000279}
280
281