diff options
Diffstat (limited to 'lib/Basic/Targets.cpp')
| -rw-r--r-- | lib/Basic/Targets.cpp | 1500 | 
1 files changed, 1500 insertions, 0 deletions
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp new file mode 100644 index 000000000000..4b94bcfc432c --- /dev/null +++ b/lib/Basic/Targets.cpp @@ -0,0 +1,1500 @@ +//===--- Targets.cpp - Implement -arch option and targets -----------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements construction of a TargetInfo object from a +// target triple. +// +//===----------------------------------------------------------------------===// + +// FIXME: Layering violation +#include "clang/AST/Builtins.h" +#include "clang/AST/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallString.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +//  Common code shared among targets. +//===----------------------------------------------------------------------===// + +static void Define(std::vector<char> &Buf, const char *Macro, +                   const char *Val = "1") { +  const char *Def = "#define "; +  Buf.insert(Buf.end(), Def, Def+strlen(Def)); +  Buf.insert(Buf.end(), Macro, Macro+strlen(Macro)); +  Buf.push_back(' '); +  Buf.insert(Buf.end(), Val, Val+strlen(Val)); +  Buf.push_back('\n'); +} + +/// DefineStd - Define a macro name and standard variants.  For example if +/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix" +/// when in GNU mode. +static void DefineStd(std::vector<char> &Buf, const char *MacroName, +                      const LangOptions &Opts) { +  assert(MacroName[0] != '_' && "Identifier should be in the user's namespace"); + +  // If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier +  // in the user's namespace. +  if (Opts.GNUMode) +    Define(Buf, MacroName); + +  // Define __unix. +  llvm::SmallString<20> TmpStr; +  TmpStr = "__"; +  TmpStr += MacroName; +  Define(Buf, TmpStr.c_str()); + +  // Define __unix__. +  TmpStr += "__"; +  Define(Buf, TmpStr.c_str()); +} + +//===----------------------------------------------------------------------===// +// Defines specific to certain operating systems. +//===----------------------------------------------------------------------===// + +static void getSolarisDefines(const LangOptions &Opts, std::vector<char> &Defs) { +  DefineStd(Defs, "sun", Opts); +  DefineStd(Defs, "unix", Opts); +  Define(Defs, "__ELF__"); +  Define(Defs, "__svr4__"); +  Define(Defs, "__SVR4"); +} + +static void getFreeBSDDefines(const LangOptions &Opts, bool is64Bit, +                              const char *Triple, std::vector<char> &Defs) { +  // FreeBSD defines; list based off of gcc output + +  const char *FreeBSD = strstr(Triple, "-freebsd"); +  FreeBSD += strlen("-freebsd"); +  char release[] = "X"; +  release[0] = FreeBSD[0]; +  char version[] = "X00001"; +  version[0] = FreeBSD[0]; + +  Define(Defs, "__FreeBSD__", release); +  Define(Defs, "__FreeBSD_cc_version", version); +  Define(Defs, "__KPRINTF_ATTRIBUTE__"); +  DefineStd(Defs, "unix", Opts); +  Define(Defs, "__ELF__", "1"); +  if (is64Bit) { +    Define(Defs, "__LP64__"); +  } +} + +static void getDragonFlyDefines(const LangOptions &Opts, +                                std::vector<char> &Defs) { +  // DragonFly defines; list based off of gcc output +  Define(Defs, "__DragonFly__"); +  Define(Defs, "__DragonFly_cc_version", "100001"); +  Define(Defs, "__ELF__"); +  Define(Defs, "__KPRINTF_ATTRIBUTE__"); +  Define(Defs, "__tune_i386__"); +  DefineStd(Defs, "unix", Opts); +} + +static void getLinuxDefines(const LangOptions &Opts, std::vector<char> &Defs) { +  // Linux defines; list based off of gcc output +  DefineStd(Defs, "unix", Opts); +  DefineStd(Defs, "linux", Opts); +  Define(Defs, "__gnu_linux__"); +  Define(Defs, "__ELF__", "1"); +} + +/// getDarwinNumber - Parse the 'darwin number' out of the specific targe +/// triple.  For example, if we have darwin8.5 return 8,5,0.  If any entry is +/// not defined, return 0's.  Return true if we have -darwin in the string or +/// false otherwise. +static bool getDarwinNumber(const char *Triple, unsigned &Maj, unsigned &Min, unsigned &Revision) { +  Maj = Min = Revision = 0; +  const char *Darwin = strstr(Triple, "-darwin"); +  if (Darwin == 0) return false; + +  Darwin += strlen("-darwin"); +  if (Darwin[0] < '0' || Darwin[0] > '9') +    return true; + +  Maj = Darwin[0]-'0'; +  ++Darwin; + +  // Handle "darwin11". +  if (Maj == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') { +    Maj = Maj*10 + (Darwin[0] - '0'); +    ++Darwin; +  } + +  // Handle minor version: 10.4.9 -> darwin8.9 -> "1049" +  if (Darwin[0] != '.') +    return true; + +  ++Darwin; +  if (Darwin[0] < '0' || Darwin[0] > '9') +    return true; + +  Min = Darwin[0]-'0'; +  ++Darwin; + +  // Handle 10.4.11 -> darwin8.11 +  if (Min == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') { +    Min = Min*10 + (Darwin[0] - '0'); +    ++Darwin; +  } + +  // Handle revision darwin8.9.1 +  if (Darwin[0] != '.') +    return true; + +  ++Darwin; +  if (Darwin[0] < '0' || Darwin[0] > '9') +    return true; + +  Revision = Darwin[0]-'0'; +  ++Darwin; + +  if (Revision == 1 && Darwin[0] >= '0' && Darwin[0] <= '9') { +    Revision = Revision*10 + (Darwin[0] - '0'); +    ++Darwin; +  } + +  return true; +} + +static void getDarwinDefines(std::vector<char> &Defs, const LangOptions &Opts) { +  Define(Defs, "__APPLE__"); +  Define(Defs, "__MACH__"); +  Define(Defs, "OBJC_NEW_PROPERTIES"); + +  // __weak is always defined, for use in blocks and with objc pointers. +  Define(Defs, "__weak", "__attribute__((objc_gc(weak)))"); + +  // Darwin defines __strong even in C mode (just to nothing). +  if (!Opts.ObjC1 || Opts.getGCMode() == LangOptions::NonGC) +    Define(Defs, "__strong", ""); +  else +    Define(Defs, "__strong", "__attribute__((objc_gc(strong)))"); +} + +static void getDarwinOSXDefines(std::vector<char> &Defs, const char *Triple) { +  // Figure out which "darwin number" the target triple is.  "darwin9" -> 10.5. +  unsigned Maj, Min, Rev; +  if (getDarwinNumber(Triple, Maj, Min, Rev)) { +    char MacOSXStr[] = "1000"; +    if (Maj >= 4 && Maj <= 13) { // 10.0-10.9 +      // darwin7 -> 1030, darwin8 -> 1040, darwin9 -> 1050, etc. +      MacOSXStr[2] = '0' + Maj-4; +    } + +    // Handle minor version: 10.4.9 -> darwin8.9 -> "1049" +    // Cap 10.4.11 -> darwin8.11 -> "1049" +    MacOSXStr[3] = std::min(Min, 9U)+'0'; +    Define(Defs, "__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", MacOSXStr); +  } +} + +static void getDarwinIPhoneOSDefines(std::vector<char> &Defs, +                                     const char *Triple) { +  // Figure out which "darwin number" the target triple is.  "darwin9" -> 10.5. +  unsigned Maj, Min, Rev; +  if (getDarwinNumber(Triple, Maj, Min, Rev)) { +    // When targetting iPhone OS, interpret the minor version and +    // revision as the iPhone OS version +    char iPhoneOSStr[] = "10000"; +    if (Min >= 2 && Min <= 9) { // iPhone OS 2.0-9.0 +      // darwin9.2.0 -> 20000, darwin9.3.0 -> 30000, etc. +      iPhoneOSStr[0] = '0' + Min; +    } + +    // Handle minor version: 2.2 -> darwin9.2.2 -> 20200 +    iPhoneOSStr[2] = std::min(Rev, 9U)+'0'; +    Define(Defs, "__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", +           iPhoneOSStr); +  } +} + +/// GetDarwinLanguageOptions - Set the default language options for darwin. +static void GetDarwinLanguageOptions(LangOptions &Opts, +                                     const char *Triple) { +  Opts.NeXTRuntime = true; + +  unsigned Maj, Min, Rev; +  if (!getDarwinNumber(Triple, Maj, Min, Rev)) +    return; + +  // Blocks default to on for 10.6 (darwin10) and beyond. +  // As does nonfragile-abi for 64bit mode +  if (Maj > 9) +    Opts.Blocks = 1; + +  if (Maj >= 9 && Opts.ObjC1 && !strncmp(Triple, "x86_64", 6)) +    Opts.ObjCNonFragileABI = 1; +} + + +//===----------------------------------------------------------------------===// +// Specific target implementations. +//===----------------------------------------------------------------------===// + +namespace { +// PPC abstract base class +class PPCTargetInfo : public TargetInfo { +  static const Builtin::Info BuiltinInfo[]; +  static const char * const GCCRegNames[]; +  static const TargetInfo::GCCRegAlias GCCRegAliases[]; + +public: +  PPCTargetInfo(const std::string& triple) : TargetInfo(triple) { +    CharIsSigned = false; +  } +  virtual void getTargetBuiltins(const Builtin::Info *&Records, +                                 unsigned &NumRecords) const { +    Records = BuiltinInfo; +    NumRecords = clang::PPC::LastTSBuiltin-Builtin::FirstTSBuiltin; +  } + +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const; + +  virtual const char *getVAListDeclaration() const { +    return "typedef char* __builtin_va_list;"; +    // This is the right definition for ABI/V4: System V.4/eabi. +    /*return "typedef struct __va_list_tag {" +           "  unsigned char gpr;" +           "  unsigned char fpr;" +           "  unsigned short reserved;" +           "  void* overflow_arg_area;" +           "  void* reg_save_area;" +           "} __builtin_va_list[1];";*/ +  } +  virtual const char *getTargetPrefix() const { +    return "ppc"; +  } +  virtual void getGCCRegNames(const char * const *&Names, +                              unsigned &NumNames) const; +  virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, +                                unsigned &NumAliases) const; +  virtual bool validateAsmConstraint(const char *&Name, +                                     TargetInfo::ConstraintInfo &Info) const { +    switch (*Name) { +    default: return false; +    case 'O': // Zero +      return true; +    case 'b': // Base register +    case 'f': // Floating point register +      Info.setAllowsRegister(); +      return true; +    } +  } +  virtual const char *getClobbers() const { +    return ""; +  } +}; + +const Builtin::Info PPCTargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false }, +#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false }, +#include "clang/AST/PPCBuiltins.def" +}; + + +/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific +/// #defines that are not tied to a specific subtarget. +void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, +                                     std::vector<char> &Defs) const { +  // Target identification. +  Define(Defs, "__ppc__"); +  Define(Defs, "_ARCH_PPC"); +  Define(Defs, "__POWERPC__"); +  if (PointerWidth == 64) { +    Define(Defs, "_ARCH_PPC64"); +    Define(Defs, "_LP64"); +    Define(Defs, "__LP64__"); +    Define(Defs, "__ppc64__"); +  } else { +    Define(Defs, "__ppc__"); +  } + +  // Target properties. +  Define(Defs, "_BIG_ENDIAN"); +  Define(Defs, "__BIG_ENDIAN__"); + +  // Subtarget options. +  Define(Defs, "__NATURAL_ALIGNMENT__"); +  Define(Defs, "__REGISTER_PREFIX__", ""); + +  // FIXME: Should be controlled by command line option. +  Define(Defs, "__LONG_DOUBLE_128__"); +} + + +const char * const PPCTargetInfo::GCCRegNames[] = { +  "0", "1", "2", "3", "4", "5", "6", "7", +  "8", "9", "10", "11", "12", "13", "14", "15", +  "16", "17", "18", "19", "20", "21", "22", "23", +  "24", "25", "26", "27", "28", "29", "30", "31", +  "0", "1", "2", "3", "4", "5", "6", "7", +  "8", "9", "10", "11", "12", "13", "14", "15", +  "16", "17", "18", "19", "20", "21", "22", "23", +  "24", "25", "26", "27", "28", "29", "30", "31", +  "mq", "lr", "ctr", "ap", +  "0", "1", "2", "3", "4", "5", "6", "7", +  "xer", +  "0", "1", "2", "3", "4", "5", "6", "7", +  "8", "9", "10", "11", "12", "13", "14", "15", +  "16", "17", "18", "19", "20", "21", "22", "23", +  "24", "25", "26", "27", "28", "29", "30", "31", +  "vrsave", "vscr", +  "spe_acc", "spefscr", +  "sfp" +}; + +void PPCTargetInfo::getGCCRegNames(const char * const *&Names, +                                   unsigned &NumNames) const { +  Names = GCCRegNames; +  NumNames = llvm::array_lengthof(GCCRegNames); +} + +const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = { +  // While some of these aliases do map to different registers +  // they still share the same register name. +  { { "cc", "cr0", "fr0", "r0", "v0"}, "0" }, +  { { "cr1", "fr1", "r1", "sp", "v1"}, "1" }, +  { { "cr2", "fr2", "r2", "toc", "v2"}, "2" }, +  { { "cr3", "fr3", "r3", "v3"}, "3" }, +  { { "cr4", "fr4", "r4", "v4"}, "4" }, +  { { "cr5", "fr5", "r5", "v5"}, "5" }, +  { { "cr6", "fr6", "r6", "v6"}, "6" }, +  { { "cr7", "fr7", "r7", "v7"}, "7" }, +  { { "fr8", "r8", "v8"}, "8" }, +  { { "fr9", "r9", "v9"}, "9" }, +  { { "fr10", "r10", "v10"}, "10" }, +  { { "fr11", "r11", "v11"}, "11" }, +  { { "fr12", "r12", "v12"}, "12" }, +  { { "fr13", "r13", "v13"}, "13" }, +  { { "fr14", "r14", "v14"}, "14" }, +  { { "fr15", "r15", "v15"}, "15" }, +  { { "fr16", "r16", "v16"}, "16" }, +  { { "fr17", "r17", "v17"}, "17" }, +  { { "fr18", "r18", "v18"}, "18" }, +  { { "fr19", "r19", "v19"}, "19" }, +  { { "fr20", "r20", "v20"}, "20" }, +  { { "fr21", "r21", "v21"}, "21" }, +  { { "fr22", "r22", "v22"}, "22" }, +  { { "fr23", "r23", "v23"}, "23" }, +  { { "fr24", "r24", "v24"}, "24" }, +  { { "fr25", "r25", "v25"}, "25" }, +  { { "fr26", "r26", "v26"}, "26" }, +  { { "fr27", "r27", "v27"}, "27" }, +  { { "fr28", "r28", "v28"}, "28" }, +  { { "fr29", "r29", "v29"}, "29" }, +  { { "fr30", "r30", "v30"}, "30" }, +  { { "fr31", "r31", "v31"}, "31" }, +}; + +void PPCTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, +                                     unsigned &NumAliases) const { +  Aliases = GCCRegAliases; +  NumAliases = llvm::array_lengthof(GCCRegAliases); +} +} // end anonymous namespace. + +namespace { +class PPC32TargetInfo : public PPCTargetInfo { +public: +  PPC32TargetInfo(const std::string& triple) : PPCTargetInfo(triple) { +    DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" +                        "i64:64:64-f32:32:32-f64:64:64-v128:128:128"; +  } +}; +} // end anonymous namespace. + +namespace { +class PPC64TargetInfo : public PPCTargetInfo { +public: +  PPC64TargetInfo(const std::string& triple) : PPCTargetInfo(triple) { +    LongWidth = LongAlign = PointerWidth = PointerAlign = 64; +    DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" +                        "i64:64:64-f32:32:32-f64:64:64-v128:128:128"; +  } +}; +} // end anonymous namespace. + + +namespace { +class DarwinPPCTargetInfo : public PPC32TargetInfo { +public: +  DarwinPPCTargetInfo(const std::string& triple) : PPC32TargetInfo(triple) {} +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    PPC32TargetInfo::getTargetDefines(Opts, Defines); +    getDarwinDefines(Defines, Opts); +    getDarwinOSXDefines(Defines, getTargetTriple()); +  } + +  /// getDefaultLangOptions - Allow the target to specify default settings for +  /// various language options.  These may be overridden by command line +  /// options. +  virtual void getDefaultLangOptions(LangOptions &Opts) { +    GetDarwinLanguageOptions(Opts, getTargetTriple()); +  } +}; +} // end anonymous namespace. + +namespace { +class DarwinPPC64TargetInfo : public PPC64TargetInfo { +public: +  DarwinPPC64TargetInfo(const std::string& triple) : PPC64TargetInfo(triple) {} +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    PPC64TargetInfo::getTargetDefines(Opts, Defines); +    getDarwinDefines(Defines, Opts); +    getDarwinOSXDefines(Defines, getTargetTriple()); +  } + +  /// getDefaultLangOptions - Allow the target to specify default settings for +  /// various language options.  These may be overridden by command line +  /// options. +  virtual void getDefaultLangOptions(LangOptions &Opts) { +    GetDarwinLanguageOptions(Opts, getTargetTriple()); +  } +}; +} // end anonymous namespace. + +namespace { +// Namespace for x86 abstract base class +const Builtin::Info BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false }, +#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false }, +#include "clang/AST/X86Builtins.def" +}; + +const char *GCCRegNames[] = { +  "ax", "dx", "cx", "bx", "si", "di", "bp", "sp", +  "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", +  "argp", "flags", "fspr", "dirflag", "frame", +  "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", +  "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", +  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", +  "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" +}; + +const TargetInfo::GCCRegAlias GCCRegAliases[] = { +  { { "al", "ah", "eax", "rax" }, "ax" }, +  { { "bl", "bh", "ebx", "rbx" }, "bx" }, +  { { "cl", "ch", "ecx", "rcx" }, "cx" }, +  { { "dl", "dh", "edx", "rdx" }, "dx" }, +  { { "esi", "rsi" }, "si" }, +  { { "edi", "rdi" }, "di" }, +  { { "esp", "rsp" }, "sp" }, +  { { "ebp", "rbp" }, "bp" }, +}; + +// X86 target abstract base class; x86-32 and x86-64 are very close, so +// most of the implementation can be shared. +class X86TargetInfo : public TargetInfo { +  enum X86SSEEnum { +    NoMMXSSE, MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42 +  } SSELevel; +public: +  X86TargetInfo(const std::string& triple) +    : TargetInfo(triple), SSELevel(NoMMXSSE) { +    LongDoubleFormat = &llvm::APFloat::x87DoubleExtended; +  } +  virtual void getTargetBuiltins(const Builtin::Info *&Records, +                                 unsigned &NumRecords) const { +    Records = BuiltinInfo; +    NumRecords = clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin; +  } +  virtual const char *getTargetPrefix() const { +    return "x86"; +  } +  virtual void getGCCRegNames(const char * const *&Names, +                              unsigned &NumNames) const { +    Names = GCCRegNames; +    NumNames = llvm::array_lengthof(GCCRegNames); +  } +  virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, +                                unsigned &NumAliases) const { +    Aliases = GCCRegAliases; +    NumAliases = llvm::array_lengthof(GCCRegAliases); +  } +  virtual bool validateAsmConstraint(const char *&Name, +                                     TargetInfo::ConstraintInfo &info) const; +  virtual std::string convertConstraint(const char Constraint) const; +  virtual const char *getClobbers() const { +    return "~{dirflag},~{fpsr},~{flags}"; +  } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const; +  virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features, +                                 const std::string &Name, +                                 bool Enabled) const; +  virtual void getDefaultFeatures(const std::string &CPU,  +                                  llvm::StringMap<bool> &Features) const; +  virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features); +}; + +void X86TargetInfo::getDefaultFeatures(const std::string &CPU,  +                                       llvm::StringMap<bool> &Features) const { +  // FIXME: This should not be here. +  Features["3dnow"] = false; +  Features["3dnowa"] = false; +  Features["mmx"] = false; +  Features["sse"] = false; +  Features["sse2"] = false; +  Features["sse3"] = false; +  Features["ssse3"] = false; +  Features["sse41"] = false; +  Features["sse42"] = false; + +  // LLVM does not currently recognize this. +  // Features["sse4a"] = false; + +  // FIXME: This *really* should not be here. + +  // X86_64 always has SSE2. +  if (PointerWidth == 64) +    Features["sse2"] = Features["sse"] = Features["mmx"] = true; + +  if (CPU == "generic" || CPU == "i386" || CPU == "i486" || CPU == "i586" || +      CPU == "pentium" || CPU == "i686" || CPU == "pentiumpro") +    ; +  else if (CPU == "pentium-mmx" || CPU == "pentium2") +    setFeatureEnabled(Features, "mmx", true); +  else if (CPU == "pentium3") +    setFeatureEnabled(Features, "sse", true); +  else if (CPU == "pentium-m" || CPU == "pentium4" || CPU == "x86-64") +    setFeatureEnabled(Features, "sse2", true); +  else if (CPU == "yonah" || CPU == "prescott" || CPU == "nocona") +    setFeatureEnabled(Features, "sse3", true); +  else if (CPU == "core2") +    setFeatureEnabled(Features, "ssse3", true); +  else if (CPU == "penryn") { +    setFeatureEnabled(Features, "sse4", true); +    Features["sse42"] = false; +  } else if (CPU == "atom") +    setFeatureEnabled(Features, "sse3", true); +  else if (CPU == "corei7") +    setFeatureEnabled(Features, "sse4", true); +  else if (CPU == "k6" || CPU == "winchip-c6") +    setFeatureEnabled(Features, "mmx", true); +  else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" ||  +           CPU == "athlon-tbird" || CPU == "winchip2" || CPU == "c3") { +    setFeatureEnabled(Features, "mmx", true); +    setFeatureEnabled(Features, "3dnow", true); +  } else if (CPU == "athlon-4" || CPU == "athlon-xp" || CPU == "athlon-mp") { +    setFeatureEnabled(Features, "sse", true); +    setFeatureEnabled(Features, "3dnowa", true); +  } else if (CPU == "k8" || CPU == "opteron" || CPU == "athlon64" || +           CPU == "athlon-fx") { +    setFeatureEnabled(Features, "sse2", true);  +    setFeatureEnabled(Features, "3dnowa", true); +  } else if (CPU == "c3-2") +    setFeatureEnabled(Features, "sse", true); +} + +bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, +                                      const std::string &Name,  +                                      bool Enabled) const { +  // FIXME: This *really* should not be here. +  if (!Features.count(Name) && Name != "sse4") +    return false; + +  if (Enabled) { +    if (Name == "mmx") +      Features["mmx"] = true; +    else if (Name == "sse") +      Features["mmx"] = Features["sse"] = true; +    else if (Name == "sse2") +      Features["mmx"] = Features["sse"] = Features["sse2"] = true; +    else if (Name == "sse3") +      Features["mmx"] = Features["sse"] = Features["sse2"] =  +        Features["sse3"] = true; +    else if (Name == "ssse3") +      Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =  +        Features["ssse3"] = true; +    else if (Name == "sse4") +      Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =  +        Features["ssse3"] = Features["sse41"] = Features["sse42"] = true; +    else if (Name == "3dnow") +      Features["3dnowa"] = true; +    else if (Name == "3dnowa") +      Features["3dnow"] = Features["3dnowa"] = true; +  } else { +    if (Name == "mmx") +      Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =  +        Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; +    else if (Name == "sse") +      Features["sse"] = Features["sse2"] = Features["sse3"] =  +        Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; +    else if (Name == "sse2") +      Features["sse2"] = Features["sse3"] = Features["ssse3"] =  +        Features["sse41"] = Features["sse42"] = false; +    else if (Name == "sse3") +      Features["sse3"] = Features["ssse3"] = Features["sse41"] =  +        Features["sse42"] = false; +    else if (Name == "ssse3") +      Features["ssse3"] = Features["sse41"] = Features["sse42"] = false; +    else if (Name == "sse4") +      Features["sse41"] = Features["sse42"] = false; +    else if (Name == "3dnow") +      Features["3dnow"] = Features["3dnowa"] = false; +    else if (Name == "3dnowa") +      Features["3dnowa"] = false; +  } + +  return true; +} + +/// HandleTargetOptions - Perform initialization based on the user +/// configured set of features. +void X86TargetInfo::HandleTargetFeatures(const llvm::StringMap<bool>&Features) { +  if (Features.lookup("sse42")) +    SSELevel = SSE42; +  else if (Features.lookup("sse41")) +    SSELevel = SSE41; +  else if (Features.lookup("ssse3")) +    SSELevel = SSSE3; +  else if (Features.lookup("sse3")) +    SSELevel = SSE3; +  else if (Features.lookup("sse2")) +    SSELevel = SSE2; +  else if (Features.lookup("sse")) +    SSELevel = SSE1; +  else if (Features.lookup("mmx")) +    SSELevel = MMX; +} + +/// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines +/// that are not tied to a specific subtarget. +void X86TargetInfo::getTargetDefines(const LangOptions &Opts, +                                     std::vector<char> &Defs) const { +  // Target identification. +  if (PointerWidth == 64) { +    Define(Defs, "_LP64"); +    Define(Defs, "__LP64__"); +    Define(Defs, "__amd64__"); +    Define(Defs, "__amd64"); +    Define(Defs, "__x86_64"); +    Define(Defs, "__x86_64__"); +  } else { +    DefineStd(Defs, "i386", Opts); +  } + +  // Target properties. +  Define(Defs, "__LITTLE_ENDIAN__"); + +  // Subtarget options. +  Define(Defs, "__nocona"); +  Define(Defs, "__nocona__"); +  Define(Defs, "__tune_nocona__"); +  Define(Defs, "__REGISTER_PREFIX__", ""); + +  // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline +  // functions in glibc header files that use FP Stack inline asm which the +  // backend can't deal with (PR879). +  Define(Defs, "__NO_MATH_INLINES"); + +  // Each case falls through to the previous one here. +  switch (SSELevel) { +  case SSE42: +    Define(Defs, "__SSE4_2__"); +  case SSE41: +    Define(Defs, "__SSE4_1__"); +  case SSSE3: +    Define(Defs, "__SSSE3__"); +  case SSE3: +    Define(Defs, "__SSE3__"); +  case SSE2: +    Define(Defs, "__SSE2__"); +    Define(Defs, "__SSE2_MATH__");  // -mfp-math=sse always implied. +  case SSE1: +    Define(Defs, "__SSE__"); +    Define(Defs, "__SSE_MATH__");   // -mfp-math=sse always implied. +  case MMX: +    Define(Defs, "__MMX__"); +  case NoMMXSSE: +    break; +  } +} + + +bool +X86TargetInfo::validateAsmConstraint(const char *&Name, +                                     TargetInfo::ConstraintInfo &Info) const { +  switch (*Name) { +  default: return false; +  case 'a': // eax. +  case 'b': // ebx. +  case 'c': // ecx. +  case 'd': // edx. +  case 'S': // esi. +  case 'D': // edi. +  case 'A': // edx:eax. +  case 't': // top of floating point stack. +  case 'u': // second from top of floating point stack. +  case 'q': // Any register accessible as [r]l: a, b, c, and d. +  case 'y': // Any MMX register. +  case 'x': // Any SSE register. +  case 'Q': // Any register accessible as [r]h: a, b, c, and d. +  case 'e': // 32-bit signed integer constant for use with zero-extending +            // x86_64 instructions. +  case 'Z': // 32-bit unsigned integer constant for use with zero-extending +            // x86_64 instructions. +  case 'N': // unsigned 8-bit integer constant for use with in and out +            // instructions. +    Info.setAllowsRegister(); +    return true; +  } +} + +std::string +X86TargetInfo::convertConstraint(const char Constraint) const { +  switch (Constraint) { +  case 'a': return std::string("{ax}"); +  case 'b': return std::string("{bx}"); +  case 'c': return std::string("{cx}"); +  case 'd': return std::string("{dx}"); +  case 'S': return std::string("{si}"); +  case 'D': return std::string("{di}"); +  case 't': // top of floating point stack. +    return std::string("{st}"); +  case 'u': // second from top of floating point stack. +    return std::string("{st(1)}"); // second from top of floating point stack. +  default: +    return std::string(1, Constraint); +  } +} +} // end anonymous namespace + +namespace { +// X86-32 generic target +class X86_32TargetInfo : public X86TargetInfo { +public: +  X86_32TargetInfo(const std::string& triple) : X86TargetInfo(triple) { +    DoubleAlign = LongLongAlign = 32; +    LongDoubleWidth = 96; +    LongDoubleAlign = 32; +    DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" +                        "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-" +                        "a0:0:64-f80:32:32"; +    SizeType = UnsignedInt; +    PtrDiffType = SignedInt; +    IntPtrType = SignedInt; +    RegParmMax = 3; +  } +  virtual const char *getVAListDeclaration() const { +    return "typedef char* __builtin_va_list;"; +  } +}; +} // end anonymous namespace + +namespace { +// x86-32 Darwin (OS X) target +class DarwinI386TargetInfo : public X86_32TargetInfo { +public: +  DarwinI386TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) { +    LongDoubleWidth = 128; +    LongDoubleAlign = 128; +    SizeType = UnsignedLong; +    IntPtrType = SignedLong; +    DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" +                        "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-" +                        "a0:0:64-f80:128:128"; +    TLSSupported = false; +  } + +  virtual const char *getStringSymbolPrefix(bool IsConstant) const { +    return IsConstant ? "\01LC" : "\01lC"; +  } + +  virtual const char *getUnicodeStringSymbolPrefix() const { +    return "__utf16_string_"; +  } + +  virtual const char *getUnicodeStringSection() const { +    return "__TEXT,__ustring"; +  } + +  virtual const char *getCFStringSymbolPrefix() const { +    return "\01LC"; +  } + +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_32TargetInfo::getTargetDefines(Opts, Defines); +    getDarwinDefines(Defines, Opts); +    getDarwinOSXDefines(Defines, getTargetTriple()); +  } + +  /// getDefaultLangOptions - Allow the target to specify default settings for +  /// various language options.  These may be overridden by command line +  /// options. +  virtual void getDefaultLangOptions(LangOptions &Opts) { +    GetDarwinLanguageOptions(Opts, getTargetTriple()); +  } +}; +} // end anonymous namespace + +namespace { +// x86-32 FreeBSD target +class FreeBSDX86_32TargetInfo : public X86_32TargetInfo { +public: +  FreeBSDX86_32TargetInfo(const std::string& triple) : +      X86_32TargetInfo(triple) { } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_32TargetInfo::getTargetDefines(Opts, Defines); +    getFreeBSDDefines(Opts, 0, getTargetTriple(), Defines); +  } +}; +} // end anonymous namespace + +namespace { +// x86-32 DragonFly target +class DragonFlyX86_32TargetInfo : public X86_32TargetInfo { +public: +  DragonFlyX86_32TargetInfo(const std::string& triple) : +      X86_32TargetInfo(triple) { } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_32TargetInfo::getTargetDefines(Opts, Defines); +    getDragonFlyDefines(Opts, Defines); +  } +}; +} // end anonymous namespace + +namespace { +// x86-32 Linux target +class LinuxX86_32TargetInfo : public X86_32TargetInfo { +public: +  LinuxX86_32TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) { +    UserLabelPrefix = ""; +  } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_32TargetInfo::getTargetDefines(Opts, Defines); +    getLinuxDefines(Opts, Defines); +  } +}; +} // end anonymous namespace + +namespace { +// x86-32 Solaris target +class SolarisX86_32TargetInfo : public X86_32TargetInfo { +public: +  SolarisX86_32TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) { +    UserLabelPrefix = ""; +    WCharType = SignedLong; +    // FIXME: WIntType should be SignedLong +  } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_32TargetInfo::getTargetDefines(Opts, Defines); +    getSolarisDefines(Opts, Defines); +  } +}; +} // end anonymous namespace + + +namespace { +// x86-32 Windows target +class WindowsX86_32TargetInfo : public X86_32TargetInfo { +public: +  WindowsX86_32TargetInfo(const std::string& triple) +    : X86_32TargetInfo(triple) { +    TLSSupported = false; +    // FIXME: Fix wchar_t. +    // FIXME: We should probably enable -fms-extensions by default for +    // this target. +  } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_32TargetInfo::getTargetDefines(Opts, Defines); +    // This list is based off of the the list of things MingW defines +    Define(Defines, "_WIN32"); +    DefineStd(Defines, "WIN32", Opts); +    DefineStd(Defines, "WINNT", Opts); +    Define(Defines, "_X86_"); +    Define(Defines, "__MSVCRT__"); +  } +}; +} // end anonymous namespace + +namespace { +// x86-64 generic target +class X86_64TargetInfo : public X86TargetInfo { +public: +  X86_64TargetInfo(const std::string &triple) : X86TargetInfo(triple) { +    LongWidth = LongAlign = PointerWidth = PointerAlign = 64; +    DoubleAlign = LongLongAlign = 64; +    LongDoubleWidth = 128; +    LongDoubleAlign = 128; +    IntMaxType = SignedLong; +    UIntMaxType = UnsignedLong; +    RegParmMax = 6; + +    DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" +                        "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" +                        "a0:0:64-f80:128:128"; +  } +  virtual const char *getVAListDeclaration() const { +    return "typedef struct __va_list_tag {" +           "  unsigned gp_offset;" +           "  unsigned fp_offset;" +           "  void* overflow_arg_area;" +           "  void* reg_save_area;" +           "} __builtin_va_list[1];"; +  } +}; +} // end anonymous namespace + +namespace { +// x86-64 FreeBSD target +class FreeBSDX86_64TargetInfo : public X86_64TargetInfo { +public: +  FreeBSDX86_64TargetInfo(const std::string &triple) +    : X86_64TargetInfo(triple) {} +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_64TargetInfo::getTargetDefines(Opts, Defines); +    getFreeBSDDefines(Opts, 1, getTargetTriple(), Defines); +  } +}; +} // end anonymous namespace + +namespace { +// x86-64 Linux target +class LinuxX86_64TargetInfo : public X86_64TargetInfo { +public: +  LinuxX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) { +    UserLabelPrefix = ""; +  } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_64TargetInfo::getTargetDefines(Opts, Defines); +    getLinuxDefines(Opts, Defines); +  } +}; +} // end anonymous namespace + +namespace { +// x86-64 Solaris target +class SolarisX86_64TargetInfo : public X86_64TargetInfo { +public: +  SolarisX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) { +    UserLabelPrefix = ""; +  } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_64TargetInfo::getTargetDefines(Opts, Defines); +    getSolarisDefines(Opts, Defines); +  } +}; +} // end anonymous namespace + +namespace { +// x86-64 Darwin (OS X) target +class DarwinX86_64TargetInfo : public X86_64TargetInfo { +public: +  DarwinX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) { +    TLSSupported = false; +  } + +  virtual const char *getStringSymbolPrefix(bool IsConstant) const { +    return IsConstant ? "\01LC" : "\01lC"; +  } + +  virtual const char *getUnicodeStringSymbolPrefix() const { +    return "__utf16_string_"; +  } + +  virtual const char *getUnicodeStringSection() const { +    return "__TEXT,__ustring"; +  } + +  virtual const char *getCFStringSymbolPrefix() const { +    return "\01L_unnamed_cfstring_"; +  } + +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    X86_64TargetInfo::getTargetDefines(Opts, Defines); +    getDarwinDefines(Defines, Opts); +    getDarwinOSXDefines(Defines, getTargetTriple()); +  } + +  /// getDefaultLangOptions - Allow the target to specify default settings for +  /// various language options.  These may be overridden by command line +  /// options. +  virtual void getDefaultLangOptions(LangOptions &Opts) { +    GetDarwinLanguageOptions(Opts, getTargetTriple()); +  } +}; +} // end anonymous namespace. + +namespace { +class ARMTargetInfo : public TargetInfo { +  enum { +    Armv4t, +    Armv5, +    Armv6, +    XScale +  } ArmArch; +public: +  ARMTargetInfo(const std::string& triple) : TargetInfo(triple) { +    // FIXME: Are the defaults correct for ARM? +    DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" +                        "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:64"; +    if (triple.find("arm-") == 0 || triple.find("armv6-") == 0) +      ArmArch = Armv6; +    else if (triple.find("armv5-") == 0) +      ArmArch = Armv5; +    else if (triple.find("armv4t-") == 0) +      ArmArch = Armv4t; +    else if (triple.find("xscale-") == 0) +      ArmArch = XScale; +    else if (triple.find("armv") == 0) { +      // FIXME: fuzzy match for other random weird arm triples.  This is useful +      // for the static analyzer and other clients, but probably should be +      // re-evaluated when codegen is brought up. +      ArmArch = Armv6; +    } +  } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defs) const { +    // Target identification. +    Define(Defs, "__arm"); +    Define(Defs, "__arm__"); + +    // Target properties. +    Define(Defs, "__LITTLE_ENDIAN__"); + +    // Subtarget options. +    if (ArmArch == Armv6) { +      Define(Defs, "__ARM_ARCH_6K__"); +      Define(Defs, "__THUMB_INTERWORK__"); +    } else if (ArmArch == Armv5) { +      Define(Defs, "__ARM_ARCH_5TEJ__"); +      Define(Defs, "__THUMB_INTERWORK__"); +      Define(Defs, "__SOFTFP__"); +    } else if (ArmArch == Armv4t) { +      Define(Defs, "__ARM_ARCH_4T__"); +      Define(Defs, "__SOFTFP__"); +    } else if (ArmArch == XScale) { +      Define(Defs, "__ARM_ARCH_5TE__"); +      Define(Defs, "__XSCALE__"); +      Define(Defs, "__SOFTFP__"); +    } +    Define(Defs, "__ARMEL__"); +    Define(Defs, "__APCS_32__"); +    Define(Defs, "__VFP_FP__"); +  } +  virtual void getTargetBuiltins(const Builtin::Info *&Records, +                                 unsigned &NumRecords) const { +    // FIXME: Implement. +    Records = 0; +    NumRecords = 0; +  } +  virtual const char *getVAListDeclaration() const { +    return "typedef char* __builtin_va_list;"; +  } +  virtual const char *getTargetPrefix() const { +    return "arm"; +  } +  virtual void getGCCRegNames(const char * const *&Names, +                              unsigned &NumNames) const { +    // FIXME: Implement. +    Names = 0; +    NumNames = 0; +  } +  virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, +                                unsigned &NumAliases) const { +    // FIXME: Implement. +    Aliases = 0; +    NumAliases = 0; +  } +  virtual bool validateAsmConstraint(const char *&Name, +                                     TargetInfo::ConstraintInfo &Info) const { +    // FIXME: Check if this is complete +    switch (*Name) { +    default: +    case 'l': // r0-r7 +    case 'h': // r8-r15 +    case 'w': // VFP Floating point register single precision +    case 'P': // VFP Floating point register double precision +      Info.setAllowsRegister(); +      return true; +    } +    return false; +  } +  virtual const char *getClobbers() const { +    // FIXME: Is this really right? +    return ""; +  } +}; +} // end anonymous namespace. + + +namespace { +class DarwinARMTargetInfo : public ARMTargetInfo { +public: +  DarwinARMTargetInfo(const std::string& triple) : ARMTargetInfo(triple) { +    TLSSupported = false; +  } + +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    ARMTargetInfo::getTargetDefines(Opts, Defines); +    getDarwinDefines(Defines, Opts); +    getDarwinIPhoneOSDefines(Defines, getTargetTriple()); +  } +}; +} // end anonymous namespace. + +namespace { +// arm FreeBSD target +class FreeBSDARMTargetInfo : public ARMTargetInfo { +public: +  FreeBSDARMTargetInfo(const std::string& triple) : ARMTargetInfo(triple) {} +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    ARMTargetInfo::getTargetDefines(Opts, Defines); +    getFreeBSDDefines(Opts, 0, getTargetTriple(), Defines); +  } +}; +} // end anonymous namespace + +namespace { +class SparcV8TargetInfo : public TargetInfo { +  static const TargetInfo::GCCRegAlias GCCRegAliases[]; +  static const char * const GCCRegNames[]; +public: +  SparcV8TargetInfo(const std::string& triple) : TargetInfo(triple) { +    // FIXME: Support Sparc quad-precision long double? +    DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" +                        "i64:64:64-f32:32:32-f64:64:64-v64:64:64"; +  } +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    DefineStd(Defines, "sparc", Opts); +    Define(Defines, "__sparcv8"); +    Define(Defines, "__REGISTER_PREFIX__", ""); +  } +  virtual void getTargetBuiltins(const Builtin::Info *&Records, +                                 unsigned &NumRecords) const { +    // FIXME: Implement! +  } +  virtual const char *getVAListDeclaration() const { +    return "typedef void* __builtin_va_list;"; +  } +  virtual const char *getTargetPrefix() const { +    return "sparc"; +  } +  virtual void getGCCRegNames(const char * const *&Names, +                              unsigned &NumNames) const; +  virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, +                                unsigned &NumAliases) const; +  virtual bool validateAsmConstraint(const char *&Name, +                                     TargetInfo::ConstraintInfo &info) const { +    // FIXME: Implement! +    return false; +  } +  virtual const char *getClobbers() const { +    // FIXME: Implement! +    return ""; +  } +}; + +const char * const SparcV8TargetInfo::GCCRegNames[] = { +  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", +  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", +  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", +  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" +}; + +void SparcV8TargetInfo::getGCCRegNames(const char * const *&Names, +                                       unsigned &NumNames) const { +  Names = GCCRegNames; +  NumNames = llvm::array_lengthof(GCCRegNames); +} + +const TargetInfo::GCCRegAlias SparcV8TargetInfo::GCCRegAliases[] = { +  { { "g0" }, "r0" }, +  { { "g1" }, "r1" }, +  { { "g2" }, "r2" }, +  { { "g3" }, "r3" }, +  { { "g4" }, "r4" }, +  { { "g5" }, "r5" }, +  { { "g6" }, "r6" }, +  { { "g7" }, "r7" }, +  { { "o0" }, "r8" }, +  { { "o1" }, "r9" }, +  { { "o2" }, "r10" }, +  { { "o3" }, "r11" }, +  { { "o4" }, "r12" }, +  { { "o5" }, "r13" }, +  { { "o6", "sp" }, "r14" }, +  { { "o7" }, "r15" }, +  { { "l0" }, "r16" }, +  { { "l1" }, "r17" }, +  { { "l2" }, "r18" }, +  { { "l3" }, "r19" }, +  { { "l4" }, "r20" }, +  { { "l5" }, "r21" }, +  { { "l6" }, "r22" }, +  { { "l7" }, "r23" }, +  { { "i0" }, "r24" }, +  { { "i1" }, "r25" }, +  { { "i2" }, "r26" }, +  { { "i3" }, "r27" }, +  { { "i4" }, "r28" }, +  { { "i5" }, "r29" }, +  { { "i6", "fp" }, "r30" }, +  { { "i7" }, "r31" }, +}; + +void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, +                                         unsigned &NumAliases) const { +  Aliases = GCCRegAliases; +  NumAliases = llvm::array_lengthof(GCCRegAliases); +} +} // end anonymous namespace. + +namespace { +class SolarisSparcV8TargetInfo : public SparcV8TargetInfo { +public: +  SolarisSparcV8TargetInfo(const std::string& triple) : +      SparcV8TargetInfo(triple) { +    SizeType = UnsignedInt; +    PtrDiffType = SignedInt; +    WCharType = SignedLong; +    // FIXME: WIntType should be SignedLong +    UserLabelPrefix = ""; +  } + +  virtual void getTargetDefines(const LangOptions &Opts, +                                std::vector<char> &Defines) const { +    SparcV8TargetInfo::getTargetDefines(Opts, Defines); +    getSolarisDefines(Opts, Defines); +  } +}; +} // end anonymous namespace. + +namespace { +  class PIC16TargetInfo : public TargetInfo{ +  public: +    PIC16TargetInfo(const std::string& triple) : TargetInfo(triple) { +      TLSSupported = false; +      IntWidth = 16; +      LongWidth = LongLongWidth = 32; +      IntMaxTWidth = 32; +      PointerWidth = 16; +      IntAlign = 8; +      LongAlign = LongLongAlign = 8; +      PointerAlign = 8; +      SizeType = UnsignedInt; +      IntMaxType = SignedLong; +      UIntMaxType = UnsignedLong; +      IntPtrType = SignedShort; +      PtrDiffType = SignedInt; +      FloatWidth = 32; +      FloatAlign = 32; +      DoubleWidth = 32; +      DoubleAlign = 32; +      LongDoubleWidth = 32; +      LongDoubleAlign = 32; +      FloatFormat = &llvm::APFloat::IEEEsingle; +      DoubleFormat = &llvm::APFloat::IEEEsingle; +      LongDoubleFormat = &llvm::APFloat::IEEEsingle; +      DescriptionString = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-f32:32:32"; + +    } +    virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return 16; } +    virtual uint64_t getPointerAlignV(unsigned AddrSpace) const { return 8; } +    virtual void getTargetDefines(const LangOptions &Opts, +                                  std::vector<char> &Defines) const { +      Define(Defines, "__pic16"); +    } +    virtual void getTargetBuiltins(const Builtin::Info *&Records, +                                   unsigned &NumRecords) const {} +    virtual const char *getVAListDeclaration() const { return "";} +    virtual const char *getClobbers() const {return "";} +    virtual const char *getTargetPrefix() const {return "pic16";} +    virtual void getGCCRegNames(const char * const *&Names, +                                unsigned &NumNames) const {} +    virtual bool validateAsmConstraint(const char *&Name, +                                       TargetInfo::ConstraintInfo &info) const { +      return true; +    } +    virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, +                                  unsigned &NumAliases) const {} +    virtual bool useGlobalsForAutomaticVariables() const {return true;} +  }; +} + +namespace { +  class MSP430TargetInfo : public TargetInfo { +    static const char * const GCCRegNames[]; +  public: +    MSP430TargetInfo(const std::string& triple) : TargetInfo(triple) { +      TLSSupported = false; +      IntWidth = 16; +      LongWidth = LongLongWidth = 32; +      IntMaxTWidth = 32; +      PointerWidth = 16; +      IntAlign = 8; +      LongAlign = LongLongAlign = 8; +      PointerAlign = 8; +      SizeType = UnsignedInt; +      IntMaxType = SignedLong; +      UIntMaxType = UnsignedLong; +      IntPtrType = SignedShort; +      PtrDiffType = SignedInt; +      DescriptionString = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8"; +   } +    virtual void getTargetDefines(const LangOptions &Opts, +                                 std::vector<char> &Defines) const { +      Define(Defines, "MSP430"); +      Define(Defines, "__MSP430__"); +      // FIXME: defines for different 'flavours' of MCU +    } +    virtual void getTargetBuiltins(const Builtin::Info *&Records, +                                   unsigned &NumRecords) const { +     // FIXME: Implement. +      Records = 0; +      NumRecords = 0; +    } +    virtual const char *getTargetPrefix() const { +      return "msp430"; +    } +    virtual void getGCCRegNames(const char * const *&Names, +                                unsigned &NumNames) const; +    virtual void getGCCRegAliases(const GCCRegAlias *&Aliases, +                                  unsigned &NumAliases) const { +      // No aliases. +      Aliases = 0; +      NumAliases = 0; +    } +    virtual bool validateAsmConstraint(const char *&Name, +                                       TargetInfo::ConstraintInfo &info) const { +      // FIXME: implement +      return true; +    } +    virtual const char *getClobbers() const { +      // FIXME: Is this really right? +      return ""; +    } +    virtual const char *getVAListDeclaration() const { +      // FIXME: implement +      return "typedef char* __builtin_va_list;"; +   } +  }; + +  const char * const MSP430TargetInfo::GCCRegNames[] = { +    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", +    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" +  }; + +  void MSP430TargetInfo::getGCCRegNames(const char * const *&Names, +                                        unsigned &NumNames) const { +    Names = GCCRegNames; +    NumNames = llvm::array_lengthof(GCCRegNames); +  } +} + + +//===----------------------------------------------------------------------===// +// Driver code +//===----------------------------------------------------------------------===// + +static inline bool IsX86(const std::string& TT) { +  return (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' && +          TT[4] == '-' && TT[1] - '3' < 6); +} + +/// CreateTargetInfo - Return the target info object for the specified target +/// triple. +TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { +  // OS detection; this isn't really anywhere near complete. +  // Additions and corrections are welcome. +  bool isDarwin = T.find("-darwin") != std::string::npos; +  bool isDragonFly = T.find("-dragonfly") != std::string::npos; +  bool isFreeBSD = T.find("-freebsd") != std::string::npos; +  bool isSolaris = T.find("-solaris") != std::string::npos; +  bool isLinux = T.find("-linux") != std::string::npos; +  bool isWindows = T.find("-windows") != std::string::npos || +                   T.find("-win32") != std::string::npos || +                   T.find("-mingw") != std::string::npos; + +  if (T.find("ppc-") == 0 || T.find("powerpc-") == 0) { +    if (isDarwin) +      return new DarwinPPCTargetInfo(T); +    return new PPC32TargetInfo(T); +  } + +  if (T.find("ppc64-") == 0 || T.find("powerpc64-") == 0) { +    if (isDarwin) +      return new DarwinPPC64TargetInfo(T); +    return new PPC64TargetInfo(T); +  } + +  if (T.find("armv") == 0 || T.find("arm-") == 0 || T.find("xscale") == 0) { +    if (isDarwin) +      return new DarwinARMTargetInfo(T); +    if (isFreeBSD) +      return new FreeBSDARMTargetInfo(T); +    return new ARMTargetInfo(T); +  } + +  if (T.find("sparc-") == 0) { +    if (isSolaris) +      return new SolarisSparcV8TargetInfo(T); +    return new SparcV8TargetInfo(T); +  } + +  if (T.find("x86_64-") == 0 || T.find("amd64-") == 0) { +    if (isDarwin) +      return new DarwinX86_64TargetInfo(T); +    if (isLinux) +      return new LinuxX86_64TargetInfo(T); +    if (isFreeBSD) +      return new FreeBSDX86_64TargetInfo(T); +    if (isSolaris) +      return new SolarisX86_64TargetInfo(T); +    return new X86_64TargetInfo(T); +  } + +  if (T.find("pic16-") == 0) +    return new PIC16TargetInfo(T); + +  if (T.find("msp430-") == 0) +    return new MSP430TargetInfo(T); + +  if (IsX86(T)) { +    if (isDarwin) +      return new DarwinI386TargetInfo(T); +    if (isLinux) +      return new LinuxX86_32TargetInfo(T); +    if (isDragonFly) +      return new DragonFlyX86_32TargetInfo(T); +    if (isFreeBSD) +      return new FreeBSDX86_32TargetInfo(T); +    if (isSolaris) +      return new SolarisX86_32TargetInfo(T); +    if (isWindows) +      return new WindowsX86_32TargetInfo(T); +    return new X86_32TargetInfo(T); +  } + +  return NULL; +}  | 
