TargetInfo.cpp revision 2b16165d8ee6a02ede96ae74a46075a1801e68d7
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> 18using namespace clang; 19 20// TargetInfo Constructor. 21TargetInfo::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 CharIsSigned = 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 FloatFormat = &llvm::APFloat::IEEEsingle; 38 DoubleFormat = &llvm::APFloat::IEEEdouble; 39 LongDoubleFormat = &llvm::APFloat::IEEEdouble; 40 DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" 41 "i64:64:64-f32:32:32-f64:64:64"; 42} 43 44// Out of line virtual dtor for TargetInfo. 45TargetInfo::~TargetInfo() {} 46 47//===----------------------------------------------------------------------===// 48 49 50static void removeGCCRegisterPrefix(const char *&Name) { 51 if (Name[0] == '%' || Name[0] == '#') 52 Name++; 53} 54 55/// isValidGCCRegisterName - Returns whether the passed in string 56/// is a valid register name according to GCC. This is used by Sema for 57/// inline asm statements. 58bool TargetInfo::isValidGCCRegisterName(const char *Name) const { 59 const char * const *Names; 60 unsigned NumNames; 61 62 // Get rid of any register prefix. 63 removeGCCRegisterPrefix(Name); 64 65 66 if (strcmp(Name, "memory") == 0 || 67 strcmp(Name, "cc") == 0) 68 return true; 69 70 getGCCRegNames(Names, NumNames); 71 72 // If we have a number it maps to an entry in the register name array. 73 if (isdigit(Name[0])) { 74 char *End; 75 int n = (int)strtol(Name, &End, 0); 76 if (*End == 0) 77 return n >= 0 && (unsigned)n < NumNames; 78 } 79 80 // Check register names. 81 for (unsigned i = 0; i < NumNames; i++) { 82 if (strcmp(Name, Names[i]) == 0) 83 return true; 84 } 85 86 // Now check aliases. 87 const GCCRegAlias *Aliases; 88 unsigned NumAliases; 89 90 getGCCRegAliases(Aliases, NumAliases); 91 for (unsigned i = 0; i < NumAliases; i++) { 92 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) { 93 if (!Aliases[i].Aliases[j]) 94 break; 95 if (strcmp(Aliases[i].Aliases[j], Name) == 0) 96 return true; 97 } 98 } 99 100 return false; 101} 102 103const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const { 104 assert(isValidGCCRegisterName(Name) && "Invalid register passed in"); 105 106 removeGCCRegisterPrefix(Name); 107 108 const char * const *Names; 109 unsigned NumNames; 110 111 getGCCRegNames(Names, NumNames); 112 113 // First, check if we have a number. 114 if (isdigit(Name[0])) { 115 char *End; 116 int n = (int)strtol(Name, &End, 0); 117 if (*End == 0) { 118 assert(n >= 0 && (unsigned)n < NumNames && 119 "Out of bounds register number!"); 120 return Names[n]; 121 } 122 } 123 124 // Now check aliases. 125 const GCCRegAlias *Aliases; 126 unsigned NumAliases; 127 128 getGCCRegAliases(Aliases, NumAliases); 129 for (unsigned i = 0; i < NumAliases; i++) { 130 for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) { 131 if (!Aliases[i].Aliases[j]) 132 break; 133 if (strcmp(Aliases[i].Aliases[j], Name) == 0) 134 return Aliases[i].Register; 135 } 136 } 137 138 return Name; 139} 140 141bool TargetInfo::validateOutputConstraint(const char *Name, 142 ConstraintInfo &info) const 143{ 144 // An output constraint must start with '=' or '+' 145 if (*Name != '=' && *Name != '+') 146 return false; 147 148 if (*Name == '+') 149 info = CI_ReadWrite; 150 else 151 info = CI_None; 152 153 Name++; 154 while (*Name) { 155 switch (*Name) { 156 default: 157 if (!validateAsmConstraint(*Name, info)) { 158 // FIXME: We temporarily return false 159 // so we can add more constraints as we hit it. 160 // Eventually, an unknown constraint should just be treated as 'g'. 161 return false; 162 } 163 case '&': // early clobber. 164 break; 165 case 'r': // general register. 166 info = (ConstraintInfo)(info|CI_AllowsRegister); 167 break; 168 case 'm': // memory operand. 169 info = (ConstraintInfo)(info|CI_AllowsMemory); 170 break; 171 case 'g': // general register, memory operand or immediate integer. 172 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister); 173 break; 174 } 175 176 Name++; 177 } 178 179 return true; 180} 181 182bool TargetInfo::validateInputConstraint(const char *Name, 183 unsigned NumOutputs, 184 ConstraintInfo &info) const { 185 while (*Name) { 186 switch (*Name) { 187 default: 188 // Check if we have a matching constraint 189 if (*Name >= '0' && *Name <= '9') { 190 unsigned i = *Name - '0'; 191 192 // Check if matching constraint is out of bounds. 193 if (i >= NumOutputs) 194 return false; 195 } else if (!validateAsmConstraint(*Name, info)) { 196 // FIXME: This assert is in place temporarily 197 // so we can add more constraints as we hit it. 198 // Eventually, an unknown constraint should just be treated as 'g'. 199 assert(0 && "Unknown input constraint type!"); 200 } 201 case '%': // commutative 202 // FIXME: Fail if % is used with the last operand. 203 break; 204 case 'i': // immediate integer. 205 case 'I': 206 case 'n': // immediate integer with a known value. 207 break; 208 case 'r': // general register. 209 info = (ConstraintInfo)(info|CI_AllowsRegister); 210 break; 211 case 'm': // memory operand. 212 info = (ConstraintInfo)(info|CI_AllowsMemory); 213 break; 214 case 'g': // general register, memory operand or immediate integer. 215 info = (ConstraintInfo)(info|CI_AllowsMemory|CI_AllowsRegister); 216 break; 217 } 218 219 Name++; 220 } 221 222 return true; 223} 224