forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			1306 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1306 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C++
		
	
	
	
//===--- ARM.cpp - Implement ARM target feature support -------------------===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file implements ARM TargetInfo objects.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "ARM.h"
 | 
						|
#include "clang/Basic/Builtins.h"
 | 
						|
#include "clang/Basic/Diagnostic.h"
 | 
						|
#include "clang/Basic/TargetBuiltins.h"
 | 
						|
#include "llvm/ADT/StringExtras.h"
 | 
						|
#include "llvm/ADT/StringRef.h"
 | 
						|
#include "llvm/ADT/StringSwitch.h"
 | 
						|
 | 
						|
using namespace clang;
 | 
						|
using namespace clang::targets;
 | 
						|
 | 
						|
void ARMTargetInfo::setABIAAPCS() {
 | 
						|
  IsAAPCS = true;
 | 
						|
 | 
						|
  DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
 | 
						|
  BFloat16Width = BFloat16Align = 16;
 | 
						|
  BFloat16Format = &llvm::APFloat::BFloat();
 | 
						|
 | 
						|
  const llvm::Triple &T = getTriple();
 | 
						|
 | 
						|
  bool IsNetBSD = T.isOSNetBSD();
 | 
						|
  bool IsOpenBSD = T.isOSOpenBSD();
 | 
						|
  if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)
 | 
						|
    WCharType = UnsignedInt;
 | 
						|
 | 
						|
  UseBitFieldTypeAlignment = true;
 | 
						|
 | 
						|
  ZeroLengthBitfieldBoundary = 0;
 | 
						|
 | 
						|
  // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
 | 
						|
  // so set preferred for small types to 32.
 | 
						|
  if (T.isOSBinFormatMachO()) {
 | 
						|
    resetDataLayout(BigEndian
 | 
						|
                        ? "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
 | 
						|
                        : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
 | 
						|
  } else if (T.isOSWindows()) {
 | 
						|
    assert(!BigEndian && "Windows on ARM does not support big endian");
 | 
						|
    resetDataLayout("e"
 | 
						|
                    "-m:w"
 | 
						|
                    "-p:32:32"
 | 
						|
                    "-Fi8"
 | 
						|
                    "-i64:64"
 | 
						|
                    "-v128:64:128"
 | 
						|
                    "-a:0:32"
 | 
						|
                    "-n32"
 | 
						|
                    "-S64");
 | 
						|
  } else if (T.isOSNaCl()) {
 | 
						|
    assert(!BigEndian && "NaCl on ARM does not support big endian");
 | 
						|
    resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S128");
 | 
						|
  } else {
 | 
						|
    resetDataLayout(BigEndian
 | 
						|
                        ? "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
 | 
						|
                        : "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
 | 
						|
  }
 | 
						|
 | 
						|
  // FIXME: Enumerated types are variable width in straight AAPCS.
 | 
						|
}
 | 
						|
 | 
						|
void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
 | 
						|
  const llvm::Triple &T = getTriple();
 | 
						|
 | 
						|
  IsAAPCS = false;
 | 
						|
 | 
						|
  if (IsAAPCS16)
 | 
						|
    DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
 | 
						|
  else
 | 
						|
    DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
 | 
						|
  BFloat16Width = BFloat16Align = 16;
 | 
						|
  BFloat16Format = &llvm::APFloat::BFloat();
 | 
						|
 | 
						|
  WCharType = SignedInt;
 | 
						|
 | 
						|
  // Do not respect the alignment of bit-field types when laying out
 | 
						|
  // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
 | 
						|
  UseBitFieldTypeAlignment = false;
 | 
						|
 | 
						|
  /// gcc forces the alignment to 4 bytes, regardless of the type of the
 | 
						|
  /// zero length bitfield.  This corresponds to EMPTY_FIELD_BOUNDARY in
 | 
						|
  /// gcc.
 | 
						|
  ZeroLengthBitfieldBoundary = 32;
 | 
						|
 | 
						|
  if (T.isOSBinFormatMachO() && IsAAPCS16) {
 | 
						|
    assert(!BigEndian && "AAPCS16 does not support big-endian");
 | 
						|
    resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128");
 | 
						|
  } else if (T.isOSBinFormatMachO())
 | 
						|
    resetDataLayout(
 | 
						|
        BigEndian
 | 
						|
            ? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
 | 
						|
            : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
 | 
						|
  else
 | 
						|
    resetDataLayout(
 | 
						|
        BigEndian
 | 
						|
            ? "E-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
 | 
						|
            : "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
 | 
						|
 | 
						|
  // FIXME: Override "preferred align" for double and long long.
 | 
						|
}
 | 
						|
 | 
						|
void ARMTargetInfo::setArchInfo() {
 | 
						|
  StringRef ArchName = getTriple().getArchName();
 | 
						|
 | 
						|
  ArchISA = llvm::ARM::parseArchISA(ArchName);
 | 
						|
  CPU = std::string(llvm::ARM::getDefaultCPU(ArchName));
 | 
						|
  llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName);
 | 
						|
  if (AK != llvm::ARM::ArchKind::INVALID)
 | 
						|
    ArchKind = AK;
 | 
						|
  setArchInfo(ArchKind);
 | 
						|
}
 | 
						|
 | 
						|
void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
 | 
						|
  StringRef SubArch;
 | 
						|
 | 
						|
  // cache TargetParser info
 | 
						|
  ArchKind = Kind;
 | 
						|
  SubArch = llvm::ARM::getSubArch(ArchKind);
 | 
						|
  ArchProfile = llvm::ARM::parseArchProfile(SubArch);
 | 
						|
  ArchVersion = llvm::ARM::parseArchVersion(SubArch);
 | 
						|
 | 
						|
  // cache CPU related strings
 | 
						|
  CPUAttr = getCPUAttr();
 | 
						|
  CPUProfile = getCPUProfile();
 | 
						|
}
 | 
						|
 | 
						|
