1 //===--- TargetInfo.cpp - Information about Target machine ----------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements the TargetInfo and TargetInfoImpl interfaces.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Basic/TargetInfo.h"
15 #include "llvm/ADT/APFloat.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include <cstdlib>
18 using namespace clang;
19 
20 // TargetInfo Constructor.
21 TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
22   // Set defaults.  Defaults are set for a 32-bit RISC platform,
23   // like PPC or SPARC.
24   // These should be overridden by concrete targets as needed.
25   TLSSupported = true;
26   PointerWidth = PointerAlign = 32;
27   WCharWidth = WCharAlign = 32;
28   IntWidth = IntAlign = 32;
29   LongWidth = LongAlign = 32;
30   LongLongWidth = LongLongAlign = 64;
31   FloatWidth = 32;
32   FloatAlign = 32;
33   DoubleWidth = 64;
34   DoubleAlign = 64;
35   LongDoubleWidth = 64;
36   LongDoubleAlign = 64;
37   IntMaxTWidth = 64;
38   SizeType = UnsignedLong;
39   PtrDiffType = SignedLong;
40   IntMaxType = SignedLongLong;
41   UIntMaxType = UnsignedLongLong;
42   IntPtrType = SignedLong;
43   WCharType = SignedInt;
44   FloatFormat = &llvm::APFloat::IEEEsingle;
45   DoubleFormat = &llvm::APFloat::IEEEdouble;
46   LongDoubleFormat = &llvm::APFloat::IEEEdouble;
47   DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
48                       "i64:64:64-f32:32:32-f64:64:64";
49   UserLabelPrefix = "_";
50 }
51 
52 // Out of line virtual dtor for TargetInfo.
53 TargetInfo::~TargetInfo() {}
54 
55 /// getTypeName - Return the user string for the specified integer type enum.
56 /// For example, SignedShort -> "short".
57 const char *TargetInfo::getTypeName(IntType T) {
58   switch (T) {
59   default: assert(0 && "not an integer!");
60   case SignedShort:      return "short";
61   case UnsignedShort:    return "unsigned short";
62   case SignedInt:        return "int";
63   case UnsignedInt:      return "unsigned int";
64   case SignedLong:       return "long int";
65   case UnsignedLong:     return "long unsigned int";
66   case SignedLongLong:   return "long long int";
67   case UnsignedLongLong: return "long long unsigned int";
68   }
69 }
70 
71 //===----------------------------------------------------------------------===//
72 
73 
74 static void removeGCCRegisterPrefix(const char *&Name) {
75   if (Name[0] == '%' || Name[0] == '#')
76     Name++;
77 }
78 
79 /// isValidGCCRegisterName - Returns whether the passed in string
80 /// is a valid register name according to GCC. This is used by Sema for
81 /// inline asm statements.
82 bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
83   const char * const *Names;
84   unsigned NumNames;
85 
86   // Get rid of any register prefix.
87   removeGCCRegisterPrefix(Name);
88 
89 
90   if (strcmp(Name, "memory") == 0 ||
91       strcmp(Name, "cc") == 0)
92     return true;
93 
94   getGCCRegNames(Names, NumNames);
95 
96   // If we have a number it maps to an entry in the register name array.
97   if (isdigit(Name[0])) {
98     char *End;
99     int n = (int)strtol(Name, &End, 0);
100     if (*End == 0)
101       return n >= 0 && (unsigned)n < NumNames;
102   }
103 
104   // Check register names.
105   for (unsigned i = 0; i < NumNames; i++) {
106     if (strcmp(Name, Names[i]) == 0)
107       return true;
108   }
109 
110   // Now check aliases.
111   const GCCRegAlias *Aliases;
112   unsigned NumAliases;
113 
114   getGCCRegAliases(Aliases, NumAliases);
115   for (unsigned i = 0; i < NumAliases; i++) {
116     for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
117       if (!Aliases[i].Aliases[j])
118         break;
119       if (strcmp(Aliases[i].Aliases[j], Name) == 0)
120         return true;
121     }
122   }
123 
124   return false;
125 }
126 
127 const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
128   assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
129 
130   removeGCCRegisterPrefix(Name);
131 
132   const char * const *Names;
133   unsigned NumNames;
134 
135   getGCCRegNames(Names, NumNames);
136 
137   // First, check if we have a number.
138   if (isdigit(Name[0])) {
139     char *End;
140     int n = (int)strtol(Name, &End, 0);
141     if (*End == 0) {
142       assert(n >= 0 && (unsigned)n < NumNames &&
143              "Out of bounds register number!");
144       return Names[n];
145     }
146   }
147 
148   // Now check aliases.
149   const GCCRegAlias *Aliases;
150   unsigned NumAliases;
151 
152   getGCCRegAliases(Aliases, NumAliases);
153   for (unsigned i = 0; i < NumAliases; i++) {
154     for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
155       if (!Aliases[i].Aliases[j])
156         break;
157       if (strcmp(Aliases[i].Aliases[j], Name) == 0)
158         return Aliases[i].Register;
159     }
160   }
161 
162   return Name;
163 }
164 
165 bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
166   const char *Name = Info.getConstraintStr().c_str();
167   // An output constraint must start with '=' or '+'
168   if (*Name != '=' && *Name != '+')
169     return false;
170 
171   if (*Name == '+')
172     Info.setIsReadWrite();
173 
174   Name++;
175   while (*Name) {
176     switch (*Name) {
177     default:
178       if (!validateAsmConstraint(Name, Info)) {
179         // FIXME: We temporarily return false
180         // so we can add more constraints as we hit it.
181         // Eventually, an unknown constraint should just be treated as 'g'.
182         return false;
183       }
184     case '&': // early clobber.
185       break;
186     case 'r': // general register.
187       Info.setAllowsRegister();
188       break;
189     case 'm': // memory operand.
190       Info.setAllowsMemory();
191       break;
192     case 'g': // general register, memory operand or immediate integer.
193     case 'X': // any operand.
194       Info.setAllowsRegister();
195       Info.setAllowsMemory();
196       break;
197     }
198 
199     Name++;
200   }
201 
202   return true;
203 }
204 
205 bool TargetInfo::resolveSymbolicName(const char *&Name,
206                                      ConstraintInfo *OutputConstraints,
207                                      unsigned NumOutputs,
208                                      unsigned &Index) const {
209   assert(*Name == '[' && "Symbolic name did not start with '['");
210   Name++;
211   const char *Start = Name;
212   while (*Name && *Name != ']')
213     Name++;
214 
215   if (!*Name) {
216     // Missing ']'
217     return false;
218   }
219 
220   std::string SymbolicName(Start, Name - Start);
221 
222   for (Index = 0; Index != NumOutputs; ++Index)
223     if (SymbolicName == OutputConstraints[Index].getName())
224       return true;
225 
226   return false;
227 }
228 
229 bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
230                                          unsigned NumOutputs,
231                                          ConstraintInfo &Info) const {
232   const char *Name = Info.ConstraintStr.c_str();
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;
244 
245         // The constraint should have the same info as the respective
246         // output constraint.
247         Info.setTiedOperand(i, OutputConstraints[i]);
248       } else if (!validateAsmConstraint(Name, Info)) {
249         // FIXME: This error return is in place temporarily so we can
250         // add more constraints as we hit it.  Eventually, an unknown
251         // constraint should just be treated as 'g'.
252         return false;
253       }
254       break;
255     case '[': {
256       unsigned Index = 0;
257       if (!resolveSymbolicName(Name, OutputConstraints, NumOutputs, Index))
258         return false;
259 
260       break;
261     }
262     case '%': // commutative
263       // FIXME: Fail if % is used with the last operand.
264       break;
265     case 'i': // immediate integer.
266     case 'n': // immediate integer with a known value.
267       break;
268     case 'I':  // Various constant constraints with target-specific meanings.
269     case 'J':
270     case 'K':
271     case 'L':
272     case 'M':
273     case 'N':
274     case 'O':
275     case 'P':
276       break;
277     case 'r': // general register.
278       Info.setAllowsRegister();
279       break;
280     case 'm': // memory operand.
281       Info.setAllowsMemory();
282       break;
283     case 'g': // general register, memory operand or immediate integer.
284     case 'X': // any operand.
285       Info.setAllowsRegister();
286       Info.setAllowsMemory();
287       break;
288     }
289 
290     Name++;
291   }
292 
293   return true;
294 }
295