#include "AArch64.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/AArch64TargetParser.h"
using namespace clang;
using namespace clang::targets;
const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsNEON.def"
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsSVE.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 TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
{#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
#include "clang/Basic/BuiltinsAArch64.def"
};
static StringRef getArchVersionString(llvm::AArch64::ArchKind Kind) {
switch (Kind) {
case llvm::AArch64::ArchKind::ARMV9A:
case llvm::AArch64::ArchKind::ARMV9_1A:
case llvm::AArch64::ArchKind::ARMV9_2A:
case llvm::AArch64::ArchKind::ARMV9_3A:
return "9";
default:
return "8";
}
}
StringRef AArch64TargetInfo::getArchProfile() const {
switch (ArchKind) {
case llvm::AArch64::ArchKind::ARMV8R:
return "R";
default:
return "A";
}
}
AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), ABI("aapcs") {
if (getTriple().isOSOpenBSD()) {
Int64Type = SignedLongLong;
IntMaxType = SignedLongLong;
} else {
if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
WCharType = UnsignedInt;
Int64Type = SignedLong;
IntMaxType = SignedLong;
}
HasLegalHalfType = true;
HasFloat16 = true;
if (Triple.isArch64Bit())
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
else
LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
MaxVectorAlign = 128;
MaxAtomicInlineWidth = 128;
MaxAtomicPromoteWidth = 128;
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad();
BFloat16Width = BFloat16Align = 16;
BFloat16Format = &llvm::APFloat::BFloat();
HasBuiltinMSVaList = true;
HasAArch64SVETypes = true;
NoAsmVariants = true;
assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
UseZeroLengthBitfieldAlignment = true;
TheCXXABI.set(TargetCXXABI::GenericAArch64);
if (Triple.getOS() == llvm::Triple::Linux)
this->MCountName = "\01_mcount";
else if (Triple.getOS() == llvm::Triple::UnknownOS)
this->MCountName =
Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
}
StringRef AArch64TargetInfo::getABI() const { return ABI; }
bool AArch64TargetInfo::setABI(const std::string &Name) {
if (Name != "aapcs" && Name != "darwinpcs")
return false;
ABI = Name;
return true;
}
bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
BranchProtectionInfo &BPI,
StringRef &Err) const {
llvm::ARM::ParsedBranchProtection PBP;
if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err))
return false;
BPI.SignReturnAddr =
llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
.Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)
.Case("all", LangOptions::SignReturnAddressScopeKind::All)
.Default(LangOptions::SignReturnAddressScopeKind::None);
if (PBP.Key == "a_key")
BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;
else
BPI.SignKey = LangOptions::SignReturnAddressKeyKind::BKey;
BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
return true;
}
bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
return Name == "generic" ||
llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
}
bool AArch64TargetInfo::setCPU(const std::string &Name) {
return isValidCPUName(Name);
}
void AArch64TargetInfo::fillValidCPUList(
SmallVectorImpl<StringRef> &Values) const {
llvm::AArch64::fillValidCPUArchList(Values);
}
void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
}
void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
MacroBuilder &Builder) const {
getTargetDefinesARMV81A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
Builder.defineMacro("__ARM_FEATURE_JCVT", "1");
getTargetDefinesARMV82A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
MacroBuilder &Builder) const {
getTargetDefinesARMV83A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARM_FEATURE_FRINT", "1");
getTargetDefinesARMV84A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV86A(const LangOptions &Opts,
MacroBuilder &Builder) const {
getTargetDefinesARMV85A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV87A(const LangOptions &Opts,
MacroBuilder &Builder) const {
getTargetDefinesARMV86A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV88A(const LangOptions &Opts,
MacroBuilder &Builder) const {
getTargetDefinesARMV87A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV9A(const LangOptions &Opts,
MacroBuilder &Builder) const {
getTargetDefinesARMV85A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV91A(const LangOptions &Opts,
MacroBuilder &Builder) const {
getTargetDefinesARMV86A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV92A(const LangOptions &Opts,
MacroBuilder &Builder) const {
getTargetDefinesARMV87A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefinesARMV93A(const LangOptions &Opts,
MacroBuilder &Builder) const {
getTargetDefinesARMV88A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__aarch64__");
if (getTriple().getOS() == llvm::Triple::UnknownOS &&
getTriple().isOSBinFormatELF())
Builder.defineMacro("__ELF__");
if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) {
Builder.defineMacro("_LP64");
Builder.defineMacro("__LP64__");
}
std::string CodeModel = getTargetOpts().CodeModel;
if (CodeModel == "default")
CodeModel = "small";
for (char &c : CodeModel)
c = toupper(c);
Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__");
Builder.defineMacro("__ARM_ACLE", "200");
Builder.defineMacro("__ARM_ARCH", getArchVersionString(ArchKind));
Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + getArchProfile() + "'");
Builder.defineMacro("__ARM_64BIT_STATE", "1");
Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
Builder.defineMacro("__ARM_FEATURE_FMA", "1");
Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); Builder.defineMacro("__ARM_FEATURE_DIV"); Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
Builder.defineMacro("__ARM_FP", "0xE");
Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
Builder.defineMacro("__ARM_FP16_ARGS", "1");
if (Opts.UnsafeFPMath)
Builder.defineMacro("__ARM_FP_FAST", "1");
Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
Twine(Opts.WCharSize ? Opts.WCharSize : 4));
Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
if (FPU & NeonMode) {
Builder.defineMacro("__ARM_NEON", "1");
Builder.defineMacro("__ARM_NEON_FP", "0xE");
}
if (FPU & SveMode)
Builder.defineMacro("__ARM_FEATURE_SVE", "1");
if ((FPU & NeonMode) && (FPU & SveMode))
Builder.defineMacro("__ARM_NEON_SVE_BRIDGE", "1");
if (HasSVE2)
Builder.defineMacro("__ARM_FEATURE_SVE2", "1");
if (HasSVE2 && HasSVE2AES)
Builder.defineMacro("__ARM_FEATURE_SVE2_AES", "1");
if (HasSVE2 && HasSVE2BitPerm)
Builder.defineMacro("__ARM_FEATURE_SVE2_BITPERM", "1");
if (HasSVE2 && HasSVE2SHA3)
Builder.defineMacro("__ARM_FEATURE_SVE2_SHA3", "1");
if (HasSVE2 && HasSVE2SM4)
Builder.defineMacro("__ARM_FEATURE_SVE2_SM4", "1");
if (HasCRC)
Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
if (HasAES && HasSHA2)
Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
if (HasAES)
Builder.defineMacro("__ARM_FEATURE_AES", "1");
if (HasSHA2)
Builder.defineMacro("__ARM_FEATURE_SHA2", "1");
if (HasSHA3) {
Builder.defineMacro("__ARM_FEATURE_SHA3", "1");
Builder.defineMacro("__ARM_FEATURE_SHA512", "1");
}
if (HasSM4) {
Builder.defineMacro("__ARM_FEATURE_SM3", "1");
Builder.defineMacro("__ARM_FEATURE_SM4", "1");
}
if (HasUnaligned)
Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
if ((FPU & NeonMode) && HasFullFP16)
Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
if (HasFullFP16)
Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
if (HasDotProd)
Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
if (HasMTE)
Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1");
if (HasTME)
Builder.defineMacro("__ARM_FEATURE_TME", "1");
if (HasMatMul)
Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");
if (HasLSE)
Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
if (HasBFloat16) {
Builder.defineMacro("__ARM_FEATURE_BF16", "1");
Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1");
Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");
Builder.defineMacro("__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", "1");
}
if ((FPU & SveMode) && HasBFloat16) {
Builder.defineMacro("__ARM_FEATURE_SVE_BF16", "1");
}
if ((FPU & SveMode) && HasMatmulFP64)
Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP64", "1");
if ((FPU & SveMode) && HasMatmulFP32)
Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP32", "1");
if ((FPU & SveMode) && HasMatMul)
Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_INT8", "1");
if ((FPU & NeonMode) && HasFP16FML)
Builder.defineMacro("__ARM_FEATURE_FP16_FML", "1");
if (Opts.hasSignReturnAddress()) {
unsigned Value = 0;
if (Opts.isSignReturnAddressWithAKey())
Value |= (1 << 0);
else
Value |= (1 << 1);
if (Opts.isSignReturnAddressScopeAll())
Value |= (1 << 2);
Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", std::to_string(Value));
}
if (Opts.BranchTargetEnforcement)
Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");
if (HasLS64)
Builder.defineMacro("__ARM_FEATURE_LS64", "1");
if (HasRandGen)
Builder.defineMacro("__ARM_FEATURE_RNG", "1");
if (HasMOPS)
Builder.defineMacro("__ARM_FEATURE_MOPS", "1");
switch (ArchKind) {
default:
break;
case llvm::AArch64::ArchKind::ARMV8_1A:
getTargetDefinesARMV81A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV8_2A:
getTargetDefinesARMV82A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV8_3A:
getTargetDefinesARMV83A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV8_4A:
getTargetDefinesARMV84A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV8_5A:
getTargetDefinesARMV85A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV8_6A:
getTargetDefinesARMV86A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV8_7A:
getTargetDefinesARMV87A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV8_8A:
getTargetDefinesARMV88A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV9A:
getTargetDefinesARMV9A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV9_1A:
getTargetDefinesARMV91A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV9_2A:
getTargetDefinesARMV92A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV9_3A:
getTargetDefinesARMV93A(Opts, Builder);
break;
}
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");
Builder.defineMacro("__FP_FAST_FMA", "1");
Builder.defineMacro("__FP_FAST_FMAF", "1");
if (FPU & SveMode)
Builder.defineMacro("__ARM_FEATURE_SVE_VECTOR_OPERATORS", "2");
if (Opts.VScaleMin && Opts.VScaleMin == Opts.VScaleMax) {
Builder.defineMacro("__ARM_FEATURE_SVE_BITS", Twine(Opts.VScaleMin * 128));
}
}
ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
Builtin::FirstTSBuiltin);
}
Optional<std::pair<unsigned, unsigned>>
AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts) const {
if (LangOpts.VScaleMin || LangOpts.VScaleMax)
return std::pair<unsigned, unsigned>(
LangOpts.VScaleMin ? LangOpts.VScaleMin : 1, LangOpts.VScaleMax);
if (hasFeature("sve"))
return std::pair<unsigned, unsigned>(1, 16);
return None;
}
bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Cases("aarch64", "arm64", "arm", true)
.Case("neon", FPU & NeonMode)
.Cases("sve", "sve2", "sve2-bitperm", "sve2-aes", "sve2-sha3", "sve2-sm4", "f64mm", "f32mm", "i8mm", "bf16", FPU & SveMode)
.Case("ls64", HasLS64)
.Default(false);
}
bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) {
FPU = FPUMode;
HasCRC = false;
HasAES = false;
HasSHA2 = false;
HasSHA3 = false;
HasSM4 = false;
HasUnaligned = true;
HasFullFP16 = false;
HasDotProd = false;
HasFP16FML = false;
HasMTE = false;
HasTME = false;
HasLS64 = false;
HasRandGen = false;
HasMatMul = false;
HasBFloat16 = false;
HasSVE2 = false;
HasSVE2AES = false;
HasSVE2SHA3 = false;
HasSVE2SM4 = false;
HasSVE2BitPerm = false;
HasMatmulFP64 = false;
HasMatmulFP32 = false;
HasLSE = false;
HasMOPS = false;
ArchKind = llvm::AArch64::ArchKind::INVALID;
for (const auto &Feature : Features) {
if (Feature == "+neon")
FPU |= NeonMode;
if (Feature == "+sve") {
FPU |= SveMode;
HasFullFP16 = true;
}
if (Feature == "+sve2") {
FPU |= SveMode;
HasFullFP16 = true;
HasSVE2 = true;
}
if (Feature == "+sve2-aes") {
FPU |= SveMode;
HasFullFP16 = true;
HasSVE2 = true;
HasSVE2AES = true;
}
if (Feature == "+sve2-sha3") {
FPU |= SveMode;
HasFullFP16 = true;
HasSVE2 = true;
HasSVE2SHA3 = true;
}
if (Feature == "+sve2-sm4") {
FPU |= SveMode;
HasFullFP16 = true;
HasSVE2 = true;
HasSVE2SM4 = true;
}
if (Feature == "+sve2-bitperm") {
FPU |= SveMode;
HasFullFP16 = true;
HasSVE2 = true;
HasSVE2BitPerm = true;
}
if (Feature == "+f32mm") {
FPU |= SveMode;
HasMatmulFP32 = true;
}
if (Feature == "+f64mm") {
FPU |= SveMode;
HasMatmulFP64 = true;
}
if (Feature == "+crc")
HasCRC = true;
if (Feature == "+aes")
HasAES = true;
if (Feature == "+sha2")
HasSHA2 = true;
if (Feature == "+sha3") {
HasSHA2 = true;
HasSHA3 = true;
}
if (Feature == "+sm4")
HasSM4 = true;
if (Feature == "+strict-align")
HasUnaligned = false;
if (Feature == "+v8a")
ArchKind = llvm::AArch64::ArchKind::ARMV8A;
if (Feature == "+v8.1a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
if (Feature == "+v8.2a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
if (Feature == "+v8.3a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_3A;
if (Feature == "+v8.4a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_4A;
if (Feature == "+v8.5a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_5A;
if (Feature == "+v8.6a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_6A;
if (Feature == "+v8.7a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_7A;
if (Feature == "+v8.8a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_8A;
if (Feature == "+v9a")
ArchKind = llvm::AArch64::ArchKind::ARMV9A;
if (Feature == "+v9.1a")
ArchKind = llvm::AArch64::ArchKind::ARMV9_1A;
if (Feature == "+v9.2a")
ArchKind = llvm::AArch64::ArchKind::ARMV9_2A;
if (Feature == "+v9.3a")
ArchKind = llvm::AArch64::ArchKind::ARMV9_3A;
if (Feature == "+v8r")
ArchKind = llvm::AArch64::ArchKind::ARMV8R;
if (Feature == "+fullfp16")
HasFullFP16 = true;
if (Feature == "+dotprod")
HasDotProd = true;
if (Feature == "+fp16fml")
HasFP16FML = true;
if (Feature == "+mte")
HasMTE = true;
if (Feature == "+tme")
HasTME = true;
if (Feature == "+pauth")
HasPAuth = true;
if (Feature == "+i8mm")
HasMatMul = true;
if (Feature == "+bf16")
HasBFloat16 = true;
if (Feature == "+lse")
HasLSE = true;
if (Feature == "+ls64")
HasLS64 = true;
if (Feature == "+rand")
HasRandGen = true;
if (Feature == "+flagm")
HasFlagM = true;
if (Feature == "+mops")
HasMOPS = true;
}
setDataLayout();
return true;
}
TargetInfo::CallingConvCheckResult
AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
switch (CC) {
case CC_C:
case CC_Swift:
case CC_SwiftAsync:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_OpenCLKernel:
case CC_AArch64VectorCall:
case CC_AArch64SVEPCS:
case CC_Win64:
return CCCR_OK;
default:
return CCCR_Warning;
}
}
bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
return TargetInfo::AArch64ABIBuiltinVaList;
}
const char *const AArch64TargetInfo::GCCRegNames[] = {
"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
"w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
"w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
"x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
"x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
"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",
"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",
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
"v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
"v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
"z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10",
"z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21",
"z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10",
"p11", "p12", "p13", "p14", "p15"
};
ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}
const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
{{"w31"}, "wsp"},
{{"x31"}, "sp"},
{{"r0"}, "x0"},
{{"r1"}, "x1"},
{{"r2"}, "x2"},
{{"r3"}, "x3"},
{{"r4"}, "x4"},
{{"r5"}, "x5"},
{{"r6"}, "x6"},
{{"r7"}, "x7"},
{{"r8"}, "x8"},
{{"r9"}, "x9"},
{{"r10"}, "x10"},
{{"r11"}, "x11"},
{{"r12"}, "x12"},
{{"r13"}, "x13"},
{{"r14"}, "x14"},
{{"r15"}, "x15"},
{{"r16"}, "x16"},
{{"r17"}, "x17"},
{{"r18"}, "x18"},
{{"r19"}, "x19"},
{{"r20"}, "x20"},
{{"r21"}, "x21"},
{{"r22"}, "x22"},
{{"r23"}, "x23"},
{{"r24"}, "x24"},
{{"r25"}, "x25"},
{{"r26"}, "x26"},
{{"r27"}, "x27"},
{{"r28"}, "x28"},
{{"r29", "x29"}, "fp"},
{{"r30", "x30"}, "lr"},
};
ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
return llvm::makeArrayRef(GCCRegAliases);
}
bool AArch64TargetInfo::validateAsmConstraint(
const char *&Name, TargetInfo::ConstraintInfo &Info) const {
switch (*Name) {
default:
return false;
case 'w': Info.setAllowsRegister();
return true;
case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'Y': case 'Z': return true;
case 'Q': Info.setAllowsMemory();
return true;
case 'S': Info.setAllowsRegister();
return true;
case 'U':
if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) {
Info.setAllowsRegister();
Name += 2;
return true;
}
return false;
case 'z': Info.setAllowsRegister();
return true;
case 'x': Info.setAllowsRegister();
return true;
case 'y': Info.setAllowsRegister();
return true;
}
return false;
}
bool AArch64TargetInfo::validateConstraintModifier(
StringRef Constraint, char Modifier, unsigned Size,
std::string &SuggestedModifier) const {
while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
Constraint = Constraint.substr(1);
switch (Constraint[0]) {
default:
return true;
case 'z':
case 'r': {
switch (Modifier) {
case 'x':
case 'w':
return true;
default:
if (Size == 64)
return true;
if (Size == 512)
return HasLS64;
SuggestedModifier = "w";
return false;
}
}
}
}
const char *AArch64TargetInfo::getClobbers() const { return ""; }
int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
if (RegNo == 0)
return 0;
if (RegNo == 1)
return 1;
return -1;
}
bool AArch64TargetInfo::hasInt128Type() const { return true; }
AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: AArch64TargetInfo(Triple, Opts) {}
void AArch64leTargetInfo::setDataLayout() {
if (getTriple().isOSBinFormatMachO()) {
if(getTriple().isArch32Bit())
resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128", "_");
else
resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128", "_");
} else
resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
}
void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__AARCH64EL__");
AArch64TargetInfo::getTargetDefines(Opts, Builder);
}
AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: AArch64TargetInfo(Triple, Opts) {}
void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__AARCH64EB__");
Builder.defineMacro("__AARCH_BIG_ENDIAN");
Builder.defineMacro("__ARM_BIG_ENDIAN");
AArch64TargetInfo::getTargetDefines(Opts, Builder);
}
void AArch64beTargetInfo::setDataLayout() {
assert(!getTriple().isOSBinFormatMachO());
resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
}
WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 32;
DoubleAlign = LongLongAlign = 64;
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
IntMaxType = SignedLongLong;
Int64Type = SignedLongLong;
SizeType = UnsignedLongLong;
PtrDiffType = SignedLongLong;
IntPtrType = SignedLongLong;
}
void WindowsARM64TargetInfo::setDataLayout() {
resetDataLayout(Triple.isOSBinFormatMachO()
? "e-m:o-i64:64-i128:128-n32:64-S128"
: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128",
Triple.isOSBinFormatMachO() ? "_" : "");
}
TargetInfo::BuiltinVaListKind
WindowsARM64TargetInfo::getBuiltinVaListKind() const {
return TargetInfo::CharPtrBuiltinVaList;
}
TargetInfo::CallingConvCheckResult
WindowsARM64TargetInfo::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:
case CC_SwiftAsync:
case CC_Win64:
return CCCR_OK;
default:
return CCCR_Warning;
}
}
MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsARM64TargetInfo(Triple, Opts) {
TheCXXABI.set(TargetCXXABI::Microsoft);
}
void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
Builder.defineMacro("_M_ARM64", "1");
}
TargetInfo::CallingConvKind
MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
return CCK_MicrosoftWin64;
}
unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const {
unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize);
if (TypeSize >= 512) { Align = std::max(Align, 128u); } else if (TypeSize >= 64) { Align = std::max(Align, 64u); } else if (TypeSize >= 16) { Align = std::max(Align, 32u); }
return Align;
}
MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsARM64TargetInfo(Triple, Opts) {
TheCXXABI.set(TargetCXXABI::GenericAArch64);
}
DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
Int64Type = SignedLongLong;
if (getTriple().isArch32Bit())
IntMaxType = SignedLongLong;
WCharType = SignedInt;
UseSignedCharForObjCBool = false;
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
UseZeroLengthBitfieldAlignment = false;
if (getTriple().isArch32Bit()) {
UseBitFieldTypeAlignment = false;
ZeroLengthBitfieldBoundary = 32;
UseZeroLengthBitfieldAlignment = true;
TheCXXABI.set(TargetCXXABI::WatchOS);
} else
TheCXXABI.set(TargetCXXABI::AppleARM64);
}
void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
const llvm::Triple &Triple,
MacroBuilder &Builder) const {
Builder.defineMacro("__AARCH64_SIMD__");
if (Triple.isArch32Bit())
Builder.defineMacro("__ARM64_ARCH_8_32__");
else
Builder.defineMacro("__ARM64_ARCH_8__");
Builder.defineMacro("__ARM_NEON__");
Builder.defineMacro("__LITTLE_ENDIAN__");
Builder.defineMacro("__REGISTER_PREFIX__", "");
Builder.defineMacro("__arm64", "1");
Builder.defineMacro("__arm64__", "1");
if (Triple.isArm64e())
Builder.defineMacro("__arm64e__", "1");
getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
}
TargetInfo::BuiltinVaListKind
DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
return TargetInfo::CharPtrBuiltinVaList;
}
RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
Triple.getOSName(),
Triple.getEnvironmentName()),
Opts) {
IsRenderScriptTarget = true;
}
void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__RENDERSCRIPT__");
AArch64leTargetInfo::getTargetDefines(Opts, Builder);
}