void ARMTargetInfo::setAtomic() {
 | 
						|
  // when triple does not specify a sub arch,
 | 
						|
  // then we are not using inline atomics
 | 
						|
  bool ShouldUseInlineAtomic =
 | 
						|
      (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) ||
 | 
						|
      (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7);
 | 
						|
  // Cortex M does not support 8 byte atomics, while general Thumb2 does.
 | 
						|
  if (ArchProfile == llvm::ARM::ProfileKind::M) {
 | 
						|
    MaxAtomicPromoteWidth = 32;
 | 
						|
    if (ShouldUseInlineAtomic)
 | 
						|
      MaxAtomicInlineWidth = 32;
 | 
						|
  } else {
 | 
						|
    MaxAtomicPromoteWidth = 64;
 | 
						|
    if (ShouldUseInlineAtomic)
 | 
						|
      MaxAtomicInlineWidth = 64;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::hasMVE() const {
 | 
						|
  return ArchKind == llvm::ARM::ArchKind::ARMV8_1MMainline && MVE != 0;
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::hasMVEFloat() const {
 | 
						|
  return hasMVE() && (MVE & MVE_FP);
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::hasCDE() const { return getARMCDECoprocMask() != 0; }
 | 
						|
 | 
						|
bool ARMTargetInfo::isThumb() const {
 | 
						|
  return ArchISA == llvm::ARM::ISAKind::THUMB;
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::supportsThumb() const {
 | 
						|
  return CPUAttr.count('T') || ArchVersion >= 6;
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::supportsThumb2() const {
 | 
						|
  return CPUAttr.equals("6T2") ||
 | 
						|
         (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
 | 
						|
}
 | 
						|
 | 
						|
StringRef ARMTargetInfo::getCPUAttr() const {
 | 
						|
  // For most sub-arches, the build attribute CPU name is enough.
 | 
						|
  // For Cortex variants, it's slightly different.
 | 
						|
  switch (ArchKind) {
 | 
						|
  default:
 | 
						|
    return llvm::ARM::getCPUAttr(ArchKind);
 | 
						|
  case llvm::ARM::ArchKind::ARMV6M:
 | 
						|
    return "6M";
 | 
						|
  case llvm::ARM::ArchKind::ARMV7S:
 | 
						|
    return "7S";
 | 
						|
  case llvm::ARM::ArchKind::ARMV7A:
 | 
						|
    return "7A";
 | 
						|
  case llvm::ARM::ArchKind::ARMV7R:
 | 
						|
    return "7R";
 | 
						|
  case llvm::ARM::ArchKind::ARMV7M:
 | 
						|
    return "7M";
 | 
						|
  case llvm::ARM::ArchKind::ARMV7EM:
 | 
						|
    return "7EM";
 | 
						|
  case llvm::ARM::ArchKind::ARMV7VE:
 | 
						|
    return "7VE";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8A:
 | 
						|
    return "8A";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_1A:
 | 
						|
    return "8_1A";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_2A:
 | 
						|
    return "8_2A";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_3A:
 | 
						|
    return "8_3A";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_4A:
 | 
						|
    return "8_4A";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_5A:
 | 
						|
    return "8_5A";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_6A:
 | 
						|
    return "8_6A";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8MBaseline:
 | 
						|
    return "8M_BASE";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8MMainline:
 | 
						|
    return "8M_MAIN";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8R:
 | 
						|
    return "8R";
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_1MMainline:
 | 
						|
    return "8_1M_MAIN";
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
StringRef ARMTargetInfo::getCPUProfile() const {
 | 
						|
  switch (ArchProfile) {
 | 
						|
  case llvm::ARM::ProfileKind::A:
 | 
						|
    return "A";
 | 
						|
  case llvm::ARM::ProfileKind::R:
 | 
						|
    return "R";
 | 
						|
  case llvm::ARM::ProfileKind::M:
 | 
						|
    return "M";
 | 
						|
  default:
 | 
						|
    return "";
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
 | 
						|
                             const TargetOptions &Opts)
 | 
						|
    : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
 | 
						|
      HW_FP(0) {
 | 
						|
  bool IsOpenBSD = Triple.isOSOpenBSD();
 | 
						|
  bool IsNetBSD = Triple.isOSNetBSD();
 | 
						|
 | 
						|
  // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
 | 
						|
  // environment where size_t is `unsigned long` rather than `unsigned int`
 | 
						|
 | 
						|
  PtrDiffType = IntPtrType =
 | 
						|
      (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
 | 
						|
       IsNetBSD)
 | 
						|
          ? SignedLong
 | 
						|
          : SignedInt;
 | 
						|
 | 
						|
  SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
 | 
						|
              IsNetBSD)
 | 
						|
                 ? UnsignedLong
 | 
						|
                 : UnsignedInt;
 | 
						|
 | 
						|
  // ptrdiff_t is inconsistent on Darwin
 | 
						|
  if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&
 | 
						|
      !Triple.isWatchABI())
 | 
						|
    PtrDiffType = SignedInt;
 | 
						|
 | 
						|
  // Cache arch related info.
 | 
						|
  setArchInfo();
 | 
						|
 | 
						|
  // {} in inline assembly are neon specifiers, not assembly variant
 | 
						|
  // specifiers.
 | 
						|
  NoAsmVariants = true;
 | 
						|
 | 
						|
  // FIXME: This duplicates code from the driver that sets the -target-abi
 | 
						|
  // option - this code is used if -target-abi isn't passed and should
 | 
						|
  // be unified in some way.
 | 
						|
  if (Triple.isOSBinFormatMachO()) {
 | 
						|
    // The backend is hardwired to assume AAPCS for M-class processors, ensure
 | 
						|
    // the frontend matches that.
 | 
						|
    if (Triple.getEnvironment() == llvm::Triple::EABI ||
 | 
						|
        Triple.getOS() == llvm::Triple::UnknownOS ||
 | 
						|
        ArchProfile == llvm::ARM::ProfileKind::M) {
 | 
						|
      setABI("aapcs");
 | 
						|
    } else if (Triple.isWatchABI()) {
 | 
						|
      setABI("aapcs16");
 | 
						|
    } else {
 | 
						|
      setABI("apcs-gnu");
 | 
						|
    }
 | 
						|
  } else if (Triple.isOSWindows()) {
 | 
						|
    // FIXME: this is invalid for WindowsCE
 | 
						|
    setABI("aapcs");
 | 
						|
  } else {
 | 
						|
    // Select the default based on the platform.
 | 
						|
    switch (Triple.getEnvironment()) {
 | 
						|
    case llvm::Triple::Android:
 | 
						|
    case llvm::Triple::GNUEABI:
 | 
						|
    case llvm::Triple::GNUEABIHF:
 | 
						|
    case llvm::Triple::MuslEABI:
 | 
						|
    case llvm::Triple::MuslEABIHF:
 | 
						|
      setABI("aapcs-linux");
 | 
						|
      break;
 | 
						|
    case llvm::Triple::EABIHF:
 | 
						|
    case llvm::Triple::EABI:
 | 
						|
      setABI("aapcs");
 | 
						|
      break;
 | 
						|
    case llvm::Triple::GNU:
 | 
						|
      setABI("apcs-gnu");
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      if (IsNetBSD)
 | 
						|
        setABI("apcs-gnu");
 | 
						|
      else if (IsOpenBSD)
 | 
						|
        setABI("aapcs-linux");
 | 
						|
      else
 | 
						|
        setABI("aapcs");
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // ARM targets default to using the ARM C++ ABI.
 | 
						|
  TheCXXABI.set(TargetCXXABI::GenericARM);
 | 
						|
 | 
						|
  // ARM has atomics up to 8 bytes
 | 
						|
  setAtomic();
 | 
						|
 | 
						|
  // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
 | 
						|
  // as well the default alignment
 | 
						|
  if (IsAAPCS && !Triple.isAndroid())
 | 
						|
    DefaultAlignForAttributeAligned = MaxVectorAlign = 64;
 | 
						|
 | 
						|
  // Do force alignment of members that follow zero length bitfields.  If
 | 
						|
  // the alignment of the zero-length bitfield is greater than the member
 | 
						|
  // that follows it, `bar', `bar' will be aligned as the  type of the
 | 
						|
  // zero length bitfield.
 | 
						|
  UseZeroLengthBitfieldAlignment = true;
 | 
						|
 | 
						|
  if (Triple.getOS() == llvm::Triple::Linux ||
 | 
						|
      Triple.getOS() == llvm::Triple::UnknownOS)
 | 
						|
    this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
 | 
						|
                           ? "llvm.arm.gnu.eabi.mcount"
 | 
						|
                           : "\01mcount";
 | 
						|
 | 
						|
  SoftFloatABI = llvm::is_contained(Opts.FeaturesAsWritten, "+soft-float-abi");
 | 
						|
}
 | 
						|
 | 
						|
StringRef ARMTargetInfo::getABI() const { return ABI; }
 | 
						|
 | 
						|
bool ARMTargetInfo::setABI(const std::string &Name) {
 | 
						|
  ABI = Name;
 | 
						|
 | 
						|
  // The defaults (above) are for AAPCS, check if we need to change them.
 | 
						|
  //
 | 
						|
  // FIXME: We need support for -meabi... we could just mangle it into the
 | 
						|
  // name.
 | 
						|
  if (Name == "apcs-gnu" || Name == "aapcs16") {
 | 
						|
    setABIAPCS(Name == "aapcs16");
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
 | 
						|
    setABIAAPCS();
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
// FIXME: This should be based on Arch attributes, not CPU names.
 | 
						|
bool ARMTargetInfo::initFeatureMap(
 | 
						|
    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
 | 
						|
    const std::vector<std::string> &FeaturesVec) const {
 | 
						|
 | 
						|
  std::string ArchFeature;
 | 
						|
  std::vector<StringRef> TargetFeatures;
 | 
						|
  llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());
 | 
						|
 | 
						|
  // Map the base architecture to an appropriate target feature, so we don't
 | 
						|
  // rely on the target triple.
 | 
						|
  llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);
 | 
						|
  if (CPUArch == llvm::ARM::ArchKind::INVALID)
 | 
						|
    CPUArch = Arch;
 | 
						|
  if (CPUArch != llvm::ARM::ArchKind::INVALID) {
 | 
						|
    ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str();
 | 
						|
    TargetFeatures.push_back(ArchFeature);
 | 
						|
  }
 | 
						|
 | 
						|
  // get default FPU features
 | 
						|
  unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
 | 
						|
  llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
 | 
						|
 | 
						|
  // get default Extension features
 | 
						|
  uint64_t Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
 | 
						|
  llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
 | 
						|
 | 
						|
  for (auto Feature : TargetFeatures)
 | 
						|
    if (Feature[0] == '+')
 | 
						|
      Features[Feature.drop_front(1)] = true;
 | 
						|
 | 
						|
  // Enable or disable thumb-mode explicitly per function to enable mixed
 | 
						|
  // ARM and Thumb code generation.
 | 
						|
  if (isThumb())
 | 
						|
    Features["thumb-mode"] = true;
 | 
						|
  else
 | 
						|
    Features["thumb-mode"] = false;
 | 
						|
 | 
						|
  // Convert user-provided arm and thumb GNU target attributes to
 | 
						|
  // [-|+]thumb-mode target features respectively.
 | 
						|
  std::vector<std::string> UpdatedFeaturesVec;
 | 
						|
  for (const auto &Feature : FeaturesVec) {
 | 
						|
    // Skip soft-float-abi; it's something we only use to initialize a bit of
 | 
						|
    // class state, and is otherwise unrecognized.
 | 
						|
    if (Feature == "+soft-float-abi")
 | 
						|
      continue;
 | 
						|
 | 
						|
    StringRef FixedFeature;
 | 
						|
    if (Feature == "+arm")
 | 
						|
      FixedFeature = "-thumb-mode";
 | 
						|
    else if (Feature == "+thumb")
 | 
						|
      FixedFeature = "+thumb-mode";
 | 
						|
    else
 | 
						|
      FixedFeature = Feature;
 | 
						|
    UpdatedFeaturesVec.push_back(FixedFeature.str());
 | 
						|
  }
 | 
						|
 | 
						|
  return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
 | 
						|
                                         DiagnosticsEngine &Diags) {
 | 
						|
  FPU = 0;
 | 
						|
  MVE = 0;
 | 
						|
  CRC = 0;
 | 
						|
  Crypto = 0;
 | 
						|
  DSP = 0;
 | 
						|
  Unaligned = 1;
 | 
						|
  SoftFloat = false;
 | 
						|
  // Note that SoftFloatABI is initialized in our constructor.
 | 
						|
  HWDiv = 0;
 | 
						|
  DotProd = 0;
 | 
						|
  HasMatMul = 0;
 | 
						|
  HasFloat16 = true;
 | 
						|
  ARMCDECoprocMask = 0;
 | 
						|
  HasBFloat16 = false;
 | 
						|
 | 
						|
  // This does not diagnose illegal cases like having both
 | 
						|
  // "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64".
 | 
						|
  for (const auto &Feature : Features) {
 | 
						|
    if (Feature == "+soft-float") {
 | 
						|
      SoftFloat = true;
 | 
						|
    } else if (Feature == "+vfp2sp" || Feature == "+vfp2") {
 | 
						|
      FPU |= VFP2FPU;
 | 
						|
      HW_FP |= HW_FP_SP;
 | 
						|
      if (Feature == "+vfp2")
 | 
						|
          HW_FP |= HW_FP_DP;
 | 
						|
    } else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" ||
 | 
						|
               Feature == "+vfp3" || Feature == "+vfp3d16") {
 | 
						|
      FPU |= VFP3FPU;
 | 
						|
      HW_FP |= HW_FP_SP;
 | 
						|
      if (Feature == "+vfp3" || Feature == "+vfp3d16")
 | 
						|
          HW_FP |= HW_FP_DP;
 | 
						|
    } else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" ||
 | 
						|
               Feature == "+vfp4" || Feature == "+vfp4d16") {
 | 
						|
      FPU |= VFP4FPU;
 | 
						|
      HW_FP |= HW_FP_SP | HW_FP_HP;
 | 
						|
      if (Feature == "+vfp4" || Feature == "+vfp4d16")
 | 
						|
          HW_FP |= HW_FP_DP;
 | 
						|
    } else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" ||
 | 
						|
               Feature == "+fp-armv8" || Feature == "+fp-armv8d16") {
 | 
						|
      FPU |= FPARMV8;
 | 
						|
      HW_FP |= HW_FP_SP | HW_FP_HP;
 | 
						|
      if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16")
 | 
						|
          HW_FP |= HW_FP_DP;
 | 
						|
    } else if (Feature == "+neon") {
 | 
						|
      FPU |= NeonFPU;
 | 
						|
      HW_FP |= HW_FP_SP;
 | 
						|
    } else if (Feature == "+hwdiv") {
 | 
						|
      HWDiv |= HWDivThumb;
 | 
						|
    } else if (Feature == "+hwdiv-arm") {
 | 
						|
      HWDiv |= HWDivARM;
 | 
						|
    } else if (Feature == "+crc") {
 | 
						|
      CRC = 1;
 | 
						|
    } else if (Feature == "+crypto") {
 | 
						|
      Crypto = 1;
 | 
						|
    } else if (Feature == "+dsp") {
 | 
						|
      DSP = 1;
 | 
						|
    } else if (Feature == "+fp64") {
 | 
						|
      HW_FP |= HW_FP_DP;
 | 
						|
    } else if (Feature == "+8msecext") {
 | 
						|
      if (CPUProfile != "M" || ArchVersion != 8) {
 | 
						|
        Diags.Report(diag::err_target_unsupported_mcmse) << CPU;
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
    } else if (Feature == "+strict-align") {
 | 
						|
      Unaligned = 0;
 | 
						|
    } else if (Feature == "+fp16") {
 | 
						|
      HW_FP |= HW_FP_HP;
 | 
						|
    } else if (Feature == "+fullfp16") {
 | 
						|
      HasLegalHalfType = true;
 | 
						|
    } else if (Feature == "+dotprod") {
 | 
						|
      DotProd = true;
 | 
						|
    } else if (Feature == "+mve") {
 | 
						|
      MVE |= MVE_INT;
 | 
						|
    } else if (Feature == "+mve.fp") {
 | 
						|
      HasLegalHalfType = true;
 | 
						|
      FPU |= FPARMV8;
 | 
						|
      MVE |= MVE_INT | MVE_FP;
 | 
						|
      HW_FP |= HW_FP_SP | HW_FP_HP;
 | 
						|
    } else if (Feature == "+i8mm") {
 | 
						|
      HasMatMul = 1;
 | 
						|
    } else if (Feature.size() == strlen("+cdecp0") && Feature >= "+cdecp0" &&
 | 
						|
               Feature <= "+cdecp7") {
 | 
						|
      unsigned Coproc = Feature.back() - '0';
 | 
						|
      ARMCDECoprocMask |= (1U << Coproc);
 | 
						|
    } else if (Feature == "+bf16") {
 | 
						|
      HasBFloat16 = true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  switch (ArchVersion) {
 | 
						|
  case 6:
 | 
						|
    if (ArchProfile == llvm::ARM::ProfileKind::M)
 | 
						|
      LDREX = 0;
 | 
						|
    else if (ArchKind == llvm::ARM::ArchKind::ARMV6K)
 | 
						|
      LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
 | 
						|
    else
 | 
						|
      LDREX = LDREX_W;
 | 
						|
    break;
 | 
						|
  case 7:
 | 
						|
    if (ArchProfile == llvm::ARM::ProfileKind::M)
 | 
						|
      LDREX = LDREX_W | LDREX_H | LDREX_B;
 | 
						|
    else
 | 
						|
      LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
 | 
						|
    break;
 | 
						|
  case 8:
 | 
						|
    LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
 | 
						|
    Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (FPMath == FP_Neon)
 | 
						|
    Features.push_back("+neonfp");
 | 
						|
  else if (FPMath == FP_VFP)
 | 
						|
    Features.push_back("-neonfp");
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::hasFeature(StringRef Feature) const {
 | 
						|
  return llvm::StringSwitch<bool>(Feature)
 | 
						|
      .Case("arm", true)
 | 
						|
      .Case("aarch32", true)
 | 
						|
      .Case("softfloat", SoftFloat)
 | 
						|
      .Case("thumb", isThumb())
 | 
						|
      .Case("neon", (FPU & NeonFPU) && !SoftFloat)
 | 
						|
      .Case("vfp", FPU && !SoftFloat)
 | 
						|
      .Case("hwdiv", HWDiv & HWDivThumb)
 | 
						|
      .Case("hwdiv-arm", HWDiv & HWDivARM)
 | 
						|
      .Case("mve", hasMVE())
 | 
						|
      .Default(false);
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::hasBFloat16Type() const {
 | 
						|
  return HasBFloat16 && !SoftFloat;
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
 | 
						|
  return Name == "generic" ||
 | 
						|
         llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;
 | 
						|
}
 | 
						|
 | 
						|
void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
 | 
						|
  llvm::ARM::fillValidCPUArchList(Values);
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::setCPU(const std::string &Name) {
 | 
						|
  if (Name != "generic")
 | 
						|
    setArchInfo(llvm::ARM::parseCPUArch(Name));
 | 
						|
 | 
						|
  if (ArchKind == llvm::ARM::ArchKind::INVALID)
 | 
						|
    return false;
 | 
						|
  setAtomic();
 | 
						|
  CPU = Name;
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::setFPMath(StringRef Name) {
 | 
						|
  if (Name == "neon") {
 | 
						|
    FPMath = FP_Neon;
 | 
						|
    return true;
 | 
						|
  } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
 | 
						|
             Name == "vfp4") {
 | 
						|
    FPMath = FP_VFP;
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
 | 
						|
                                            MacroBuilder &Builder) const {
 | 
						|
  Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
 | 
						|
}
 | 
						|
 | 
						|
void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
 | 
						|
                                            MacroBuilder &Builder) const {
 | 
						|
  // Also include the ARMv8.1-A defines
 | 
						|
  getTargetDefinesARMV81A(Opts, Builder);
 | 
						|
}
 | 
						|
 | 
						|
void ARMTargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
 | 
						|
                                            MacroBuilder &Builder) const {
 | 
						|
  // Also include the ARMv8.2-A defines
 | 
						|
  Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
 | 
						|
  getTargetDefinesARMV82A(Opts, Builder);
 | 
						|
}
 | 
						|
 | 
						|
void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
 | 
						|
                                     MacroBuilder &Builder) const {
 | 
						|
  // Target identification.
 | 
						|
  Builder.defineMacro("__arm");
 | 
						|
  Builder.defineMacro("__arm__");
 | 
						|
  // For bare-metal none-eabi.
 | 
						|
  if (getTriple().getOS() == llvm::Triple::UnknownOS &&
 | 
						|
      (getTriple().getEnvironment() == llvm::Triple::EABI ||
 | 
						|
       getTriple().getEnvironment() == llvm::Triple::EABIHF))
 | 
						|
    Builder.defineMacro("__ELF__");
 | 
						|
 | 
						|
  // Target properties.
 | 
						|
  Builder.defineMacro("__REGISTER_PREFIX__", "");
 | 
						|
 | 
						|
  // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
 | 
						|
  // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
 | 
						|
  if (getTriple().isWatchABI())
 | 
						|
    Builder.defineMacro("__ARM_ARCH_7K__", "2");
 | 
						|
 | 
						|
  if (!CPUAttr.empty())
 | 
						|
    Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
 | 
						|
 | 
						|
  // ACLE 6.4.1 ARM/Thumb instruction set architecture
 | 
						|
  // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
 | 
						|
  Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
 | 
						|
 | 
						|
  if (ArchVersion >= 8) {
 | 
						|
    // ACLE 6.5.7 Crypto Extension
 | 
						|
    if (Crypto)
 | 
						|
      Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
 | 
						|
    // ACLE 6.5.8 CRC32 Extension
 | 
						|
    if (CRC)
 | 
						|
      Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
 | 
						|
    // ACLE 6.5.10 Numeric Maximum and Minimum
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
 | 
						|
    // ACLE 6.5.9 Directed Rounding
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
 | 
						|
  }
 | 
						|
 | 
						|
  // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA.  It
 | 
						|
  // is not defined for the M-profile.
 | 
						|
  // NOTE that the default profile is assumed to be 'A'
 | 
						|
  if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)
 | 
						|
    Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
 | 
						|
 | 
						|
  // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
 | 
						|
  // Thumb ISA (including v6-M and v8-M Baseline).  It is set to 2 if the
 | 
						|
  // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
 | 
						|
  // v7 and v8 architectures excluding v8-M Baseline.
 | 
						|
  if (supportsThumb2())
 | 
						|
    Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
 | 
						|
  else if (supportsThumb())
 | 
						|
    Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
 | 
						|
 | 
						|
  // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
 | 
						|
  // instruction set such as ARM or Thumb.
 | 
						|
  Builder.defineMacro("__ARM_32BIT_STATE", "1");
 | 
						|
 | 
						|
  // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
 | 
						|
 | 
						|
  // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
 | 
						|
  if (!CPUProfile.empty())
 | 
						|
    Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
 | 
						|
 | 
						|
  // ACLE 6.4.3 Unaligned access supported in hardware
 | 
						|
  if (Unaligned)
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
 | 
						|
 | 
						|
  // ACLE 6.4.4 LDREX/STREX
 | 
						|
  if (LDREX)
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX));
 | 
						|
 | 
						|
  // ACLE 6.4.5 CLZ
 | 
						|
  if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
 | 
						|
      ArchVersion > 6)
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
 | 
						|
 | 
						|
  // ACLE 6.5.1 Hardware Floating Point
 | 
						|
  if (HW_FP)
 | 
						|
    Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP));
 | 
						|
 | 
						|
  // ACLE predefines.
 | 
						|
  Builder.defineMacro("__ARM_ACLE", "200");
 | 
						|
 | 
						|
  // FP16 support (we currently only support IEEE format).
 | 
						|
  Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
 | 
						|
  Builder.defineMacro("__ARM_FP16_ARGS", "1");
 | 
						|
 | 
						|
  // ACLE 6.5.3 Fused multiply-accumulate (FMA)
 | 
						|
  if (ArchVersion >= 7 && (FPU & VFP4FPU))
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_FMA", "1");
 | 
						|
 | 
						|
  // Subtarget options.
 | 
						|
 | 
						|
  // FIXME: It's more complicated than this and we don't really support
 | 
						|
  // interworking.
 | 
						|
  // Windows on ARM does not "support" interworking
 | 
						|
  if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
 | 
						|
    Builder.defineMacro("__THUMB_INTERWORK__");
 | 
						|
 | 
						|
  if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
 | 
						|
    // Embedded targets on Darwin follow AAPCS, but not EABI.
 | 
						|
    // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
 | 
						|
    if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
 | 
						|
      Builder.defineMacro("__ARM_EABI__");
 | 
						|
    Builder.defineMacro("__ARM_PCS", "1");
 | 
						|
  }
 | 
						|
 | 
						|
  if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
 | 
						|
    Builder.defineMacro("__ARM_PCS_VFP", "1");
 | 
						|
 | 
						|
  if (SoftFloat)
 | 
						|
    Builder.defineMacro("__SOFTFP__");
 | 
						|
 | 
						|
  // ACLE position independent code macros.
 | 
						|
  if (Opts.ROPI)
 | 
						|
    Builder.defineMacro("__ARM_ROPI", "1");
 | 
						|
  if (Opts.RWPI)
 | 
						|
    Builder.defineMacro("__ARM_RWPI", "1");
 | 
						|
 | 
						|
  if (ArchKind == llvm::ARM::ArchKind::XSCALE)
 | 
						|
    Builder.defineMacro("__XSCALE__");
 | 
						|
 | 
						|
  if (isThumb()) {
 | 
						|
    Builder.defineMacro("__THUMBEL__");
 | 
						|
    Builder.defineMacro("__thumb__");
 | 
						|
    if (supportsThumb2())
 | 
						|
      Builder.defineMacro("__thumb2__");
 | 
						|
  }
 | 
						|
 | 
						|
  // ACLE 6.4.9 32-bit SIMD instructions
 | 
						|
  if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP))
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
 | 
						|
 | 
						|
  // ACLE 6.4.10 Hardware Integer Divide
 | 
						|
  if (((HWDiv & HWDivThumb) && isThumb()) ||
 | 
						|
      ((HWDiv & HWDivARM) && !isThumb())) {
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
 | 
						|
    Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
 | 
						|
  }
 | 
						|
 | 
						|
  // Note, this is always on in gcc, even though it doesn't make sense.
 | 
						|
  Builder.defineMacro("__APCS_32__");
 | 
						|
 | 
						|
  if (FPUModeIsVFP((FPUMode)FPU)) {
 | 
						|
    Builder.defineMacro("__VFP_FP__");
 | 
						|
    if (FPU & VFP2FPU)
 | 
						|
      Builder.defineMacro("__ARM_VFPV2__");
 | 
						|
    if (FPU & VFP3FPU)
 | 
						|
      Builder.defineMacro("__ARM_VFPV3__");
 | 
						|
    if (FPU & VFP4FPU)
 | 
						|
      Builder.defineMacro("__ARM_VFPV4__");
 | 
						|
    if (FPU & FPARMV8)
 | 
						|
      Builder.defineMacro("__ARM_FPV5__");
 | 
						|
  }
 | 
						|
 | 
						|
  // This only gets set when Neon instructions are actually available, unlike
 | 
						|
  // the VFP define, hence the soft float and arch check. This is subtly
 | 
						|
  // different from gcc, we follow the intent which was that it should be set
 | 
						|
  // when Neon instructions are actually available.
 | 
						|
  if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
 | 
						|
    Builder.defineMacro("__ARM_NEON", "1");
 | 
						|
    Builder.defineMacro("__ARM_NEON__");
 | 
						|
    // current AArch32 NEON implementations do not support double-precision
 | 
						|
    // floating-point even when it is present in VFP.
 | 
						|
    Builder.defineMacro("__ARM_NEON_FP",
 | 
						|
                        "0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP));
 | 
						|
  }
 | 
						|
 | 
						|
  if (hasMVE()) {
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_MVE", hasMVEFloat() ? "3" : "1");
 | 
						|
  }
 | 
						|
 | 
						|
  if (hasCDE()) {
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_CDE", "1");
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_CDE_COPROC",
 | 
						|
                        "0x" + Twine::utohexstr(getARMCDECoprocMask()));
 | 
						|
  }
 | 
						|
 | 
						|
  Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
 | 
						|
                      Twine(Opts.WCharSize ? Opts.WCharSize : 4));
 | 
						|
 | 
						|
  Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
 | 
						|
 | 
						|
  // CMSE
 | 
						|
  if (ArchVersion == 8 && ArchProfile == llvm::ARM::ProfileKind::M)
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_CMSE", Opts.Cmse ? "3" : "1");
 | 
						|
 | 
						|
  if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
 | 
						|
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
 | 
						|
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
 | 
						|
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
 | 
						|
    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
 | 
						|
  }
 | 
						|
 | 
						|
  // ACLE 6.4.7 DSP instructions
 | 
						|
  if (DSP) {
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_DSP", "1");
 | 
						|
  }
 | 
						|
 | 
						|
  // ACLE 6.4.8 Saturation instructions
 | 
						|
  bool SAT = false;
 | 
						|
  if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_SAT", "1");
 | 
						|
    SAT = true;
 | 
						|
  }
 | 
						|
 | 
						|
  // ACLE 6.4.6 Q (saturation) flag
 | 
						|
  if (DSP || SAT)
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
 | 
						|
 | 
						|
  if (Opts.UnsafeFPMath)
 | 
						|
    Builder.defineMacro("__ARM_FP_FAST", "1");
 | 
						|
 | 
						|
  // Armv8.2-A FP16 vector intrinsic
 | 
						|
  if ((FPU & NeonFPU) && HasLegalHalfType)
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
 | 
						|
 | 
						|
  // Armv8.2-A FP16 scalar intrinsics
 | 
						|
  if (HasLegalHalfType)
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
 | 
						|
 | 
						|
  // Armv8.2-A dot product intrinsics
 | 
						|
  if (DotProd)
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
 | 
						|
 | 
						|
  if (HasMatMul)
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");
 | 
						|
 | 
						|
  if (HasBFloat16) {
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_BF16", "1");
 | 
						|
    Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1");
 | 
						|
    Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");
 | 
						|
  }
 | 
						|
 | 
						|
  switch (ArchKind) {
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_1A:
 | 
						|
    getTargetDefinesARMV81A(Opts, Builder);
 | 
						|
    break;
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_2A:
 | 
						|
    getTargetDefinesARMV82A(Opts, Builder);
 | 
						|
    break;
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_3A:
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_4A:
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_5A:
 | 
						|
  case llvm::ARM::ArchKind::ARMV8_6A:
 | 
						|
    getTargetDefinesARMV83A(Opts, Builder);
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
 | 
						|
#define BUILTIN(ID, TYPE, ATTRS)                                               \
 | 
						|
  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
 | 
						|
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
 | 
						|
  {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
 | 
						|
#include "clang/Basic/BuiltinsNEON.def"
 | 
						|
 | 
						|
#define BUILTIN(ID, TYPE, ATTRS)                                               \
 | 
						|
  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
 | 
						|
#define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
 | 
						|
  {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
 | 
						|
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
 | 
						|
  {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
 | 
						|
#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
 | 
						|
  {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
 | 
						|
#include "clang/Basic/BuiltinsARM.def"
 | 
						|
};
 | 
						|
 | 
						|
ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
 | 
						|
  return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
 | 
						|
                                             Builtin::FirstTSBuiltin);
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
 | 
						|
TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
 | 
						|
  return IsAAPCS
 | 
						|
             ? AAPCSABIBuiltinVaList
 | 
						|
             : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
 | 
						|
                                         : TargetInfo::VoidPtrBuiltinVaList);
 | 
						|
}
 | 
						|
 | 
						|
const char *const ARMTargetInfo::GCCRegNames[] = {
 | 
						|
    // Integer registers
 | 
						|
    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
 | 
						|
    "r12", "sp", "lr", "pc",
 | 
						|
 | 
						|
    // Float registers
 | 
						|
    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
 | 
						|
    "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
 | 
						|
    "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
 | 
						|
 | 
						|
    // Double registers
 | 
						|
    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
 | 
						|
    "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
 | 
						|
    "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
 | 
						|
 | 
						|
    // Quad registers
 | 
						|
    "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
 | 
						|
    "q12", "q13", "q14", "q15"};
 | 
						|
 | 
						|
ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
 | 
						|
  return llvm::makeArrayRef(GCCRegNames);
 | 
						|
}
 | 
						|
 | 
						|
