blob: 0a561d75cb88c5409cada3532490ebdae61afa0c [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 Lattner4b009652007-07-25 00:24:17 +000019using namespace clang;
20
Chris Lattner3b74cac2008-03-08 08:59:43 +000021// TargetInfo Constructor.
22TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
23 // Set defaults. These should be overridden by concrete targets as needed.
24 CharIsSigned = true;
25 WCharWidth = WCharAlign = 32;
26 FloatFormat = &llvm::APFloat::IEEEsingle;
27 DoubleFormat = &llvm::APFloat::IEEEdouble;
28 LongDoubleFormat = &llvm::APFloat::IEEEdouble;
29}
30
Chris Lattner0fb8d852008-03-08 08:24:01 +000031// Out of line virtual dtor for TargetInfo.
32TargetInfo::~TargetInfo() {}
Chris Lattner4b009652007-07-25 00:24:17 +000033
Chris Lattner858eece2007-09-22 18:29:59 +000034//===----------------------------------------------------------------------===//
Chris Lattner858eece2007-09-22 18:29:59 +000035
Chris Lattner4b009652007-07-25 00:24:17 +000036
Chris Lattnerfc457002008-03-05 01:18:20 +000037static void removeGCCRegisterPrefix(const char *&Name) {
Anders Carlsson74385982008-02-06 00:11:32 +000038 if (Name[0] == '%' || Name[0] == '#')
39 Name++;
40}
41
Anders Carlsson7dd1c952007-11-24 23:38:12 +000042/// isValidGCCRegisterName - Returns whether the passed in string
43/// is a valid register name according to GCC. This is used by Sema for
44/// inline asm statements.
45bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
Anders Carlsson49dadd62007-11-25 00:25:21 +000046 const char * const *Names;
47 unsigned NumNames;
48
49 // Get rid of any register prefix.
Anders Carlsson74385982008-02-06 00:11:32 +000050 removeGCCRegisterPrefix(Name);
51
Anders Carlsson49dadd62007-11-25 00:25:21 +000052
53 if (strcmp(Name, "memory") == 0 ||
54 strcmp(Name, "cc") == 0)
55 return true;
56
Chris Lattner0fb8d852008-03-08 08:24:01 +000057 getGCCRegNames(Names, NumNames);
Anders Carlsson49dadd62007-11-25 00:25:21 +000058
59 // If we have a number it maps to an entry in the register name array.
60 if (isdigit(Name[0])) {
61 char *End;
62 int n = (int)strtol(Name, &End, 0);
63 if (*End == 0)
64 return n >= 0 && (unsigned)n < NumNames;
65 }
66
67 // Check register names.
68 for (unsigned i = 0; i < NumNames; i++) {
69 if (strcmp(Name, Names[i]) == 0)
70 return true;
71 }
72
73 // Now check aliases.
Chris Lattner0fb8d852008-03-08 08:24:01 +000074 const GCCRegAlias *Aliases;
Anders Carlsson49dadd62007-11-25 00:25:21 +000075 unsigned NumAliases;
76
Chris Lattner0fb8d852008-03-08 08:24:01 +000077 getGCCRegAliases(Aliases, NumAliases);
Anders Carlsson49dadd62007-11-25 00:25:21 +000078 for (unsigned i = 0; i < NumAliases; i++) {
79 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
80 if (!Aliases[i].Aliases[j])
81 break;
82 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
83 return true;
84 }
85 }
86
Anders Carlsson7dd1c952007-11-24 23:38:12 +000087 return false;
88}
Anders Carlsson4ce42302007-11-27 04:11:28 +000089
Chris Lattner0fb8d852008-03-08 08:24:01 +000090const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
Anders Carlsson4ce42302007-11-27 04:11:28 +000091 assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
92
Anders Carlsson74385982008-02-06 00:11:32 +000093 removeGCCRegisterPrefix(Name);
Anders Carlsson3fb39b12008-02-05 23:30:20 +000094
Anders Carlsson4ce42302007-11-27 04:11:28 +000095 const char * const *Names;
96 unsigned NumNames;
97
Chris Lattner0fb8d852008-03-08 08:24:01 +000098 getGCCRegNames(Names, NumNames);
Anders Carlsson4ce42302007-11-27 04:11:28 +000099
100 // First, check if we have a number.
101 if (isdigit(Name[0])) {
102 char *End;
103 int n = (int)strtol(Name, &End, 0);
104 if (*End == 0) {
105 assert(n >= 0 && (unsigned)n < NumNames &&
106 "Out of bounds register number!");
107 return Names[n];
108 }
109 }
110
111 // Now check aliases.
Chris Lattner0fb8d852008-03-08 08:24:01 +0000112 const GCCRegAlias *Aliases;
Anders Carlsson4ce42302007-11-27 04:11:28 +0000113 unsigned NumAliases;
114
Chris Lattner0fb8d852008-03-08 08:24:01 +0000115 getGCCRegAliases(Aliases, NumAliases);
Anders Carlsson4ce42302007-11-27 04:11:28 +0000116 for (unsigned i = 0; i < NumAliases; i++) {
117 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
118 if (!Aliases[i].Aliases[j])
119 break;
120 if (strcmp(Aliases[i].Aliases[j], Name) == 0)
121 return Aliases[i].Register;
122 }
123 }
124
125 return Name;
126}
127
128bool TargetInfo::validateOutputConstraint(const char *Name,
129 ConstraintInfo &info) const
130{
131 // An output constraint must start with '=' or '+'
132 if (*Name != '=' && *Name != '+')
133 return false;
134
135 if (*Name == '+')
136 info = CI_ReadWrite;
137 else
138 info = CI_None;
139
140 Name++;
141 while (*Name) {
142 switch (*Name) {
143 default:
Chris Lattner0fb8d852008-03-08 08:24:01 +0000144 if (!validateAsmConstraint(*Name, info)) {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000145 // FIXME: This assert is in place temporarily
146 // so we can add more constraints as we hit it.
147 // Eventually, an unknown constraint should just be treated as 'g'.
148 assert(0 && "Unknown output constraint type!");
149 }
150 case '&': // early clobber.
151 break;
152 case 'r': // general register.
153 info = (ConstraintInfo)(info|CI_AllowsRegister);
154 break;
155 case 'm': // memory operand.
156 info = (ConstraintInfo)(info|CI_AllowsMemory);
157 break;
158 case 'g': // general register, memory operand or immediate integer.
159 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
160 break;
161 }
162
163 Name++;
164 }
165
166 return true;
167}
168
169bool TargetInfo::validateInputConstraint(const char *Name,
170 unsigned NumOutputs,
Chris Lattner0fb8d852008-03-08 08:24:01 +0000171 ConstraintInfo &info) const {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000172 while (*Name) {
173 switch (*Name) {
174 default:
175 // Check if we have a matching constraint
176 if (*Name >= '0' && *Name <= '9') {
177 unsigned i = *Name - '0';
178
179 // Check if matching constraint is out of bounds.
180 if (i >= NumOutputs)
181 return false;
Chris Lattner0fb8d852008-03-08 08:24:01 +0000182 } else if (!validateAsmConstraint(*Name, info)) {
Anders Carlsson4ce42302007-11-27 04:11:28 +0000183 // FIXME: This assert is in place temporarily
184 // so we can add more constraints as we hit it.
185 // Eventually, an unknown constraint should just be treated as 'g'.
186 assert(0 && "Unknown input constraint type!");
187 }
Anders Carlsson333052c2007-12-08 19:32:57 +0000188 case '%': // commutative
189 // FIXME: Fail if % is used with the last operand.
190 break;
Anders Carlsson4ce42302007-11-27 04:11:28 +0000191 case 'i': // immediate integer.
Anders Carlssonf8e50d92008-02-18 17:00:25 +0000192 case 'I':
Anders Carlssonbdb0e2b2008-03-09 06:02:02 +0000193 case 'n': // immediate integer with a known value.
Anders Carlsson4ce42302007-11-27 04:11:28 +0000194 break;
195 case 'r': // general register.
196 info = (ConstraintInfo)(info|CI_AllowsRegister);
197 break;
198 case 'm': // memory operand.
199 info = (ConstraintInfo)(info|CI_AllowsMemory);
200 break;
201 case 'g': // general register, memory operand or immediate integer.
202 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister);
203 break;
204 }
205
206 Name++;
207 }
208
209 return true;
210}