blob: 1f0becee3413c9becef43a046b29b278b24ef6cc [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,
Chris Lattner8cd0e932008-03-05 18:54:05 +000031 const llvm::fltSemantics *&Format) {
Chris Lattner858eece2007-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 Lattner8cd0e932008-03-05 18:54:05 +000037 const llvm::fltSemantics *&Format) {
Anders Carlssonf6db4262008-02-17 03:40:02 +000038 Size = 64; // FIXME: implement correctly.
39 Align = 32;
Chris Lattner858eece2007-09-22 18:29:59 +000040 Format = &llvm::APFloat::IEEEdouble;
41}
42void TargetInfo::getLongDoubleInfo(uint64_t &Size, unsigned &Align,
Chris Lattner8cd0e932008-03-05 18:54:05 +000043 const llvm::fltSemantics *&Format) {
Chris Lattner36f46b82007-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 Lattner858eece2007-09-22 18:29:59 +000048}
49
50
51//===----------------------------------------------------------------------===//
52
Chris Lattner296d1c82008-03-05 00:53:34 +000053TargetInfo::~TargetInfo() {
Chris Lattnerfc457002008-03-05 01:18:20 +000054 delete Target;
Chris Lattner296d1c82008-03-05 00:53:34 +000055}
56
Ted Kremenek40499482007-12-03 22:06:55 +000057const char* TargetInfo::getTargetTriple() const {
Chris Lattnerfc457002008-03-05 01:18:20 +000058 return Target->getTargetTriple();
Ted Kremenek40499482007-12-03 22:06:55 +000059}
60
Anders Carlsson333052c2007-12-08 19:32:57 +000061const char *TargetInfo::getTargetPrefix() const {
Chris Lattnerfc457002008-03-05 01:18:20 +000062 return Target->getTargetPrefix();
Chris Lattner4b009652007-07-25 00:24:17 +000063}
64
65/// getTargetDefines - Appends the target-specific #define values for this
66/// target set to the specified buffer.
67void TargetInfo::getTargetDefines(std::vector<char> &Buffer) {
Chris Lattnerfc457002008-03-05 01:18:20 +000068 Target->getTargetDefines(Buffer);
Chris Lattner4b009652007-07-25 00:24:17 +000069}
70
71/// ComputeWCharWidth - Determine the width of the wchar_t type for the primary
72/// target, diagnosing whether this is non-portable across the secondary
73/// targets.
Chris Lattner8cd0e932008-03-05 18:54:05 +000074void TargetInfo::ComputeWCharInfo() {
Chris Lattnerfc457002008-03-05 01:18:20 +000075 Target->getWCharInfo(WCharWidth, WCharAlign);
Chris Lattner4b009652007-07-25 00:24:17 +000076}
77
78
79/// getTargetBuiltins - Return information about target-specific builtins for
80/// the current primary target, and info about which builtins are non-portable
81/// across the current set of primary and secondary targets.
82void TargetInfo::getTargetBuiltins(const Builtin::Info *&Records,
Chris Lattnerfc457002008-03-05 01:18:20 +000083 unsigned &NumRecords) const {
Chris Lattner4b009652007-07-25 00:24:17 +000084 // Get info about what actual builtins we will expose.
Chris Lattnerfc457002008-03-05 01:18:20 +000085 Target->getTargetBuiltins(Records, NumRecords);
Chris Lattner4b009652007-07-25 00:24:17 +000086}
87
Anders Carlsson8b58e8a2007-10-13 00:45:48 +000088/// getVAListDeclaration - Return the declaration to use for
89/// __builtin_va_list, which is target-specific.
90const char *TargetInfo::getVAListDeclaration() const {
Chris Lattnerfc457002008-03-05 01:18:20 +000091 return Target->getVAListDeclaration();
Anders Carlsson8b58e8a2007-10-13 00:45:48 +000092}
Chris Lattner4b009652007-07-25 00:24:17 +000093
Chris Lattnerfc457002008-03-05 01:18:20 +000094static void removeGCCRegisterPrefix(const char *&Name) {
Anders Carlsson74385982008-02-06 00:11:32 +000095 if (Name[0] == '%' || Name[0] == '#')
96 Name++;
97}
98
Anders Carlsson7dd1c952007-11-24 23:38:12 +000099/// isValidGCCRegisterName - Returns whether the passed in string
100/// is a valid register name according to GCC. This is used by Sema for
101/// inline asm statements.
102bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
Anders Carlsson49dadd62007-11-25 00:25:21 +0000103 const char * const *Names;
104 unsigned NumNames;
105
106 // Get rid of any register prefix.
Anders Carlsson74385982008-02-06 00:11:32 +0000107 removeGCCRegisterPrefix(Name);
108
Anders Carlsson49dadd62007-11-25 00:25:21 +0000109
110 if (strcmp(Name, "memory") == 0 ||
111 strcmp(Name, "cc") == 0)
112 return true;
113
Chris Lattnerfc457002008-03-05 01:18:20 +0000114 Target->getGCCRegNames(Names, NumNames);
Anders Carlsson49dadd62007-11-25 00:25:21 +0000115
116 // If we have a number it maps to an entry in the register name array.
117 if (isdigit(Name[0])) {
118 char *End;
119 int n = (int)strtol(Name, &End, 0);
120 if (*End == 0)
121 return n >= 0 && (unsigned)n < NumNames;
122 }
123
124 // Check register names.
125 for (unsigned i = 0; i < NumNames; i++) {
126 if (strcmp(Name, Names[i]) == 0)
127 return true;
128 }
129
130 // Now check aliases.
131 const TargetInfoImpl::GCCRegAlias *Aliases;
132 unsigned NumAliases;
133
Chris Lattnerfc457002008-03-05 01:18:20 +0000134 Target->getGCCRegAliases(Aliases, NumAliases);
Anders Carlsson49dadd62007-11-25 00:25:21 +0000135 for (unsigned i = 0; i < NumAliases; i++) {
136 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
137 if (!Aliases[i].Aliases[j])
138 break;
139 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
140 return true;
141 }
142 }
143
Anders Carlsson7dd1c952007-11-24 23:38:12 +0000144 return false;
145}
Anders Carlsson4ce42302007-11-27 04:11:28 +0000146
147const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const
148{
149 assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
150
Anders Carlsson74385982008-02-06 00:11:32 +0000151 removeGCCRegisterPrefix(Name);
Anders Carlsson3fb39b12008-02-05 23:30:20 +0000152
Anders Carlsson4ce42302007-11-27 04:11:28 +0000153 const char * const *Names;
154 unsigned NumNames;
155
Chris Lattnerfc457002008-03-05 01:18:20 +0000156 Target->getGCCRegNames(Names, NumNames);
Anders Carlsson4ce42302007-11-27 04:11:28 +0000157
158 // First, check if we have a number.
159 if (isdigit(Name[0])) {
160 char *End;
161 int n = (int)strtol(Name, &End, 0);
162 if (*End == 0) {
163 assert(n >= 0 && (unsigned)n < NumNames &&
164 "Out of bounds register number!");
165 return Names[n];
166 }
167 }
168
169 // Now check aliases.
170 const TargetInfoImpl::GCCRegAlias *Aliases;
171 unsigned NumAliases;
172
Chris Lattnerfc457002008-03-05 01:18:20 +0000173 Target->getGCCRegAliases(Aliases, NumAliases);
Anders Carlsson4ce42302007-11-27 04:11:28 +0000174 for (unsigned i = 0; i < NumAliases; i++) {
175 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
176 if (!Aliases[i].Aliases[j])
177 break;
178 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
179 return Aliases[i].Register;
180 }
181 }
182
183 return Name;
184}
185
186bool TargetInfo::validateOutputConstraint(const char *Name,
187 ConstraintInfo &info) const
188{
189 // An output constraint must start with '=' or '+'
190 if (*Name != '=' && *Name != '+')
191 return false;
192
193 if (*Name == '+')
194 info = CI_ReadWrite;
195 else
196 info = CI_None;
197
198 Name++;
199 while (*Name) {
200 switch (*Name) {
201 default:
Chris Lattnerfc457002008-03-05 01:18:20 +0000202 if (!Target->validateAsmConstraint(*Name, info)) {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000203 // FIXME: This assert is in place temporarily
204 // so we can add more constraints as we hit it.
205 // Eventually, an unknown constraint should just be treated as 'g'.
206 assert(0 && "Unknown output constraint type!");
207 }
208 case '&': // early clobber.
209 break;
210 case 'r': // general register.
211 info = (ConstraintInfo)(info|CI_AllowsRegister);
212 break;
213 case 'm': // memory operand.
214 info = (ConstraintInfo)(info|CI_AllowsMemory);
215 break;
216 case 'g': // general register, memory operand or immediate integer.
217 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
218 break;
219 }
220
221 Name++;
222 }
223
224 return true;
225}
226
227bool TargetInfo::validateInputConstraint(const char *Name,
228 unsigned NumOutputs,
229 ConstraintInfo &info) const
230{
231 while (*Name) {
232 switch (*Name) {
233 default:
234 // Check if we have a matching constraint
235 if (*Name >= '0' && *Name <= '9') {
236 unsigned i = *Name - '0';
237
238 // Check if matching constraint is out of bounds.
239 if (i >= NumOutputs)
240 return false;
Chris Lattnerfc457002008-03-05 01:18:20 +0000241 } else if (!Target->validateAsmConstraint(*Name, info)) {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000242 // FIXME: This assert is in place temporarily
243 // so we can add more constraints as we hit it.
244 // Eventually, an unknown constraint should just be treated as 'g'.
245 assert(0 && "Unknown input constraint type!");
246 }
Anders Carlsson333052c2007-12-08 19:32:57 +0000247 case '%': // commutative
248 // FIXME: Fail if % is used with the last operand.
249 break;
Anders Carlsson4ce42302007-11-27 04:11:28 +0000250 case 'i': // immediate integer.
Anders Carlssonf8e50d92008-02-18 17:00:25 +0000251 case 'I':
Anders Carlsson4ce42302007-11-27 04:11:28 +0000252 break;
253 case 'r': // general register.
254 info = (ConstraintInfo)(info|CI_AllowsRegister);
255 break;
256 case 'm': // memory operand.
257 info = (ConstraintInfo)(info|CI_AllowsMemory);
258 break;
259 case 'g': // general register, memory operand or immediate integer.
260 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
261 break;
262 }
263
264 Name++;
265 }
266
267 return true;
268}
269
Lauro Ramos Venanciobb37a042008-02-26 18:33:46 +0000270std::string TargetInfo::convertConstraint(const char Constraint) const {
Chris Lattnerfc457002008-03-05 01:18:20 +0000271 return Target->convertConstraint(Constraint);
Lauro Ramos Venanciobb37a042008-02-26 18:33:46 +0000272}
273
Chris Lattnerfc457002008-03-05 01:18:20 +0000274const char *TargetInfo::getClobbers() const {
275 return Target->getClobbers();
Anders Carlsson4ce42302007-11-27 04:11:28 +0000276}
277
278