const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
 | 
						|
    {{"a1"}, "r0"},  {{"a2"}, "r1"},        {{"a3"}, "r2"},  {{"a4"}, "r3"},
 | 
						|
    {{"v1"}, "r4"},  {{"v2"}, "r5"},        {{"v3"}, "r6"},  {{"v4"}, "r7"},
 | 
						|
    {{"v5"}, "r8"},  {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
 | 
						|
    {{"ip"}, "r12"}, {{"r13"}, "sp"},       {{"r14"}, "lr"}, {{"r15"}, "pc"},
 | 
						|
    // The S, D and Q registers overlap, but aren't really aliases; we
 | 
						|
    // don't want to substitute one of these for a different-sized one.
 | 
						|
};
 | 
						|
 | 
						|
ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
 | 
						|
  return llvm::makeArrayRef(GCCRegAliases);
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::validateAsmConstraint(
 | 
						|
    const char *&Name, TargetInfo::ConstraintInfo &Info) const {
 | 
						|
  switch (*Name) {
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  case 'l': // r0-r7 if thumb, r0-r15 if ARM
 | 
						|
    Info.setAllowsRegister();
 | 
						|
    return true;
 | 
						|
  case 'h': // r8-r15, thumb only
 | 
						|
    if (isThumb()) {
 | 
						|
      Info.setAllowsRegister();
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case 's': // An integer constant, but allowing only relocatable values.
 | 
						|
    return true;
 | 
						|
  case 't': // s0-s31, d0-d31, or q0-q15
 | 
						|
  case 'w': // s0-s15, d0-d7, or q0-q3
 | 
						|
  case 'x': // s0-s31, d0-d15, or q0-q7
 | 
						|
    Info.setAllowsRegister();
 | 
						|
    return true;
 | 
						|
  case 'j': // An immediate integer between 0 and 65535 (valid for MOVW)
 | 
						|
    // only available in ARMv6T2 and above
 | 
						|
    if (CPUAttr.equals("6T2") || ArchVersion >= 7) {
 | 
						|
      Info.setRequiresImmediate(0, 65535);
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case 'I':
 | 
						|
    if (isThumb()) {
 | 
						|
      if (!supportsThumb2())
 | 
						|
        Info.setRequiresImmediate(0, 255);
 | 
						|
      else
 | 
						|
        // FIXME: should check if immediate value would be valid for a Thumb2
 | 
						|
        // data-processing instruction
 | 
						|
        Info.setRequiresImmediate();
 | 
						|
    } else
 | 
						|
      // FIXME: should check if immediate value would be valid for an ARM
 | 
						|
      // data-processing instruction
 | 
						|
      Info.setRequiresImmediate();
 | 
						|
    return true;
 | 
						|
  case 'J':
 | 
						|
    if (isThumb() && !supportsThumb2())
 | 
						|
      Info.setRequiresImmediate(-255, -1);
 | 
						|
    else
 | 
						|
      Info.setRequiresImmediate(-4095, 4095);
 | 
						|
    return true;
 | 
						|
  case 'K':
 | 
						|
    if (isThumb()) {
 | 
						|
      if (!supportsThumb2())
 | 
						|
        // FIXME: should check if immediate value can be obtained from shifting
 | 
						|
        // a value between 0 and 255 left by any amount
 | 
						|
        Info.setRequiresImmediate();
 | 
						|
      else
 | 
						|
        // FIXME: should check if immediate value would be valid for a Thumb2
 | 
						|
        // data-processing instruction when inverted
 | 
						|
        Info.setRequiresImmediate();
 | 
						|
    } else
 | 
						|
      // FIXME: should check if immediate value would be valid for an ARM
 | 
						|
      // data-processing instruction when inverted
 | 
						|
      Info.setRequiresImmediate();
 | 
						|
    return true;
 | 
						|
  case 'L':
 | 
						|
    if (isThumb()) {
 | 
						|
      if (!supportsThumb2())
 | 
						|
        Info.setRequiresImmediate(-7, 7);
 | 
						|
      else
 | 
						|
        // FIXME: should check if immediate value would be valid for a Thumb2
 | 
						|
        // data-processing instruction when negated
 | 
						|
        Info.setRequiresImmediate();
 | 
						|
    } else
 | 
						|
      // FIXME: should check if immediate value  would be valid for an ARM
 | 
						|
      // data-processing instruction when negated
 | 
						|
      Info.setRequiresImmediate();
 | 
						|
    return true;
 | 
						|
  case 'M':
 | 
						|
    if (isThumb() && !supportsThumb2())
 | 
						|
      // FIXME: should check if immediate value is a multiple of 4 between 0 and
 | 
						|
      // 1020
 | 
						|
      Info.setRequiresImmediate();
 | 
						|
    else
 | 
						|
      // FIXME: should check if immediate value is a power of two or a integer
 | 
						|
      // between 0 and 32
 | 
						|
      Info.setRequiresImmediate();
 | 
						|
    return true;
 | 
						|
  case 'N':
 | 
						|
    // Thumb1 only
 | 
						|
    if (isThumb() && !supportsThumb2()) {
 | 
						|
      Info.setRequiresImmediate(0, 31);
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case 'O':
 | 
						|
    // Thumb1 only
 | 
						|
    if (isThumb() && !supportsThumb2()) {
 | 
						|
      // FIXME: should check if immediate value is a multiple of 4 between -508
 | 
						|
      // and 508
 | 
						|
      Info.setRequiresImmediate();
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case 'Q': // A memory address that is a single base register.
 | 
						|
    Info.setAllowsMemory();
 | 
						|
    return true;
 | 
						|
  case 'T':
 | 
						|
    switch (Name[1]) {
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    case 'e': // Even general-purpose register
 | 
						|
    case 'o': // Odd general-purpose register
 | 
						|
      Info.setAllowsRegister();
 | 
						|
      Name++;
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case 'U': // a memory reference...
 | 
						|
    switch (Name[1]) {
 | 
						|
    case 'q': // ...ARMV4 ldrsb
 | 
						|
    case 'v': // ...VFP load/store (reg+constant offset)
 | 
						|
    case 'y': // ...iWMMXt load/store
 | 
						|
    case 't': // address valid for load/store opaque types wider
 | 
						|
              // than 128-bits
 | 
						|
    case 'n': // valid address for Neon doubleword vector load/store
 | 
						|
    case 'm': // valid address for Neon element and structure load/store
 | 
						|
    case 's': // valid address for non-offset loads/stores of quad-word
 | 
						|
              // values in four ARM registers
 | 
						|
      Info.setAllowsMemory();
 | 
						|
      Name++;
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
 | 
						|
  std::string R;
 | 
						|
  switch (*Constraint) {
 | 
						|
  case 'U': // Two-character constraint; add "^" hint for later parsing.
 | 
						|
  case 'T':
 | 
						|
    R = std::string("^") + std::string(Constraint, 2);
 | 
						|
    Constraint++;
 | 
						|
    break;
 | 
						|
  case 'p': // 'p' should be translated to 'r' by default.
 | 
						|
    R = std::string("r");
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    return std::string(1, *Constraint);
 | 
						|
  }
 | 
						|
  return R;
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::validateConstraintModifier(
 | 
						|
    StringRef Constraint, char Modifier, unsigned Size,
 | 
						|
    std::string &SuggestedModifier) const {
 | 
						|
  bool isOutput = (Constraint[0] == '=');
 | 
						|
  bool isInOut = (Constraint[0] == '+');
 | 
						|
 | 
						|
  // Strip off constraint modifiers.
 | 
						|
  while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
 | 
						|
    Constraint = Constraint.substr(1);
 | 
						|
 | 
						|
  switch (Constraint[0]) {
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  case 'r': {
 | 
						|
    switch (Modifier) {
 | 
						|
    default:
 | 
						|
      return (isInOut || isOutput || Size <= 64);
 | 
						|
    case 'q':
 | 
						|
      // A register of size 32 cannot fit a vector type.
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
const char *ARMTargetInfo::getClobbers() const {
 | 
						|
  // FIXME: Is this really right?
 | 
						|
  return "";
 | 
						|
}
 | 
						|
 | 
						|
TargetInfo::CallingConvCheckResult
 | 
						|
ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
 | 
						|
  switch (CC) {
 | 
						|
  case CC_AAPCS:
 | 
						|
  case CC_AAPCS_VFP:
 | 
						|
  case CC_Swift:
 | 
						|
  case CC_OpenCLKernel:
 | 
						|
    return CCCR_OK;
 | 
						|
  default:
 | 
						|
    return CCCR_Warning;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
 | 
						|
  if (RegNo == 0)
 | 
						|
    return 0;
 | 
						|
  if (RegNo == 1)
 | 
						|
    return 1;
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
bool ARMTargetInfo::hasSjLjLowering() const { return true; }
 | 
						|
 | 
						|
ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
 | 
						|
                                 const TargetOptions &Opts)
 | 
						|
    : ARMTargetInfo(Triple, Opts) {}
 | 
						|
 | 
						|
void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
 | 
						|
                                       MacroBuilder &Builder) const {
 | 
						|
  Builder.defineMacro("__ARMEL__");
 | 
						|
  ARMTargetInfo::getTargetDefines(Opts, Builder);
 | 
						|
}
 | 
						|
 | 
						|
ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
 | 
						|
                                 const TargetOptions &Opts)
 | 
						|
    : ARMTargetInfo(Triple, Opts) {}
 | 
						|
 | 
						|
void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
 | 
						|
                                       MacroBuilder &Builder) const {
 | 
						|
  Builder.defineMacro("__ARMEB__");
 | 
						|
  Builder.defineMacro("__ARM_BIG_ENDIAN");
 | 
						|
  ARMTargetInfo::getTargetDefines(Opts, Builder);
 | 
						|
}
 | 
						|
 | 
						|
WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
 | 
						|
                                           const TargetOptions &Opts)
 | 
						|
    : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
 | 
						|
}
 | 
						|
 | 
						|
void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
 | 
						|
                                                  MacroBuilder &Builder) const {
 | 
						|
  // FIXME: this is invalid for WindowsCE
 | 
						|
  Builder.defineMacro("_M_ARM_NT", "1");
 | 
						|
  Builder.defineMacro("_M_ARMT", "_M_ARM");
 | 
						|
  Builder.defineMacro("_M_THUMB", "_M_ARM");
 | 
						|
 | 
						|
  assert((Triple.getArch() == llvm::Triple::arm ||
 | 
						|
          Triple.getArch() == llvm::Triple::thumb) &&
 | 
						|
         "invalid architecture for Windows ARM target info");
 | 
						|
  unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
 | 
						|
  Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
 | 
						|
 | 
						|
  // TODO map the complete set of values
 | 
						|
  // 31: VFPv3 40: VFPv4
 | 
						|
  Builder.defineMacro("_M_ARM_FP", "31");
 | 
						|
}
 | 
						|
 | 
						|
TargetInfo::BuiltinVaListKind
 | 
						|
WindowsARMTargetInfo::getBuiltinVaListKind() const {
 | 
						|
  return TargetInfo::CharPtrBuiltinVaList;
 | 
						|
}
 | 
						|
 | 
						|
TargetInfo::CallingConvCheckResult
 | 
						|
WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
 | 
						|
  switch (CC) {
 | 
						|
  case CC_X86StdCall:
 | 
						|
  case CC_X86ThisCall:
 | 
						|
  case CC_X86FastCall:
 | 
						|
  case CC_X86VectorCall:
 | 
						|
    return CCCR_Ignore;
 | 
						|
  case CC_C:
 | 
						|
  case CC_OpenCLKernel:
 | 
						|
  case CC_PreserveMost:
 | 
						|
  case CC_PreserveAll:
 | 
						|
  case CC_Swift:
 | 
						|
    return CCCR_OK;
 | 
						|
  default:
 | 
						|
    return CCCR_Warning;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Windows ARM + Itanium C++ ABI Target
 | 
						|
ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
 | 
						|
    const llvm::Triple &Triple, const TargetOptions &Opts)
 | 
						|
    : WindowsARMTargetInfo(Triple, Opts) {
 | 
						|
  TheCXXABI.set(TargetCXXABI::GenericARM);
 | 
						|
}
 | 
						|
 | 
						|
void ItaniumWindowsARMleTargetInfo::getTargetDefines(
 | 
						|
    const LangOptions &Opts, MacroBuilder &Builder) const {
 | 
						|
  WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
 | 
						|
 | 
						|
  if (Opts.MSVCCompat)
 | 
						|
    WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
 | 
						|
}
 | 
						|
 | 
						|
// Windows ARM, MS (C++) ABI
 | 
						|
MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
 | 
						|
                                                   const TargetOptions &Opts)
 | 
						|
    : WindowsARMTargetInfo(Triple, Opts) {
 | 
						|
  TheCXXABI.set(TargetCXXABI::Microsoft);
 | 
						|
}
 | 
						|
 | 
						|
void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
 | 
						|
                                                MacroBuilder &Builder) const {
 | 
						|
  WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
 | 
						|
  WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
 | 
						|
}
 | 
						|
 | 
						|
MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
 | 
						|
                                       const TargetOptions &Opts)
 | 
						|
    : WindowsARMTargetInfo(Triple, Opts) {
 | 
						|
  TheCXXABI.set(TargetCXXABI::GenericARM);
 | 
						|
}
 | 
						|
 | 
						|
void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
 | 
						|
                                          MacroBuilder &Builder) const {
 | 
						|
  WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
 | 
						|
  Builder.defineMacro("_ARM_");
 | 
						|
}
 | 
						|
 | 
						|
CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
 | 
						|
                                         const TargetOptions &Opts)
 | 
						|
    : ARMleTargetInfo(Triple, Opts) {
 | 
						|
  this->WCharType = TargetInfo::UnsignedShort;
 | 
						|
  TLSSupported = false;
 | 
						|
  DoubleAlign = LongLongAlign = 64;
 | 
						|
  resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
 | 
						|
}
 | 
						|
 | 
						|
void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
 | 
						|
                                           MacroBuilder &Builder) const {
 | 
						|
  ARMleTargetInfo::getTargetDefines(Opts, Builder);
 | 
						|
  Builder.defineMacro("_ARM_");
 | 
						|
  Builder.defineMacro("__CYGWIN__");
 | 
						|
  Builder.defineMacro("__CYGWIN32__");
 | 
						|
  DefineStd(Builder, "unix", Opts);
 | 
						|
  if (Opts.CPlusPlus)
 | 
						|
    Builder.defineMacro("_GNU_SOURCE");
 | 
						|
}
 | 
						|
 | 
						|
DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
 | 
						|
                                         const TargetOptions &Opts)
 | 
						|
    : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
 | 
						|
  HasAlignMac68kSupport = true;
 | 
						|
  // iOS always has 64-bit atomic instructions.
 | 
						|
  // FIXME: This should be based off of the target features in
 | 
						|
  // ARMleTargetInfo.
 | 
						|
  MaxAtomicInlineWidth = 64;
 | 
						|
 | 
						|
  if (Triple.isWatchABI()) {
 | 
						|
    // Darwin on iOS uses a variant of the ARM C++ ABI.
 | 
						|
    TheCXXABI.set(TargetCXXABI::WatchOS);
 | 
						|
 | 
						|
    // BOOL should be a real boolean on the new ABI
 | 
						|
    UseSignedCharForObjCBool = false;
 | 
						|
  } else
 | 
						|
    TheCXXABI.set(TargetCXXABI::iOS);
 | 
						|
}
 | 
						|
 | 
						|
void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
 | 
						|
                                       const llvm::Triple &Triple,
 | 
						|
                                       MacroBuilder &Builder) const {
 | 
						|
  getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
 | 
						|
}
 | 
						|
 | 
						|
RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,
 | 
						|
                                                   const TargetOptions &Opts)
 | 
						|
    : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
 | 
						|
                                   Triple.getOSName(),
 | 
						|
                                   Triple.getEnvironmentName()),
 | 
						|
                      Opts) {
 | 
						|
  IsRenderScriptTarget = true;
 | 
						|
  LongWidth = LongAlign = 64;
 | 
						|
}
 | 
						|
 | 
						|
void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
 | 
						|
                                                MacroBuilder &Builder) const {
 | 
						|
  Builder.defineMacro("__RENDERSCRIPT__");
 | 
						|
  ARMleTargetInfo::getTargetDefines(Opts, Builder);
 | 
						|
}
 |