blob: 16dad1cc2887184f6155562af075bf5306163540 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- TargetInfo.cpp - Information about Target machine ----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +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 Lattner525a0502007-09-22 18:29:59 +000017#include "llvm/ADT/APFloat.h"
Anders Carlsson6fa90862007-11-25 00:25:21 +000018#include "llvm/ADT/StringMap.h"
19#include "llvm/ADT/STLExtras.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000020#include <set>
21using namespace clang;
22
23void TargetInfoImpl::ANCHOR() {} // out-of-line virtual method for class.
24
25
Chris Lattner525a0502007-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,
Chris Lattner98be4942008-03-05 18:54:05 +000031 const llvm::fltSemantics *&Format) {
Chris Lattner525a0502007-09-22 18:29:59 +000032 Align = 32; // FIXME: implement correctly.
33 Size = 32;
34 Format = &llvm::APFloat::IEEEsingle;
35}
36void TargetInfo::getDoubleInfo(uint64_t &Size, unsigned &Align,
Chris Lattner98be4942008-03-05 18:54:05 +000037 const llvm::fltSemantics *&Format) {
Anders Carlssona9b20e52008-02-17 03:40:02 +000038 Size = 64; // FIXME: implement correctly.
39 Align = 32;
Chris Lattner525a0502007-09-22 18:29:59 +000040 Format = &llvm::APFloat::IEEEdouble;
41}
42void TargetInfo::getLongDoubleInfo(uint64_t &Size, unsigned &Align,
Chris Lattner98be4942008-03-05 18:54:05 +000043 const llvm::fltSemantics *&Format) {
Chris Lattner1c9bdae2007-09-22 18:38:30 +000044 Size = Align = 64; // FIXME: implement correctly.
45 Format = &llvm::APFloat::IEEEdouble;
46 //Size = 80; Align = 32; // FIXME: implement correctly.
47 //Format = &llvm::APFloat::x87DoubleExtended;
Chris Lattner525a0502007-09-22 18:29:59 +000048}
49
50
51//===----------------------------------------------------------------------===//
52
Chris Lattner39016112008-03-08 08:07:34 +000053TargetInfo::TargetInfo(const TargetInfoImpl *TII) {
54 Target = TII;
55
56 // Initialize Cache values to uncomputed.
57 TII->getWCharInfo(WCharWidth, WCharAlign);
58}
59
60
Chris Lattner544f0432008-03-05 00:53:34 +000061TargetInfo::~TargetInfo() {
Chris Lattner42e67372008-03-05 01:18:20 +000062 delete Target;
Chris Lattner544f0432008-03-05 00:53:34 +000063}
64
Ted Kremenekae360762007-12-03 22:06:55 +000065const char* TargetInfo::getTargetTriple() const {
Chris Lattner42e67372008-03-05 01:18:20 +000066 return Target->getTargetTriple();
Ted Kremenekae360762007-12-03 22:06:55 +000067}
68
Anders Carlsson44fe49c2007-12-08 19:32:57 +000069const char *TargetInfo::getTargetPrefix() const {
Chris Lattner42e67372008-03-05 01:18:20 +000070 return Target->getTargetPrefix();
Reid Spencer5f016e22007-07-11 17:01:13 +000071}
72
73/// getTargetDefines - Appends the target-specific #define values for this
74/// target set to the specified buffer.
75void TargetInfo::getTargetDefines(std::vector<char> &Buffer) {
Chris Lattner42e67372008-03-05 01:18:20 +000076 Target->getTargetDefines(Buffer);
Reid Spencer5f016e22007-07-11 17:01:13 +000077}
78
Reid Spencer5f016e22007-07-11 17:01:13 +000079
80/// getTargetBuiltins - Return information about target-specific builtins for
81/// the current primary target, and info about which builtins are non-portable
82/// across the current set of primary and secondary targets.
83void TargetInfo::getTargetBuiltins(const Builtin::Info *&Records,
Chris Lattner42e67372008-03-05 01:18:20 +000084 unsigned &NumRecords) const {
Reid Spencer5f016e22007-07-11 17:01:13 +000085 // Get info about what actual builtins we will expose.
Chris Lattner42e67372008-03-05 01:18:20 +000086 Target->getTargetBuiltins(Records, NumRecords);
Reid Spencer5f016e22007-07-11 17:01:13 +000087}
88
Anders Carlssonfb5e5ba2007-10-13 00:45:48 +000089/// getVAListDeclaration - Return the declaration to use for
90/// __builtin_va_list, which is target-specific.
91const char *TargetInfo::getVAListDeclaration() const {
Chris Lattner42e67372008-03-05 01:18:20 +000092 return Target->getVAListDeclaration();
Anders Carlssonfb5e5ba2007-10-13 00:45:48 +000093}
Reid Spencer5f016e22007-07-11 17:01:13 +000094
Chris Lattner42e67372008-03-05 01:18:20 +000095static void removeGCCRegisterPrefix(const char *&Name) {
Anders Carlssonea041752008-02-06 00:11:32 +000096 if (Name[0] == '%' || Name[0] == '#')
97 Name++;
98}
99
Anders Carlsson3346ae62007-11-24 23:38:12 +0000100/// isValidGCCRegisterName - Returns whether the passed in string
101/// is a valid register name according to GCC. This is used by Sema for
102/// inline asm statements.
103bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
Anders Carlsson6fa90862007-11-25 00:25:21 +0000104 const char * const *Names;
105 unsigned NumNames;
106
107 // Get rid of any register prefix.
Anders Carlssonea041752008-02-06 00:11:32 +0000108 removeGCCRegisterPrefix(Name);
109
Anders Carlsson6fa90862007-11-25 00:25:21 +0000110
111 if (strcmp(Name, "memory") == 0 ||
112 strcmp(Name, "cc") == 0)
113 return true;
114
Chris Lattner42e67372008-03-05 01:18:20 +0000115 Target->getGCCRegNames(Names, NumNames);
Anders Carlsson6fa90862007-11-25 00:25:21 +0000116
117 // If we have a number it maps to an entry in the register name array.
118 if (isdigit(Name[0])) {
119 char *End;
120 int n = (int)strtol(Name, &End, 0);
121 if (*End == 0)
122 return n >= 0 && (unsigned)n < NumNames;
123 }
124
125 // Check register names.
126 for (unsigned i = 0; i < NumNames; i++) {
127 if (strcmp(Name, Names[i]) == 0)
128 return true;
129 }
130
131 // Now check aliases.
132 const TargetInfoImpl::GCCRegAlias *Aliases;
133 unsigned NumAliases;
134
Chris Lattner42e67372008-03-05 01:18:20 +0000135 Target->getGCCRegAliases(Aliases, NumAliases);
Anders Carlsson6fa90862007-11-25 00:25:21 +0000136 for (unsigned i = 0; i < NumAliases; i++) {
137 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
138 if (!Aliases[i].Aliases[j])
139 break;
140 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
141 return true;
142 }
143 }
144
Anders Carlsson3346ae62007-11-24 23:38:12 +0000145 return false;
146}
Anders Carlssond04c6e22007-11-27 04:11:28 +0000147
148const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const
149{
150 assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
151
Anders Carlssonea041752008-02-06 00:11:32 +0000152 removeGCCRegisterPrefix(Name);
Anders Carlssonef3577d2008-02-05 23:30:20 +0000153
Anders Carlssond04c6e22007-11-27 04:11:28 +0000154 const char * const *Names;
155 unsigned NumNames;
156
Chris Lattner42e67372008-03-05 01:18:20 +0000157 Target->getGCCRegNames(Names, NumNames);
Anders Carlssond04c6e22007-11-27 04:11:28 +0000158
159 // First, check if we have a number.
160 if (isdigit(Name[0])) {
161 char *End;
162 int n = (int)strtol(Name, &End, 0);
163 if (*End == 0) {
164 assert(n >= 0 && (unsigned)n < NumNames &&
165 "Out of bounds register number!");
166 return Names[n];
167 }
168 }
169
170 // Now check aliases.
171 const TargetInfoImpl::GCCRegAlias *Aliases;
172 unsigned NumAliases;
173
Chris Lattner42e67372008-03-05 01:18:20 +0000174 Target->getGCCRegAliases(Aliases, NumAliases);
Anders Carlssond04c6e22007-11-27 04:11:28 +0000175 for (unsigned i = 0; i < NumAliases; i++) {
176 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
177 if (!Aliases[i].Aliases[j])
178 break;
179 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
180 return Aliases[i].Register;
181 }
182 }
183
184 return Name;
185}
186
187bool TargetInfo::validateOutputConstraint(const char *Name,
188 ConstraintInfo &info) const
189{
190 // An output constraint must start with '=' or '+'
191 if (*Name != '=' && *Name != '+')
192 return false;
193
194 if (*Name == '+')
195 info = CI_ReadWrite;
196 else
197 info = CI_None;
198
199 Name++;
200 while (*Name) {
201 switch (*Name) {
202 default:
Chris Lattner42e67372008-03-05 01:18:20 +0000203 if (!Target->validateAsmConstraint(*Name, info)) {
Anders Carlssond04c6e22007-11-27 04:11:28 +0000204 // FIXME: This assert is in place temporarily
205 // so we can add more constraints as we hit it.
206 // Eventually, an unknown constraint should just be treated as 'g'.
207 assert(0 && "Unknown output constraint type!");
208 }
209 case '&': // early clobber.
210 break;
211 case 'r': // general register.
212 info = (ConstraintInfo)(info|CI_AllowsRegister);
213 break;
214 case 'm': // memory operand.
215 info = (ConstraintInfo)(info|CI_AllowsMemory);
216 break;
217 case 'g': // general register, memory operand or immediate integer.
218 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
219 break;
220 }
221
222 Name++;
223 }
224
225 return true;
226}
227
228bool TargetInfo::validateInputConstraint(const char *Name,
229 unsigned NumOutputs,
230 ConstraintInfo &info) const
231{
232 while (*Name) {
233 switch (*Name) {
234 default:
235 // Check if we have a matching constraint
236 if (*Name >= '0' && *Name <= '9') {
237 unsigned i = *Name - '0';
238
239 // Check if matching constraint is out of bounds.
240 if (i >= NumOutputs)
241 return false;
Chris Lattner42e67372008-03-05 01:18:20 +0000242 } else if (!Target->validateAsmConstraint(*Name, info)) {
Anders Carlssond04c6e22007-11-27 04:11:28 +0000243 // FIXME: This assert is in place temporarily
244 // so we can add more constraints as we hit it.
245 // Eventually, an unknown constraint should just be treated as 'g'.
246 assert(0 && "Unknown input constraint type!");
247 }
Anders Carlsson44fe49c2007-12-08 19:32:57 +0000248 case '%': // commutative
249 // FIXME: Fail if % is used with the last operand.
250 break;
Anders Carlssond04c6e22007-11-27 04:11:28 +0000251 case 'i': // immediate integer.
Anders Carlssonb41edf92008-02-18 17:00:25 +0000252 case 'I':
Anders Carlssond04c6e22007-11-27 04:11:28 +0000253 break;
254 case 'r': // general register.
255 info = (ConstraintInfo)(info|CI_AllowsRegister);
256 break;
257 case 'm': // memory operand.
258 info = (ConstraintInfo)(info|CI_AllowsMemory);
259 break;
260 case 'g': // general register, memory operand or immediate integer.
261 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
262 break;
263 }
264
265 Name++;
266 }
267
268 return true;
269}
270
Lauro Ramos Venancioa5694b82008-02-26 18:33:46 +0000271std::string TargetInfo::convertConstraint(const char Constraint) const {
Chris Lattner42e67372008-03-05 01:18:20 +0000272 return Target->convertConstraint(Constraint);
Lauro Ramos Venancioa5694b82008-02-26 18:33:46 +0000273}
274
Chris Lattner42e67372008-03-05 01:18:20 +0000275const char *TargetInfo::getClobbers() const {
276 return Target->getClobbers();
Anders Carlssond04c6e22007-11-27 04:11:28 +0000277}
278
279