1193326Sed//===--- TargetInfo.cpp - Information about Target machine ----------------===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file implements the TargetInfo and TargetInfoImpl interfaces.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14249423Sdim#include "clang/Basic/TargetInfo.h"
15221345Sdim#include "clang/Basic/AddressSpaces.h"
16249423Sdim#include "clang/Basic/CharInfo.h"
17199482Srdivacky#include "clang/Basic/LangOptions.h"
18193326Sed#include "llvm/ADT/APFloat.h"
19193326Sed#include "llvm/ADT/STLExtras.h"
20226633Sdim#include "llvm/Support/ErrorHandling.h"
21193326Sed#include <cstdlib>
22193326Sedusing namespace clang;
23193326Sed
24221345Sdimstatic const LangAS::Map DefaultAddrSpaceMap = { 0 };
25221345Sdim
26193326Sed// TargetInfo Constructor.
27243830SdimTargetInfo::TargetInfo(const std::string &T) : TargetOpts(), Triple(T)
28243830Sdim{
29207619Srdivacky  // Set defaults.  Defaults are set for a 32-bit RISC platform, like PPC or
30207619Srdivacky  // SPARC.  These should be overridden by concrete targets as needed.
31234353Sdim  BigEndian = true;
32193326Sed  TLSSupported = true;
33207619Srdivacky  NoAsmVariants = false;
34193326Sed  PointerWidth = PointerAlign = 32;
35218893Sdim  BoolWidth = BoolAlign = 8;
36193326Sed  IntWidth = IntAlign = 32;
37193326Sed  LongWidth = LongAlign = 32;
38193326Sed  LongLongWidth = LongLongAlign = 64;
39234353Sdim  SuitableAlign = 64;
40251662Sdim  MinGlobalAlign = 0;
41226633Sdim  HalfWidth = 16;
42226633Sdim  HalfAlign = 16;
43193326Sed  FloatWidth = 32;
44193326Sed  FloatAlign = 32;
45193326Sed  DoubleWidth = 64;
46193326Sed  DoubleAlign = 64;
47193326Sed  LongDoubleWidth = 64;
48193326Sed  LongDoubleAlign = 64;
49210299Sed  LargeArrayMinWidth = 0;
50210299Sed  LargeArrayAlign = 0;
51226633Sdim  MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
52239462Sdim  MaxVectorAlign = 0;
53193326Sed  SizeType = UnsignedLong;
54193326Sed  PtrDiffType = SignedLong;
55193326Sed  IntMaxType = SignedLongLong;
56193326Sed  UIntMaxType = UnsignedLongLong;
57193326Sed  IntPtrType = SignedLong;
58193326Sed  WCharType = SignedInt;
59198398Srdivacky  WIntType = SignedInt;
60198092Srdivacky  Char16Type = UnsignedShort;
61198092Srdivacky  Char32Type = UnsignedInt;
62195341Sed  Int64Type = SignedLongLong;
63199990Srdivacky  SigAtomicType = SignedInt;
64243830Sdim  ProcessIDType = SignedInt;
65234982Sdim  UseSignedCharForObjCBool = true;
66207619Srdivacky  UseBitFieldTypeAlignment = true;
67226633Sdim  UseZeroLengthBitfieldAlignment = false;
68226633Sdim  ZeroLengthBitfieldBoundary = 0;
69226633Sdim  HalfFormat = &llvm::APFloat::IEEEhalf;
70193326Sed  FloatFormat = &llvm::APFloat::IEEEsingle;
71193326Sed  DoubleFormat = &llvm::APFloat::IEEEdouble;
72193326Sed  LongDoubleFormat = &llvm::APFloat::IEEEdouble;
73193326Sed  DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
74199482Srdivacky                      "i64:64:64-f32:32:32-f64:64:64-n32";
75193326Sed  UserLabelPrefix = "_";
76218893Sdim  MCountName = "mcount";
77226633Sdim  RegParmMax = 0;
78226633Sdim  SSERegParmMax = 0;
79208600Srdivacky  HasAlignMac68kSupport = false;
80210299Sed
81210299Sed  // Default to no types using fpret.
82210299Sed  RealTypeUsesObjCFPRet = 0;
83212904Sdim
84234353Sdim  // Default to not using fp2ret for __Complex long double
85234353Sdim  ComplexLongDoubleUsesFP2Ret = false;
86234353Sdim
87212904Sdim  // Default to using the Itanium ABI.
88249423Sdim  TheCXXABI.set(TargetCXXABI::GenericItanium);
89221345Sdim
90221345Sdim  // Default to an empty address space map.
91221345Sdim  AddrSpaceMap = &DefaultAddrSpaceMap;
92221345Sdim
93221345Sdim  // Default to an unknown platform name.
94221345Sdim  PlatformName = "unknown";
95221345Sdim  PlatformMinVersion = VersionTuple();
96193326Sed}
97193326Sed
98193326Sed// Out of line virtual dtor for TargetInfo.
99193326SedTargetInfo::~TargetInfo() {}
100193326Sed
101193326Sed/// getTypeName - Return the user string for the specified integer type enum.
102193326Sed/// For example, SignedShort -> "short".
103193326Sedconst char *TargetInfo::getTypeName(IntType T) {
104193326Sed  switch (T) {
105226633Sdim  default: llvm_unreachable("not an integer!");
106193326Sed  case SignedShort:      return "short";
107193326Sed  case UnsignedShort:    return "unsigned short";
108193326Sed  case SignedInt:        return "int";
109193326Sed  case UnsignedInt:      return "unsigned int";
110193326Sed  case SignedLong:       return "long int";
111193326Sed  case UnsignedLong:     return "long unsigned int";
112193326Sed  case SignedLongLong:   return "long long int";
113193326Sed  case UnsignedLongLong: return "long long unsigned int";
114193326Sed  }
115193326Sed}
116193326Sed
117198398Srdivacky/// getTypeConstantSuffix - Return the constant suffix for the specified
118198398Srdivacky/// integer type enum. For example, SignedLong -> "L".
119198398Srdivackyconst char *TargetInfo::getTypeConstantSuffix(IntType T) {
120198398Srdivacky  switch (T) {
121226633Sdim  default: llvm_unreachable("not an integer!");
122198398Srdivacky  case SignedShort:
123198398Srdivacky  case SignedInt:        return "";
124198398Srdivacky  case SignedLong:       return "L";
125198398Srdivacky  case SignedLongLong:   return "LL";
126198398Srdivacky  case UnsignedShort:
127198398Srdivacky  case UnsignedInt:      return "U";
128198398Srdivacky  case UnsignedLong:     return "UL";
129198398Srdivacky  case UnsignedLongLong: return "ULL";
130198398Srdivacky  }
131198398Srdivacky}
132198398Srdivacky
133218893Sdim/// getTypeWidth - Return the width (in bits) of the specified integer type
134198398Srdivacky/// enum. For example, SignedInt -> getIntWidth().
135198398Srdivackyunsigned TargetInfo::getTypeWidth(IntType T) const {
136198398Srdivacky  switch (T) {
137226633Sdim  default: llvm_unreachable("not an integer!");
138199482Srdivacky  case SignedShort:
139198398Srdivacky  case UnsignedShort:    return getShortWidth();
140199482Srdivacky  case SignedInt:
141198398Srdivacky  case UnsignedInt:      return getIntWidth();
142199482Srdivacky  case SignedLong:
143198398Srdivacky  case UnsignedLong:     return getLongWidth();
144199482Srdivacky  case SignedLongLong:
145198398Srdivacky  case UnsignedLongLong: return getLongLongWidth();
146198398Srdivacky  };
147198398Srdivacky}
148198398Srdivacky
149218893Sdim/// getTypeAlign - Return the alignment (in bits) of the specified integer type
150199482Srdivacky/// enum. For example, SignedInt -> getIntAlign().
151199482Srdivackyunsigned TargetInfo::getTypeAlign(IntType T) const {
152199482Srdivacky  switch (T) {
153226633Sdim  default: llvm_unreachable("not an integer!");
154199482Srdivacky  case SignedShort:
155199482Srdivacky  case UnsignedShort:    return getShortAlign();
156199482Srdivacky  case SignedInt:
157199482Srdivacky  case UnsignedInt:      return getIntAlign();
158199482Srdivacky  case SignedLong:
159199482Srdivacky  case UnsignedLong:     return getLongAlign();
160199482Srdivacky  case SignedLongLong:
161199482Srdivacky  case UnsignedLongLong: return getLongLongAlign();
162199482Srdivacky  };
163199482Srdivacky}
164199482Srdivacky
165198893Srdivacky/// isTypeSigned - Return whether an integer types is signed. Returns true if
166198398Srdivacky/// the type is signed; false otherwise.
167218893Sdimbool TargetInfo::isTypeSigned(IntType T) {
168198398Srdivacky  switch (T) {
169226633Sdim  default: llvm_unreachable("not an integer!");
170198398Srdivacky  case SignedShort:
171198398Srdivacky  case SignedInt:
172198398Srdivacky  case SignedLong:
173218893Sdim  case SignedLongLong:
174198398Srdivacky    return true;
175198398Srdivacky  case UnsignedShort:
176198398Srdivacky  case UnsignedInt:
177198398Srdivacky  case UnsignedLong:
178218893Sdim  case UnsignedLongLong:
179198398Srdivacky    return false;
180198398Srdivacky  };
181198398Srdivacky}
182198398Srdivacky
183199482Srdivacky/// setForcedLangOptions - Set forced language options.
184199482Srdivacky/// Apply changes to the target information with respect to certain
185199482Srdivacky/// language options which change the target configuration.
186199482Srdivackyvoid TargetInfo::setForcedLangOptions(LangOptions &Opts) {
187207619Srdivacky  if (Opts.NoBitFieldTypeAlign)
188207619Srdivacky    UseBitFieldTypeAlignment = false;
189207619Srdivacky  if (Opts.ShortWChar)
190199482Srdivacky    WCharType = UnsignedShort;
191199482Srdivacky}
192198398Srdivacky
193193326Sed//===----------------------------------------------------------------------===//
194193326Sed
195193326Sed
196226633Sdimstatic StringRef removeGCCRegisterPrefix(StringRef Name) {
197193326Sed  if (Name[0] == '%' || Name[0] == '#')
198203955Srdivacky    Name = Name.substr(1);
199218893Sdim
200203955Srdivacky  return Name;
201193326Sed}
202193326Sed
203224145Sdim/// isValidClobber - Returns whether the passed in string is
204224145Sdim/// a valid clobber in an inline asm statement. This is used by
205224145Sdim/// Sema.
206226633Sdimbool TargetInfo::isValidClobber(StringRef Name) const {
207224145Sdim  return (isValidGCCRegisterName(Name) ||
208224145Sdim	  Name == "memory" || Name == "cc");
209224145Sdim}
210224145Sdim
211193326Sed/// isValidGCCRegisterName - Returns whether the passed in string
212193326Sed/// is a valid register name according to GCC. This is used by Sema for
213193326Sed/// inline asm statements.
214226633Sdimbool TargetInfo::isValidGCCRegisterName(StringRef Name) const {
215203955Srdivacky  if (Name.empty())
216203955Srdivacky    return false;
217218893Sdim
218193326Sed  const char * const *Names;
219193326Sed  unsigned NumNames;
220198092Srdivacky
221193326Sed  // Get rid of any register prefix.
222203955Srdivacky  Name = removeGCCRegisterPrefix(Name);
223193326Sed
224193326Sed  getGCCRegNames(Names, NumNames);
225198092Srdivacky
226193326Sed  // If we have a number it maps to an entry in the register name array.
227249423Sdim  if (isDigit(Name[0])) {
228203955Srdivacky    int n;
229203955Srdivacky    if (!Name.getAsInteger(0, n))
230193326Sed      return n >= 0 && (unsigned)n < NumNames;
231193326Sed  }
232193326Sed
233193326Sed  // Check register names.
234193326Sed  for (unsigned i = 0; i < NumNames; i++) {
235203955Srdivacky    if (Name == Names[i])
236193326Sed      return true;
237193326Sed  }
238198092Srdivacky
239224145Sdim  // Check any additional names that we have.
240224145Sdim  const AddlRegName *AddlNames;
241224145Sdim  unsigned NumAddlNames;
242224145Sdim  getGCCAddlRegNames(AddlNames, NumAddlNames);
243224145Sdim  for (unsigned i = 0; i < NumAddlNames; i++)
244224145Sdim    for (unsigned j = 0; j < llvm::array_lengthof(AddlNames[i].Names); j++) {
245224145Sdim      if (!AddlNames[i].Names[j])
246224145Sdim	break;
247224145Sdim      // Make sure the register that the additional name is for is within
248224145Sdim      // the bounds of the register names from above.
249224145Sdim      if (AddlNames[i].Names[j] == Name && AddlNames[i].RegNum < NumNames)
250224145Sdim	return true;
251224145Sdim  }
252224145Sdim
253193326Sed  // Now check aliases.
254193326Sed  const GCCRegAlias *Aliases;
255193326Sed  unsigned NumAliases;
256198092Srdivacky
257193326Sed  getGCCRegAliases(Aliases, NumAliases);
258193326Sed  for (unsigned i = 0; i < NumAliases; i++) {
259193326Sed    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
260193326Sed      if (!Aliases[i].Aliases[j])
261193326Sed        break;
262203955Srdivacky      if (Aliases[i].Aliases[j] == Name)
263193326Sed        return true;
264193326Sed    }
265193326Sed  }
266198092Srdivacky
267193326Sed  return false;
268193326Sed}
269193326Sed
270226633SdimStringRef
271226633SdimTargetInfo::getNormalizedGCCRegisterName(StringRef Name) const {
272193326Sed  assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
273198092Srdivacky
274203955Srdivacky  // Get rid of any register prefix.
275203955Srdivacky  Name = removeGCCRegisterPrefix(Name);
276198092Srdivacky
277193326Sed  const char * const *Names;
278193326Sed  unsigned NumNames;
279193326Sed
280193326Sed  getGCCRegNames(Names, NumNames);
281193326Sed
282193326Sed  // First, check if we have a number.
283249423Sdim  if (isDigit(Name[0])) {
284203955Srdivacky    int n;
285203955Srdivacky    if (!Name.getAsInteger(0, n)) {
286198092Srdivacky      assert(n >= 0 && (unsigned)n < NumNames &&
287193326Sed             "Out of bounds register number!");
288193326Sed      return Names[n];
289193326Sed    }
290193326Sed  }
291198092Srdivacky
292224145Sdim  // Check any additional names that we have.
293224145Sdim  const AddlRegName *AddlNames;
294224145Sdim  unsigned NumAddlNames;
295224145Sdim  getGCCAddlRegNames(AddlNames, NumAddlNames);
296224145Sdim  for (unsigned i = 0; i < NumAddlNames; i++)
297224145Sdim    for (unsigned j = 0; j < llvm::array_lengthof(AddlNames[i].Names); j++) {
298224145Sdim      if (!AddlNames[i].Names[j])
299224145Sdim	break;
300224145Sdim      // Make sure the register that the additional name is for is within
301224145Sdim      // the bounds of the register names from above.
302224145Sdim      if (AddlNames[i].Names[j] == Name && AddlNames[i].RegNum < NumNames)
303224145Sdim	return Name;
304224145Sdim    }
305224145Sdim
306193326Sed  // Now check aliases.
307193326Sed  const GCCRegAlias *Aliases;
308193326Sed  unsigned NumAliases;
309198092Srdivacky
310193326Sed  getGCCRegAliases(Aliases, NumAliases);
311193326Sed  for (unsigned i = 0; i < NumAliases; i++) {
312193326Sed    for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
313193326Sed      if (!Aliases[i].Aliases[j])
314193326Sed        break;
315203955Srdivacky      if (Aliases[i].Aliases[j] == Name)
316193326Sed        return Aliases[i].Register;
317193326Sed    }
318193326Sed  }
319198092Srdivacky
320193326Sed  return Name;
321193326Sed}
322193326Sed
323193326Sedbool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
324193326Sed  const char *Name = Info.getConstraintStr().c_str();
325193326Sed  // An output constraint must start with '=' or '+'
326193326Sed  if (*Name != '=' && *Name != '+')
327193326Sed    return false;
328193326Sed
329193326Sed  if (*Name == '+')
330193326Sed    Info.setIsReadWrite();
331193326Sed
332193326Sed  Name++;
333193326Sed  while (*Name) {
334193326Sed    switch (*Name) {
335193326Sed    default:
336193326Sed      if (!validateAsmConstraint(Name, Info)) {
337193326Sed        // FIXME: We temporarily return false
338193326Sed        // so we can add more constraints as we hit it.
339193326Sed        // Eventually, an unknown constraint should just be treated as 'g'.
340193326Sed        return false;
341193326Sed      }
342193326Sed    case '&': // early clobber.
343193326Sed      break;
344198092Srdivacky    case '%': // commutative.
345198092Srdivacky      // FIXME: Check that there is a another register after this one.
346198092Srdivacky      break;
347193326Sed    case 'r': // general register.
348193326Sed      Info.setAllowsRegister();
349193326Sed      break;
350193326Sed    case 'm': // memory operand.
351218893Sdim    case 'o': // offsetable memory operand.
352218893Sdim    case 'V': // non-offsetable memory operand.
353218893Sdim    case '<': // autodecrement memory operand.
354218893Sdim    case '>': // autoincrement memory operand.
355193326Sed      Info.setAllowsMemory();
356193326Sed      break;
357193326Sed    case 'g': // general register, memory operand or immediate integer.
358193326Sed    case 'X': // any operand.
359193326Sed      Info.setAllowsRegister();
360193326Sed      Info.setAllowsMemory();
361193326Sed      break;
362212904Sdim    case ',': // multiple alternative constraint.  Pass it.
363212904Sdim      // Handle additional optional '=' or '+' modifiers.
364218893Sdim      if (Name[1] == '=' || Name[1] == '+')
365212904Sdim        Name++;
366212904Sdim      break;
367212904Sdim    case '?': // Disparage slightly code.
368218893Sdim    case '!': // Disparage severely.
369243830Sdim    case '#': // Ignore as constraint.
370243830Sdim    case '*': // Ignore for choosing register preferences.
371212904Sdim      break;  // Pass them.
372193326Sed    }
373198092Srdivacky
374193326Sed    Name++;
375193326Sed  }
376198092Srdivacky
377251662Sdim  // If a constraint allows neither memory nor register operands it contains
378251662Sdim  // only modifiers. Reject it.
379251662Sdim  return Info.allowsMemory() || Info.allowsRegister();
380193326Sed}
381193326Sed
382193326Sedbool TargetInfo::resolveSymbolicName(const char *&Name,
383193326Sed                                     ConstraintInfo *OutputConstraints,
384193326Sed                                     unsigned NumOutputs,
385193326Sed                                     unsigned &Index) const {
386193326Sed  assert(*Name == '[' && "Symbolic name did not start with '['");
387193326Sed  Name++;
388193326Sed  const char *Start = Name;
389193326Sed  while (*Name && *Name != ']')
390193326Sed    Name++;
391198092Srdivacky
392193326Sed  if (!*Name) {
393193326Sed    // Missing ']'
394193326Sed    return false;
395193326Sed  }
396198092Srdivacky
397193326Sed  std::string SymbolicName(Start, Name - Start);
398198092Srdivacky
399193326Sed  for (Index = 0; Index != NumOutputs; ++Index)
400193326Sed    if (SymbolicName == OutputConstraints[Index].getName())
401193326Sed      return true;
402193326Sed
403193326Sed  return false;
404193326Sed}
405193326Sed
406193326Sedbool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
407193326Sed                                         unsigned NumOutputs,
408193326Sed                                         ConstraintInfo &Info) const {
409193326Sed  const char *Name = Info.ConstraintStr.c_str();
410193326Sed
411193326Sed  while (*Name) {
412193326Sed    switch (*Name) {
413193326Sed    default:
414193326Sed      // Check if we have a matching constraint
415193326Sed      if (*Name >= '0' && *Name <= '9') {
416193326Sed        unsigned i = *Name - '0';
417198092Srdivacky
418193326Sed        // Check if matching constraint is out of bounds.
419193326Sed        if (i >= NumOutputs)
420193326Sed          return false;
421198092Srdivacky
422218893Sdim        // A number must refer to an output only operand.
423218893Sdim        if (OutputConstraints[i].isReadWrite())
424218893Sdim          return false;
425218893Sdim
426218893Sdim        // If the constraint is already tied, it must be tied to the
427218893Sdim        // same operand referenced to by the number.
428218893Sdim        if (Info.hasTiedOperand() && Info.getTiedOperand() != i)
429218893Sdim          return false;
430218893Sdim
431198092Srdivacky        // The constraint should have the same info as the respective
432193326Sed        // output constraint.
433193326Sed        Info.setTiedOperand(i, OutputConstraints[i]);
434193326Sed      } else if (!validateAsmConstraint(Name, Info)) {
435193326Sed        // FIXME: This error return is in place temporarily so we can
436193326Sed        // add more constraints as we hit it.  Eventually, an unknown
437193326Sed        // constraint should just be treated as 'g'.
438193326Sed        return false;
439193326Sed      }
440193326Sed      break;
441193326Sed    case '[': {
442193326Sed      unsigned Index = 0;
443193326Sed      if (!resolveSymbolicName(Name, OutputConstraints, NumOutputs, Index))
444193326Sed        return false;
445198092Srdivacky
446218893Sdim      // If the constraint is already tied, it must be tied to the
447218893Sdim      // same operand referenced to by the number.
448218893Sdim      if (Info.hasTiedOperand() && Info.getTiedOperand() != Index)
449218893Sdim        return false;
450218893Sdim
451212904Sdim      Info.setTiedOperand(Index, OutputConstraints[Index]);
452193326Sed      break;
453198092Srdivacky    }
454193326Sed    case '%': // commutative
455193326Sed      // FIXME: Fail if % is used with the last operand.
456193326Sed      break;
457193326Sed    case 'i': // immediate integer.
458193326Sed    case 'n': // immediate integer with a known value.
459193326Sed      break;
460193326Sed    case 'I':  // Various constant constraints with target-specific meanings.
461193326Sed    case 'J':
462193326Sed    case 'K':
463193326Sed    case 'L':
464193326Sed    case 'M':
465193326Sed    case 'N':
466193326Sed    case 'O':
467193326Sed    case 'P':
468193326Sed      break;
469193326Sed    case 'r': // general register.
470193326Sed      Info.setAllowsRegister();
471193326Sed      break;
472193326Sed    case 'm': // memory operand.
473218893Sdim    case 'o': // offsettable memory operand.
474218893Sdim    case 'V': // non-offsettable memory operand.
475218893Sdim    case '<': // autodecrement memory operand.
476218893Sdim    case '>': // autoincrement memory operand.
477193326Sed      Info.setAllowsMemory();
478193326Sed      break;
479193326Sed    case 'g': // general register, memory operand or immediate integer.
480193326Sed    case 'X': // any operand.
481193326Sed      Info.setAllowsRegister();
482193326Sed      Info.setAllowsMemory();
483193326Sed      break;
484218893Sdim    case 'E': // immediate floating point.
485218893Sdim    case 'F': // immediate floating point.
486218893Sdim    case 'p': // address operand.
487218893Sdim      break;
488212904Sdim    case ',': // multiple alternative constraint.  Ignore comma.
489212904Sdim      break;
490212904Sdim    case '?': // Disparage slightly code.
491221345Sdim    case '!': // Disparage severely.
492243830Sdim    case '#': // Ignore as constraint.
493243830Sdim    case '*': // Ignore for choosing register preferences.
494212904Sdim      break;  // Pass them.
495193326Sed    }
496198092Srdivacky
497193326Sed    Name++;
498193326Sed  }
499198092Srdivacky
500193326Sed  return true;
501193326Sed}
502249423Sdim
503249423Sdimbool TargetCXXABI::tryParse(llvm::StringRef name) {
504249423Sdim  const Kind unknown = static_cast<Kind>(-1);
505249423Sdim  Kind kind = llvm::StringSwitch<Kind>(name)
506249423Sdim    .Case("arm", GenericARM)
507249423Sdim    .Case("ios", iOS)
508249423Sdim    .Case("itanium", GenericItanium)
509249423Sdim    .Case("microsoft", Microsoft)
510249423Sdim    .Default(unknown);
511249423Sdim  if (kind == unknown) return false;
512249423Sdim
513249423Sdim  set(kind);
514249423Sdim  return true;
515249423Sdim}
516