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   Int64Type = SignedLongLong;
45   FloatFormat = &llvm::APFloat::IEEEsingle;
46   DoubleFormat = &llvm::APFloat::IEEEdouble;
47   LongDoubleFormat = &llvm::APFloat::IEEEdouble;
48   DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
49                       "i64:64:64-f32:32:32-f64:64:64";
50   UserLabelPrefix = "_";
51 }
52 
53 // Out of line virtual dtor for TargetInfo.
54 TargetInfo::~TargetInfo() {}
55 
56 /// getTypeName - Return the user string for the specified integer type enum.
57 /// For example, SignedShort -> "short".
58 const char *TargetInfo::getTypeName(IntType T) {
59   switch (T) {
60   default: assert(0 && "not an integer!");
61   case SignedShort:      return "short";
62   case UnsignedShort:    return "unsigned short";
63   case SignedInt:        return "int";
64   case UnsignedInt:      return "unsigned int";
65   case SignedLong:       return "long int";
66   case UnsignedLong:     return "long unsigned int";
67   case SignedLongLong:   return "long long int";
68   case UnsignedLongLong: return "long long unsigned int";
69   }
70 }
71 
72 //===----------------------------------------------------------------------===//
73 
74 
75 static void removeGCCRegisterPrefix(const char *&Name) {
76   if (Name[0] == '%' || Name[0] == '#')
77     Name++;
78 }
79 
80 /// isValidGCCRegisterName - Returns whether the passed in string
81 /// is a valid register name according to GCC. This is used by Sema for
82 /// inline asm statements.
83 bool TargetInfo::isValidGCCRegisterName(const char *Name) const {
84   const char * const *Names;
85   unsigned NumNames;
86 
87   // Get rid of any register prefix.
88   removeGCCRegisterPrefix(Name);
89 
90 
91   if (strcmp(Name, "memory") == 0 ||
92       strcmp(Name, "cc") == 0)
93     return true;
94 
95   getGCCRegNames(Names, NumNames);
96 
97   // If we have a number it maps to an entry in the register name array.
98   if (isdigit(Name[0])) {
99     char *End;
100     int n = (int)strtol(Name, &End, 0);
101     if (*End == 0)
102       return n >= 0 && (unsigned)n < NumNames;
103   }
104 
105   // Check register names.
106   for (unsigned i = 0; i < NumNames; i++) {
107     if (strcmp(Name, Names[i]) == 0)
108       return true;
109   }
110 
111   // Now check aliases.
112   const GCCRegAlias *Aliases;
113   unsigned NumAliases;
114 
115   getGCCRegAliases(Aliases, NumAliases);
116   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 true;
122     }
123   }
124 
125   return false;
126 }
127 
128 const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const {
129   assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
130 
131   removeGCCRegisterPrefix(Name);
132 
133   const char * const *Names;
134   unsigned NumNames;
135 
136   getGCCRegNames(Names, NumNames);
137 
138   // First, check if we have a number.
139   if (isdigit(Name[0])) {
140     char *End;
141     int n = (int)strtol(Name, &End, 0);
142     if (*End == 0) {
143       assert(n >= 0 && (unsigned)n < NumNames &&
144              "Out of bounds register number!");
145       return Names[n];
146     }
147   }
148 
149   // Now check aliases.
150   const GCCRegAlias *Aliases;
151   unsigned NumAliases;
152 
153   getGCCRegAliases(Aliases, NumAliases);
154   for (unsigned i = 0; i < NumAliases; i++) {
155     for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
156       if (!Aliases[i].Aliases[j])
157         break;
158       if (strcmp(Aliases[i].Aliases[j], Name) == 0)
159         return Aliases[i].Register;
160     }
161   }
162 
163   return Name;
164 }
165 
166 bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
167   const char *Name = Info.getConstraintStr().c_str();
168   // An output constraint must start with '=' or '+'
169   if (*Name != '=' && *Name != '+')
170     return false;
171 
172   if (*Name == '+')
173     Info.setIsReadWrite();
174 
175   Name++;
176   while (*Name) {
177     switch (*Name) {
178     default:
179       if (!validateAsmConstraint(Name, Info)) {
180         // FIXME: We temporarily return false
181         // so we can add more constraints as we hit it.
182         // Eventually, an unknown constraint should just be treated as 'g'.
183         return false;
184       }
185     case '&': // early clobber.
186       break;
187     case 'r': // general register.
188       Info.setAllowsRegister();
189       break;
190     case 'm': // memory operand.
191       Info.setAllowsMemory();
192       break;
193     case 'g': // general register, memory operand or immediate integer.
194     case 'X': // any operand.
195       Info.setAllowsRegister();
196       Info.setAllowsMemory();
197       break;
198     }
199 
200     Name++;
201   }
202 
203   return true;
204 }
205 
206 bool TargetInfo::resolveSymbolicName(const char *&Name,
207                                      ConstraintInfo *OutputConstraints,
208                                      unsigned NumOutputs,
209                                      unsigned &Index) const {
210   assert(*Name == '[' && "Symbolic name did not start with '['");
211   Name++;
212   const char *Start = Name;
213   while (*Name && *Name != ']')
214     Name++;
215 
216   if (!*Name) {
217     // Missing ']'
218     return false;
219   }
220 
221   std::string SymbolicName(Start, Name - Start);
222 
223   for (Index = 0; Index != NumOutputs; ++Index)
224     if (SymbolicName == OutputConstraints[Index].getName())
225       return true;
226 
227   return false;
228 }
229 
230 bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
231                                          unsigned NumOutputs,
232                                          ConstraintInfo &Info) const {
233   const char *Name = Info.ConstraintStr.c_str();
234 
235   while (*Name) {
236     switch (*Name) {
237     default:
238       // Check if we have a matching constraint
239       if (*Name >= '0' && *Name <= '9') {
240         unsigned i = *Name - '0';
241 
242         // Check if matching constraint is out of bounds.
243         if (i >= NumOutputs)
244           return false;
245 
246         // The constraint should have the same info as the respective
247         // output constraint.
248         Info.setTiedOperand(i, OutputConstraints[i]);
249       } else if (!validateAsmConstraint(Name, Info)) {
250         // FIXME: This error return is in place temporarily so we can
251         // add more constraints as we hit it.  Eventually, an unknown
252         // constraint should just be treated as 'g'.
253         return false;
254       }
255       break;
256     case '[': {
257       unsigned Index = 0;
258       if (!resolveSymbolicName(Name, OutputConstraints, NumOutputs, Index))
259         return false;
260 
261       break;
262     }
263     case '%': // commutative
264       // FIXME: Fail if % is used with the last operand.
265       break;
266     case 'i': // immediate integer.
267     case 'n': // immediate integer with a known value.
268       break;
269     case 'I':  // Various constant constraints with target-specific meanings.
270     case 'J':
271     case 'K':
272     case 'L':
273     case 'M':
274     case 'N':
275     case 'O':
276     case 'P':
277       break;
278     case 'r': // general register.
279       Info.setAllowsRegister();
280       break;
281     case 'm': // memory operand.
282       Info.setAllowsMemory();
283       break;
284     case 'g': // general register, memory operand or immediate integer.
285     case 'X': // any operand.
286       Info.setAllowsRegister();
287       Info.setAllowsMemory();
288       break;
289     }
290 
291     Name++;
292   }
293 
294   return true;
295 }
296