mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[ARM, AArch64] Move ARM/AArch64 target parsers into
separate files to enable future changes. This moves ARM and AArch64 target parsing into their own files. They are still accessible through TargetParser.h as before. Several functions in AArch64 which were just forwarders to ARM have been removed. All except AArch64::getFPUName were unused, and that was only used in a test. Which itself was overlapping one in ARM, so it has also been removed. Differential revision: https://reviews.llvm.org/D53980 llvm-svn: 347741
This commit is contained in:
parent
ea9fed10ed
commit
c8642ec8b2
121
include/llvm/Support/AArch64TargetParser.h
Normal file
121
include/llvm/Support/AArch64TargetParser.h
Normal file
@ -0,0 +1,121 @@
|
||||
//===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a target parser to recognise AArch64 hardware features
|
||||
// such as FPU/CPU/ARCH and extension names.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_AARCH64TARGETPARSERCOMMON_H
|
||||
#define LLVM_SUPPORT_AARCH64TARGETPARSERCOMMON_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/ARMTargetParser.h"
|
||||
#include <vector>
|
||||
|
||||
// FIXME:This should be made into class design,to avoid dupplication.
|
||||
namespace llvm {
|
||||
namespace AArch64 {
|
||||
|
||||
// Arch extension modifiers for CPUs.
|
||||
enum ArchExtKind : unsigned {
|
||||
AEK_INVALID = 0,
|
||||
AEK_NONE = 1,
|
||||
AEK_CRC = 1 << 1,
|
||||
AEK_CRYPTO = 1 << 2,
|
||||
AEK_FP = 1 << 3,
|
||||
AEK_SIMD = 1 << 4,
|
||||
AEK_FP16 = 1 << 5,
|
||||
AEK_PROFILE = 1 << 6,
|
||||
AEK_RAS = 1 << 7,
|
||||
AEK_LSE = 1 << 8,
|
||||
AEK_SVE = 1 << 9,
|
||||
AEK_DOTPROD = 1 << 10,
|
||||
AEK_RCPC = 1 << 11,
|
||||
AEK_RDM = 1 << 12,
|
||||
AEK_SM4 = 1 << 13,
|
||||
AEK_SHA3 = 1 << 14,
|
||||
AEK_SHA2 = 1 << 15,
|
||||
AEK_AES = 1 << 16,
|
||||
AEK_FP16FML = 1 << 17,
|
||||
AEK_RAND = 1 << 18,
|
||||
AEK_MTE = 1 << 19,
|
||||
};
|
||||
|
||||
enum class ArchKind {
|
||||
#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID,
|
||||
#include "AArch64TargetParser.def"
|
||||
};
|
||||
|
||||
const ARM::ArchNames<ArchKind> AArch64ARCHNames[] = {
|
||||
#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, \
|
||||
ARCH_BASE_EXT) \
|
||||
{NAME, \
|
||||
sizeof(NAME) - 1, \
|
||||
CPU_ATTR, \
|
||||
sizeof(CPU_ATTR) - 1, \
|
||||
SUB_ARCH, \
|
||||
sizeof(SUB_ARCH) - 1, \
|
||||
ARM::FPUKind::ARCH_FPU, \
|
||||
ARCH_BASE_EXT, \
|
||||
AArch64::ArchKind::ID, \
|
||||
ARCH_ATTR},
|
||||
#include "AArch64TargetParser.def"
|
||||
};
|
||||
|
||||
const ARM::ExtName AArch64ARCHExtNames[] = {
|
||||
#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
|
||||
{NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE},
|
||||
#include "AArch64TargetParser.def"
|
||||
};
|
||||
|
||||
const ARM::CpuNames<ArchKind> AArch64CPUNames[] = {
|
||||
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
{NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT},
|
||||
#include "AArch64TargetParser.def"
|
||||
};
|
||||
|
||||
const ArchKind ArchKinds[] = {
|
||||
#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \
|
||||
ArchKind::ID,
|
||||
#include "AArch64TargetParser.def"
|
||||
};
|
||||
|
||||
// FIXME: These should be moved to TargetTuple once it exists
|
||||
bool getExtensionFeatures(unsigned Extensions,
|
||||
std::vector<StringRef> &Features);
|
||||
bool getArchFeatures(ArchKind AK, std::vector<StringRef> &Features);
|
||||
|
||||
StringRef getArchName(ArchKind AK);
|
||||
unsigned getArchAttr(ArchKind AK);
|
||||
StringRef getCPUAttr(ArchKind AK);
|
||||
StringRef getSubArch(ArchKind AK);
|
||||
StringRef getArchExtName(unsigned ArchExtKind);
|
||||
StringRef getArchExtFeature(StringRef ArchExt);
|
||||
|
||||
// Information by Name
|
||||
unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
|
||||
unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
|
||||
StringRef getDefaultCPU(StringRef Arch);
|
||||
ArchKind getCPUArchKind(StringRef CPU);
|
||||
|
||||
// Parser
|
||||
ArchKind parseArch(StringRef Arch);
|
||||
ArchExtKind parseArchExt(StringRef ArchExt);
|
||||
ArchKind parseCPUArch(StringRef CPU);
|
||||
// Used by target parser tests
|
||||
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
|
||||
|
||||
bool isX18ReservedByDefault(const Triple &TT);
|
||||
|
||||
} // namespace AArch64
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
262
include/llvm/Support/ARMTargetParser.h
Normal file
262
include/llvm/Support/ARMTargetParser.h
Normal file
@ -0,0 +1,262 @@
|
||||
//===-- ARMTargetParser - Parser for ARM target features --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a target parser to recognise ARM hardware features
|
||||
// such as FPU/CPU/ARCH/extensions and specific support such as HWDIV.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_ARMTARGETPARSER_H
|
||||
#define LLVM_SUPPORT_ARMTARGETPARSER_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/ARMBuildAttributes.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace ARM {
|
||||
|
||||
// Arch extension modifiers for CPUs.
|
||||
// Note that this is not the same as the AArch64 list
|
||||
enum ArchExtKind : unsigned {
|
||||
AEK_INVALID = 0,
|
||||
AEK_NONE = 1,
|
||||
AEK_CRC = 1 << 1,
|
||||
AEK_CRYPTO = 1 << 2,
|
||||
AEK_FP = 1 << 3,
|
||||
AEK_HWDIVTHUMB = 1 << 4,
|
||||
AEK_HWDIVARM = 1 << 5,
|
||||
AEK_MP = 1 << 6,
|
||||
AEK_SIMD = 1 << 7,
|
||||
AEK_SEC = 1 << 8,
|
||||
AEK_VIRT = 1 << 9,
|
||||
AEK_DSP = 1 << 10,
|
||||
AEK_FP16 = 1 << 11,
|
||||
AEK_RAS = 1 << 12,
|
||||
AEK_SVE = 1 << 13,
|
||||
AEK_DOTPROD = 1 << 14,
|
||||
AEK_SHA2 = 1 << 15,
|
||||
AEK_AES = 1 << 16,
|
||||
AEK_FP16FML = 1 << 17,
|
||||
// Unsupported extensions.
|
||||
AEK_OS = 0x8000000,
|
||||
AEK_IWMMXT = 0x10000000,
|
||||
AEK_IWMMXT2 = 0x20000000,
|
||||
AEK_MAVERICK = 0x40000000,
|
||||
AEK_XSCALE = 0x80000000,
|
||||
};
|
||||
|
||||
// List of Arch Extension names.
|
||||
// FIXME: TableGen this.
|
||||
struct ExtName {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
unsigned ID;
|
||||
const char *Feature;
|
||||
const char *NegFeature;
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
};
|
||||
|
||||
const ExtName ARCHExtNames[] = {
|
||||
#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
|
||||
{NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE},
|
||||
#include "ARMTargetParser.def"
|
||||
};
|
||||
|
||||
// List of HWDiv names (use getHWDivSynonym) and which architectural
|
||||
// features they correspond to (use getHWDivFeatures).
|
||||
// FIXME: TableGen this.
|
||||
const struct {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
unsigned ID;
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
} HWDivNames[] = {
|
||||
#define ARM_HW_DIV_NAME(NAME, ID) {NAME, sizeof(NAME) - 1, ID},
|
||||
#include "ARMTargetParser.def"
|
||||
};
|
||||
|
||||
// Arch names.
|
||||
enum class ArchKind {
|
||||
#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID,
|
||||
#include "ARMTargetParser.def"
|
||||
};
|
||||
|
||||
// List of CPU names and their arches.
|
||||
// The same CPU can have multiple arches and can be default on multiple arches.
|
||||
// When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
|
||||
// When this becomes table-generated, we'd probably need two tables.
|
||||
// FIXME: TableGen this.
|
||||
template <typename T> struct CpuNames {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
T ArchID;
|
||||
bool Default; // is $Name the default CPU for $ArchID ?
|
||||
unsigned DefaultExtensions;
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
};
|
||||
|
||||
const CpuNames<ArchKind> CPUNames[] = {
|
||||
#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
{NAME, sizeof(NAME) - 1, ARM::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT},
|
||||
#include "ARMTargetParser.def"
|
||||
};
|
||||
|
||||
// FPU names.
|
||||
enum FPUKind {
|
||||
#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) KIND,
|
||||
#include "ARMTargetParser.def"
|
||||
FK_LAST
|
||||
};
|
||||
|
||||
// FPU Version
|
||||
enum class FPUVersion {
|
||||
NONE,
|
||||
VFPV2,
|
||||
VFPV3,
|
||||
VFPV3_FP16,
|
||||
VFPV4,
|
||||
VFPV5
|
||||
};
|
||||
|
||||
// An FPU name restricts the FPU in one of three ways:
|
||||
enum class FPURestriction {
|
||||
None = 0, ///< No restriction
|
||||
D16, ///< Only 16 D registers
|
||||
SP_D16 ///< Only single-precision instructions, with 16 D registers
|
||||
};
|
||||
|
||||
// An FPU name implies one of three levels of Neon support:
|
||||
enum class NeonSupportLevel {
|
||||
None = 0, ///< No Neon
|
||||
Neon, ///< Neon
|
||||
Crypto ///< Neon with Crypto
|
||||
};
|
||||
|
||||
// ISA kinds.
|
||||
enum class ISAKind { INVALID = 0, ARM, THUMB, AARCH64 };
|
||||
|
||||
// Endianness
|
||||
// FIXME: BE8 vs. BE32?
|
||||
enum class EndianKind { INVALID = 0, LITTLE, BIG };
|
||||
|
||||
// v6/v7/v8 Profile
|
||||
enum class ProfileKind { INVALID = 0, A, R, M };
|
||||
|
||||
// List of canonical FPU names (use getFPUSynonym) and which architectural
|
||||
// features they correspond to (use getFPUFeatures).
|
||||
// FIXME: TableGen this.
|
||||
// The entries must appear in the order listed in ARM::FPUKind for correct
|
||||
// indexing
|
||||
struct FPUName {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
FPUKind ID;
|
||||
FPUVersion FPUVer;
|
||||
NeonSupportLevel NeonSupport;
|
||||
FPURestriction Restriction;
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
};
|
||||
|
||||
static const FPUName FPUNames[] = {
|
||||
#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
|
||||
{NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION},
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
};
|
||||
|
||||
// List of canonical arch names (use getArchSynonym).
|
||||
// This table also provides the build attribute fields for CPU arch
|
||||
// and Arch ID, according to the Addenda to the ARM ABI, chapters
|
||||
// 2.4 and 2.3.5.2 respectively.
|
||||
// FIXME: SubArch values were simplified to fit into the expectations
|
||||
// of the triples and are not conforming with their official names.
|
||||
// Check to see if the expectation should be changed.
|
||||
// FIXME: TableGen this.
|
||||
template <typename T> struct ArchNames {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
const char *CPUAttrCStr;
|
||||
size_t CPUAttrLength;
|
||||
const char *SubArchCStr;
|
||||
size_t SubArchLength;
|
||||
unsigned DefaultFPU;
|
||||
unsigned ArchBaseExtensions;
|
||||
T ID;
|
||||
ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
|
||||
// CPU class in build attributes.
|
||||
StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
|
||||
|
||||
// Sub-Arch name.
|
||||
StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
|
||||
};
|
||||
|
||||
static const ArchNames<ArchKind> ARCHNames[] = {
|
||||
#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, \
|
||||
ARCH_BASE_EXT) \
|
||||
{NAME, sizeof(NAME) - 1, \
|
||||
CPU_ATTR, sizeof(CPU_ATTR) - 1, \
|
||||
SUB_ARCH, sizeof(SUB_ARCH) - 1, \
|
||||
ARCH_FPU, ARCH_BASE_EXT, \
|
||||
ArchKind::ID, ARCH_ATTR},
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
};
|
||||
|
||||
// Information by ID
|
||||
StringRef getFPUName(unsigned FPUKind);
|
||||
FPUVersion getFPUVersion(unsigned FPUKind);
|
||||
NeonSupportLevel getFPUNeonSupportLevel(unsigned FPUKind);
|
||||
FPURestriction getFPURestriction(unsigned FPUKind);
|
||||
|
||||
// FIXME: These should be moved to TargetTuple once it exists
|
||||
bool getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features);
|
||||
bool getHWDivFeatures(unsigned HWDivKind, std::vector<StringRef> &Features);
|
||||
bool getExtensionFeatures(unsigned Extensions,
|
||||
std::vector<StringRef> &Features);
|
||||
|
||||
StringRef getArchName(ArchKind AK);
|
||||
unsigned getArchAttr(ArchKind AK);
|
||||
StringRef getCPUAttr(ArchKind AK);
|
||||
StringRef getSubArch(ArchKind AK);
|
||||
StringRef getArchExtName(unsigned ArchExtKind);
|
||||
StringRef getArchExtFeature(StringRef ArchExt);
|
||||
StringRef getHWDivName(unsigned HWDivKind);
|
||||
|
||||
// Information by Name
|
||||
unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
|
||||
unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
|
||||
StringRef getDefaultCPU(StringRef Arch);
|
||||
StringRef getCanonicalArchName(StringRef Arch);
|
||||
StringRef getFPUSynonym(StringRef FPU);
|
||||
StringRef getArchSynonym(StringRef Arch);
|
||||
|
||||
// Parser
|
||||
unsigned parseHWDiv(StringRef HWDiv);
|
||||
unsigned parseFPU(StringRef FPU);
|
||||
ArchKind parseArch(StringRef Arch);
|
||||
unsigned parseArchExt(StringRef ArchExt);
|
||||
ArchKind parseCPUArch(StringRef CPU);
|
||||
ISAKind parseArchISA(StringRef Arch);
|
||||
EndianKind parseArchEndian(StringRef Arch);
|
||||
ProfileKind parseArchProfile(StringRef Arch);
|
||||
unsigned parseArchVersion(StringRef Arch);
|
||||
|
||||
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
|
||||
StringRef computeDefaultTargetABI(const Triple &TT, StringRef CPU);
|
||||
|
||||
} // namespace ARM
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -18,215 +18,20 @@
|
||||
// FIXME: vector is used because that's what clang uses for subtarget feature
|
||||
// lists, but SmallVector would probably be better
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/ARMTargetParser.h"
|
||||
#include "llvm/Support/AArch64TargetParser.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class StringRef;
|
||||
|
||||
// Target specific information into their own namespaces. These should be
|
||||
// generated from TableGen because the information is already there, and there
|
||||
// is where new information about targets will be added.
|
||||
// Target specific information in their own namespaces.
|
||||
// (ARM/AArch64 are declared in ARM/AArch64TargetParser.h)
|
||||
// These should be generated from TableGen because the information is already
|
||||
// there, and there is where new information about targets will be added.
|
||||
// FIXME: To TableGen this we need to make some table generated files available
|
||||
// even if the back-end is not compiled with LLVM, plus we need to create a new
|
||||
// back-end to TableGen to create these clean tables.
|
||||
namespace ARM {
|
||||
|
||||
// FPU Version
|
||||
enum class FPUVersion {
|
||||
NONE,
|
||||
VFPV2,
|
||||
VFPV3,
|
||||
VFPV3_FP16,
|
||||
VFPV4,
|
||||
VFPV5
|
||||
};
|
||||
|
||||
// An FPU name restricts the FPU in one of three ways:
|
||||
enum class FPURestriction {
|
||||
None = 0, ///< No restriction
|
||||
D16, ///< Only 16 D registers
|
||||
SP_D16 ///< Only single-precision instructions, with 16 D registers
|
||||
};
|
||||
|
||||
// An FPU name implies one of three levels of Neon support:
|
||||
enum class NeonSupportLevel {
|
||||
None = 0, ///< No Neon
|
||||
Neon, ///< Neon
|
||||
Crypto ///< Neon with Crypto
|
||||
};
|
||||
|
||||
// FPU names.
|
||||
enum FPUKind {
|
||||
#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) KIND,
|
||||
#include "ARMTargetParser.def"
|
||||
FK_LAST
|
||||
};
|
||||
|
||||
// Arch names.
|
||||
enum class ArchKind {
|
||||
#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID,
|
||||
#include "ARMTargetParser.def"
|
||||
};
|
||||
|
||||
// Arch extension modifiers for CPUs.
|
||||
enum ArchExtKind : unsigned {
|
||||
AEK_INVALID = 0,
|
||||
AEK_NONE = 1,
|
||||
AEK_CRC = 1 << 1,
|
||||
AEK_CRYPTO = 1 << 2,
|
||||
AEK_FP = 1 << 3,
|
||||
AEK_HWDIVTHUMB = 1 << 4,
|
||||
AEK_HWDIVARM = 1 << 5,
|
||||
AEK_MP = 1 << 6,
|
||||
AEK_SIMD = 1 << 7,
|
||||
AEK_SEC = 1 << 8,
|
||||
AEK_VIRT = 1 << 9,
|
||||
AEK_DSP = 1 << 10,
|
||||
AEK_FP16 = 1 << 11,
|
||||
AEK_RAS = 1 << 12,
|
||||
AEK_SVE = 1 << 13,
|
||||
AEK_DOTPROD = 1 << 14,
|
||||
AEK_SHA2 = 1 << 15,
|
||||
AEK_AES = 1 << 16,
|
||||
AEK_FP16FML = 1 << 17,
|
||||
// Unsupported extensions.
|
||||
AEK_OS = 0x8000000,
|
||||
AEK_IWMMXT = 0x10000000,
|
||||
AEK_IWMMXT2 = 0x20000000,
|
||||
AEK_MAVERICK = 0x40000000,
|
||||
AEK_XSCALE = 0x80000000,
|
||||
};
|
||||
|
||||
// ISA kinds.
|
||||
enum class ISAKind { INVALID = 0, ARM, THUMB, AARCH64 };
|
||||
|
||||
// Endianness
|
||||
// FIXME: BE8 vs. BE32?
|
||||
enum class EndianKind { INVALID = 0, LITTLE, BIG };
|
||||
|
||||
// v6/v7/v8 Profile
|
||||
enum class ProfileKind { INVALID = 0, A, R, M };
|
||||
|
||||
StringRef getCanonicalArchName(StringRef Arch);
|
||||
|
||||
// Information by ID
|
||||
StringRef getFPUName(unsigned FPUKind);
|
||||
FPUVersion getFPUVersion(unsigned FPUKind);
|
||||
NeonSupportLevel getFPUNeonSupportLevel(unsigned FPUKind);
|
||||
FPURestriction getFPURestriction(unsigned FPUKind);
|
||||
|
||||
// FIXME: These should be moved to TargetTuple once it exists
|
||||
bool getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features);
|
||||
bool getHWDivFeatures(unsigned HWDivKind, std::vector<StringRef> &Features);
|
||||
bool getExtensionFeatures(unsigned Extensions,
|
||||
std::vector<StringRef> &Features);
|
||||
|
||||
StringRef getArchName(ArchKind AK);
|
||||
unsigned getArchAttr(ArchKind AK);
|
||||
StringRef getCPUAttr(ArchKind AK);
|
||||
StringRef getSubArch(ArchKind AK);
|
||||
StringRef getArchExtName(unsigned ArchExtKind);
|
||||
StringRef getArchExtFeature(StringRef ArchExt);
|
||||
StringRef getHWDivName(unsigned HWDivKind);
|
||||
|
||||
// Information by Name
|
||||
unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
|
||||
unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
|
||||
StringRef getDefaultCPU(StringRef Arch);
|
||||
|
||||
// Parser
|
||||
unsigned parseHWDiv(StringRef HWDiv);
|
||||
unsigned parseFPU(StringRef FPU);
|
||||
ArchKind parseArch(StringRef Arch);
|
||||
unsigned parseArchExt(StringRef ArchExt);
|
||||
ArchKind parseCPUArch(StringRef CPU);
|
||||
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
|
||||
ISAKind parseArchISA(StringRef Arch);
|
||||
EndianKind parseArchEndian(StringRef Arch);
|
||||
ProfileKind parseArchProfile(StringRef Arch);
|
||||
unsigned parseArchVersion(StringRef Arch);
|
||||
|
||||
StringRef computeDefaultTargetABI(const Triple &TT, StringRef CPU);
|
||||
|
||||
} // namespace ARM
|
||||
|
||||
// FIXME:This should be made into class design,to avoid dupplication.
|
||||
namespace AArch64 {
|
||||
|
||||
// Arch names.
|
||||
enum class ArchKind {
|
||||
#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID,
|
||||
#include "AArch64TargetParser.def"
|
||||
};
|
||||
|
||||
// Arch extension modifiers for CPUs.
|
||||
enum ArchExtKind : unsigned {
|
||||
AEK_INVALID = 0,
|
||||
AEK_NONE = 1,
|
||||
AEK_CRC = 1 << 1,
|
||||
AEK_CRYPTO = 1 << 2,
|
||||
AEK_FP = 1 << 3,
|
||||
AEK_SIMD = 1 << 4,
|
||||
AEK_FP16 = 1 << 5,
|
||||
AEK_PROFILE = 1 << 6,
|
||||
AEK_RAS = 1 << 7,
|
||||
AEK_LSE = 1 << 8,
|
||||
AEK_SVE = 1 << 9,
|
||||
AEK_DOTPROD = 1 << 10,
|
||||
AEK_RCPC = 1 << 11,
|
||||
AEK_RDM = 1 << 12,
|
||||
AEK_SM4 = 1 << 13,
|
||||
AEK_SHA3 = 1 << 14,
|
||||
AEK_SHA2 = 1 << 15,
|
||||
AEK_AES = 1 << 16,
|
||||
AEK_FP16FML = 1 << 17,
|
||||
AEK_RAND = 1 << 18,
|
||||
AEK_MTE = 1 << 19,
|
||||
};
|
||||
|
||||
StringRef getCanonicalArchName(StringRef Arch);
|
||||
|
||||
// Information by ID
|
||||
StringRef getFPUName(unsigned FPUKind);
|
||||
ARM::FPUVersion getFPUVersion(unsigned FPUKind);
|
||||
ARM::NeonSupportLevel getFPUNeonSupportLevel(unsigned FPUKind);
|
||||
ARM::FPURestriction getFPURestriction(unsigned FPUKind);
|
||||
|
||||
// FIXME: These should be moved to TargetTuple once it exists
|
||||
bool getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features);
|
||||
bool getExtensionFeatures(unsigned Extensions,
|
||||
std::vector<StringRef> &Features);
|
||||
bool getArchFeatures(ArchKind AK, std::vector<StringRef> &Features);
|
||||
|
||||
StringRef getArchName(ArchKind AK);
|
||||
unsigned getArchAttr(ArchKind AK);
|
||||
StringRef getCPUAttr(ArchKind AK);
|
||||
StringRef getSubArch(ArchKind AK);
|
||||
StringRef getArchExtName(unsigned ArchExtKind);
|
||||
StringRef getArchExtFeature(StringRef ArchExt);
|
||||
unsigned checkArchVersion(StringRef Arch);
|
||||
|
||||
// Information by Name
|
||||
unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
|
||||
unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
|
||||
StringRef getDefaultCPU(StringRef Arch);
|
||||
AArch64::ArchKind getCPUArchKind(StringRef CPU);
|
||||
|
||||
// Parser
|
||||
unsigned parseFPU(StringRef FPU);
|
||||
AArch64::ArchKind parseArch(StringRef Arch);
|
||||
ArchExtKind parseArchExt(StringRef ArchExt);
|
||||
ArchKind parseCPUArch(StringRef CPU);
|
||||
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
|
||||
ARM::ISAKind parseArchISA(StringRef Arch);
|
||||
ARM::EndianKind parseArchEndian(StringRef Arch);
|
||||
ARM::ProfileKind parseArchProfile(StringRef Arch);
|
||||
unsigned parseArchVersion(StringRef Arch);
|
||||
|
||||
bool isX18ReservedByDefault(const Triple &TT);
|
||||
|
||||
} // namespace AArch64
|
||||
|
||||
namespace X86 {
|
||||
|
||||
// This should be kept in sync with libcc/compiler-rt as its included by clang
|
||||
|
206
lib/Support/AArch64TargetParser.cpp
Normal file
206
lib/Support/AArch64TargetParser.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
//===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a target parser to recognise AArch64 hardware features
|
||||
// such as FPU/CPU/ARCH and extension names.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/AArch64TargetParser.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include <cctype>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static unsigned checkArchVersion(llvm::StringRef Arch) {
|
||||
if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
|
||||
return (Arch[1] - 48);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned AArch64::getDefaultFPU(StringRef CPU, AArch64::ArchKind AK) {
|
||||
if (CPU == "generic")
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
|
||||
|
||||
return StringSwitch<unsigned>(CPU)
|
||||
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, ARM::DEFAULT_FPU)
|
||||
#include "../../include/llvm/Support/AArch64TargetParser.def"
|
||||
.Default(ARM::FK_INVALID);
|
||||
}
|
||||
|
||||
unsigned AArch64::getDefaultExtensions(StringRef CPU, AArch64::ArchKind AK) {
|
||||
if (CPU == "generic")
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
|
||||
|
||||
return StringSwitch<unsigned>(CPU)
|
||||
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, AArch64ARCHNames[static_cast<unsigned>(ArchKind::ID)] \
|
||||
.ArchBaseExtensions | \
|
||||
DEFAULT_EXT)
|
||||
#include "../../include/llvm/Support/AArch64TargetParser.def"
|
||||
.Default(AArch64::AEK_INVALID);
|
||||
}
|
||||
|
||||
AArch64::ArchKind AArch64::getCPUArchKind(StringRef CPU) {
|
||||
if (CPU == "generic")
|
||||
return ArchKind::ARMV8A;
|
||||
|
||||
return StringSwitch<AArch64::ArchKind>(CPU)
|
||||
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, ArchKind::ID)
|
||||
#include "../../include/llvm/Support/AArch64TargetParser.def"
|
||||
.Default(ArchKind::INVALID);
|
||||
}
|
||||
|
||||
bool AArch64::getExtensionFeatures(unsigned Extensions,
|
||||
std::vector<StringRef> &Features) {
|
||||
if (Extensions == AArch64::AEK_INVALID)
|
||||
return false;
|
||||
|
||||
if (Extensions & AEK_FP)
|
||||
Features.push_back("+fp-armv8");
|
||||
if (Extensions & AEK_SIMD)
|
||||
Features.push_back("+neon");
|
||||
if (Extensions & AEK_CRC)
|
||||
Features.push_back("+crc");
|
||||
if (Extensions & AEK_CRYPTO)
|
||||
Features.push_back("+crypto");
|
||||
if (Extensions & AEK_DOTPROD)
|
||||
Features.push_back("+dotprod");
|
||||
if (Extensions & AEK_FP16FML)
|
||||
Features.push_back("+fp16fml");
|
||||
if (Extensions & AEK_FP16)
|
||||
Features.push_back("+fullfp16");
|
||||
if (Extensions & AEK_PROFILE)
|
||||
Features.push_back("+spe");
|
||||
if (Extensions & AEK_RAS)
|
||||
Features.push_back("+ras");
|
||||
if (Extensions & AEK_LSE)
|
||||
Features.push_back("+lse");
|
||||
if (Extensions & AEK_RDM)
|
||||
Features.push_back("+rdm");
|
||||
if (Extensions & AEK_SVE)
|
||||
Features.push_back("+sve");
|
||||
if (Extensions & AEK_RCPC)
|
||||
Features.push_back("+rcpc");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AArch64::getArchFeatures(AArch64::ArchKind AK,
|
||||
std::vector<StringRef> &Features) {
|
||||
if (AK == ArchKind::ARMV8_1A)
|
||||
Features.push_back("+v8.1a");
|
||||
if (AK == ArchKind::ARMV8_2A)
|
||||
Features.push_back("+v8.2a");
|
||||
if (AK == ArchKind::ARMV8_3A)
|
||||
Features.push_back("+v8.3a");
|
||||
if (AK == ArchKind::ARMV8_4A)
|
||||
Features.push_back("+v8.4a");
|
||||
if (AK == ArchKind::ARMV8_5A)
|
||||
Features.push_back("+v8.5a");
|
||||
|
||||
return AK != ArchKind::INVALID;
|
||||
}
|
||||
|
||||
StringRef AArch64::getArchName(AArch64::ArchKind AK) {
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].getName();
|
||||
}
|
||||
|
||||
StringRef AArch64::getCPUAttr(AArch64::ArchKind AK) {
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
|
||||
}
|
||||
|
||||
StringRef AArch64::getSubArch(AArch64::ArchKind AK) {
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch();
|
||||
}
|
||||
|
||||
unsigned AArch64::getArchAttr(AArch64::ArchKind AK) {
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
|
||||
}
|
||||
|
||||
StringRef AArch64::getArchExtName(unsigned ArchExtKind) {
|
||||
for (const auto &AE : AArch64ARCHExtNames)
|
||||
if (ArchExtKind == AE.ID)
|
||||
return AE.getName();
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
|
||||
if (ArchExt.startswith("no")) {
|
||||
StringRef ArchExtBase(ArchExt.substr(2));
|
||||
for (const auto &AE : AArch64ARCHExtNames) {
|
||||
if (AE.NegFeature && ArchExtBase == AE.getName())
|
||||
return StringRef(AE.NegFeature);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &AE : AArch64ARCHExtNames)
|
||||
if (AE.Feature && ArchExt == AE.getName())
|
||||
return StringRef(AE.Feature);
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef AArch64::getDefaultCPU(StringRef Arch) {
|
||||
ArchKind AK = parseArch(Arch);
|
||||
if (AK == ArchKind::INVALID)
|
||||
return StringRef();
|
||||
|
||||
// Look for multiple AKs to find the default for pair AK+Name.
|
||||
for (const auto &CPU : AArch64CPUNames)
|
||||
if (CPU.ArchID == AK && CPU.Default)
|
||||
return CPU.getName();
|
||||
|
||||
// If we can't find a default then target the architecture instead
|
||||
return "generic";
|
||||
}
|
||||
|
||||
void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
|
||||
for (const auto &Arch : AArch64CPUNames) {
|
||||
if (Arch.ArchID != ArchKind::INVALID)
|
||||
Values.push_back(Arch.getName());
|
||||
}
|
||||
}
|
||||
|
||||
bool AArch64::isX18ReservedByDefault(const Triple &TT) {
|
||||
return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
|
||||
TT.isOSWindows();
|
||||
}
|
||||
|
||||
// Allows partial match, ex. "v8a" matches "armv8a".
|
||||
AArch64::ArchKind AArch64::parseArch(StringRef Arch) {
|
||||
Arch = ARM::getCanonicalArchName(Arch);
|
||||
if (checkArchVersion(Arch) < 8)
|
||||
return ArchKind::INVALID;
|
||||
|
||||
StringRef Syn = ARM::getArchSynonym(Arch);
|
||||
for (const auto A : AArch64ARCHNames) {
|
||||
if (A.getName().endswith(Syn))
|
||||
return A.ID;
|
||||
}
|
||||
return ArchKind::INVALID;
|
||||
}
|
||||
|
||||
AArch64::ArchExtKind AArch64::parseArchExt(StringRef ArchExt) {
|
||||
for (const auto A : AArch64ARCHExtNames) {
|
||||
if (ArchExt == A.getName())
|
||||
return static_cast<ArchExtKind>(A.ID);
|
||||
}
|
||||
return AArch64::AEK_INVALID;
|
||||
}
|
||||
|
||||
AArch64::ArchKind AArch64::parseCPUArch(StringRef CPU) {
|
||||
for (const auto C : AArch64CPUNames) {
|
||||
if (CPU == C.getName())
|
||||
return C.ArchID;
|
||||
}
|
||||
return ArchKind::INVALID;
|
||||
}
|
576
lib/Support/ARMTargetParser.cpp
Normal file
576
lib/Support/ARMTargetParser.cpp
Normal file
@ -0,0 +1,576 @@
|
||||
//===-- ARMTargetParser - Parser for ARM target features --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a target parser to recognise ARM hardware features
|
||||
// such as FPU/CPU/ARCH/extensions and specific support such as HWDIV.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/ARMTargetParser.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static StringRef getHWDivSynonym(StringRef HWDiv) {
|
||||
return StringSwitch<StringRef>(HWDiv)
|
||||
.Case("thumb,arm", "arm,thumb")
|
||||
.Default(HWDiv);
|
||||
}
|
||||
|
||||
// Allows partial match, ex. "v7a" matches "armv7a".
|
||||
ARM::ArchKind ARM::parseArch(StringRef Arch) {
|
||||
Arch = getCanonicalArchName(Arch);
|
||||
StringRef Syn = getArchSynonym(Arch);
|
||||
for (const auto A : ARCHNames) {
|
||||
if (A.getName().endswith(Syn))
|
||||
return A.ID;
|
||||
}
|
||||
return ArchKind::INVALID;
|
||||
}
|
||||
|
||||
// Version number (ex. v7 = 7).
|
||||
unsigned ARM::parseArchVersion(StringRef Arch) {
|
||||
Arch = getCanonicalArchName(Arch);
|
||||
switch (parseArch(Arch)) {
|
||||
case ArchKind::ARMV2:
|
||||
case ArchKind::ARMV2A:
|
||||
return 2;
|
||||
case ArchKind::ARMV3:
|
||||
case ArchKind::ARMV3M:
|
||||
return 3;
|
||||
case ArchKind::ARMV4:
|
||||
case ArchKind::ARMV4T:
|
||||
return 4;
|
||||
case ArchKind::ARMV5T:
|
||||
case ArchKind::ARMV5TE:
|
||||
case ArchKind::IWMMXT:
|
||||
case ArchKind::IWMMXT2:
|
||||
case ArchKind::XSCALE:
|
||||
case ArchKind::ARMV5TEJ:
|
||||
return 5;
|
||||
case ArchKind::ARMV6:
|
||||
case ArchKind::ARMV6K:
|
||||
case ArchKind::ARMV6T2:
|
||||
case ArchKind::ARMV6KZ:
|
||||
case ArchKind::ARMV6M:
|
||||
return 6;
|
||||
case ArchKind::ARMV7A:
|
||||
case ArchKind::ARMV7VE:
|
||||
case ArchKind::ARMV7R:
|
||||
case ArchKind::ARMV7M:
|
||||
case ArchKind::ARMV7S:
|
||||
case ArchKind::ARMV7EM:
|
||||
case ArchKind::ARMV7K:
|
||||
return 7;
|
||||
case ArchKind::ARMV8A:
|
||||
case ArchKind::ARMV8_1A:
|
||||
case ArchKind::ARMV8_2A:
|
||||
case ArchKind::ARMV8_3A:
|
||||
case ArchKind::ARMV8_4A:
|
||||
case ArchKind::ARMV8_5A:
|
||||
case ArchKind::ARMV8R:
|
||||
case ArchKind::ARMV8MBaseline:
|
||||
case ArchKind::ARMV8MMainline:
|
||||
return 8;
|
||||
case ArchKind::INVALID:
|
||||
return 0;
|
||||
}
|
||||
llvm_unreachable("Unhandled architecture");
|
||||
}
|
||||
|
||||
// Profile A/R/M
|
||||
ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) {
|
||||
Arch = getCanonicalArchName(Arch);
|
||||
switch (parseArch(Arch)) {
|
||||
case ArchKind::ARMV6M:
|
||||
case ArchKind::ARMV7M:
|
||||
case ArchKind::ARMV7EM:
|
||||
case ArchKind::ARMV8MMainline:
|
||||
case ArchKind::ARMV8MBaseline:
|
||||
return ProfileKind::M;
|
||||
case ArchKind::ARMV7R:
|
||||
case ArchKind::ARMV8R:
|
||||
return ProfileKind::R;
|
||||
case ArchKind::ARMV7A:
|
||||
case ArchKind::ARMV7VE:
|
||||
case ArchKind::ARMV7K:
|
||||
case ArchKind::ARMV8A:
|
||||
case ArchKind::ARMV8_1A:
|
||||
case ArchKind::ARMV8_2A:
|
||||
case ArchKind::ARMV8_3A:
|
||||
case ArchKind::ARMV8_4A:
|
||||
case ArchKind::ARMV8_5A:
|
||||
return ProfileKind::A;
|
||||
case ArchKind::ARMV2:
|
||||
case ArchKind::ARMV2A:
|
||||
case ArchKind::ARMV3:
|
||||
case ArchKind::ARMV3M:
|
||||
case ArchKind::ARMV4:
|
||||
case ArchKind::ARMV4T:
|
||||
case ArchKind::ARMV5T:
|
||||
case ArchKind::ARMV5TE:
|
||||
case ArchKind::ARMV5TEJ:
|
||||
case ArchKind::ARMV6:
|
||||
case ArchKind::ARMV6K:
|
||||
case ArchKind::ARMV6T2:
|
||||
case ArchKind::ARMV6KZ:
|
||||
case ArchKind::ARMV7S:
|
||||
case ArchKind::IWMMXT:
|
||||
case ArchKind::IWMMXT2:
|
||||
case ArchKind::XSCALE:
|
||||
case ArchKind::INVALID:
|
||||
return ProfileKind::INVALID;
|
||||
}
|
||||
llvm_unreachable("Unhandled architecture");
|
||||
}
|
||||
|
||||
StringRef ARM::getArchSynonym(StringRef Arch) {
|
||||
return StringSwitch<StringRef>(Arch)
|
||||
.Case("v5", "v5t")
|
||||
.Case("v5e", "v5te")
|
||||
.Case("v6j", "v6")
|
||||
.Case("v6hl", "v6k")
|
||||
.Cases("v6m", "v6sm", "v6s-m", "v6-m")
|
||||
.Cases("v6z", "v6zk", "v6kz")
|
||||
.Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
|
||||
.Case("v7r", "v7-r")
|
||||
.Case("v7m", "v7-m")
|
||||
.Case("v7em", "v7e-m")
|
||||
.Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a")
|
||||
.Case("v8.1a", "v8.1-a")
|
||||
.Case("v8.2a", "v8.2-a")
|
||||
.Case("v8.3a", "v8.3-a")
|
||||
.Case("v8.4a", "v8.4-a")
|
||||
.Case("v8.5a", "v8.5-a")
|
||||
.Case("v8r", "v8-r")
|
||||
.Case("v8m.base", "v8-m.base")
|
||||
.Case("v8m.main", "v8-m.main")
|
||||
.Default(Arch);
|
||||
}
|
||||
|
||||
bool ARM::getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features) {
|
||||
|
||||
if (FPUKind >= FK_LAST || FPUKind == FK_INVALID)
|
||||
return false;
|
||||
|
||||
// fp-only-sp and d16 subtarget features are independent of each other, so we
|
||||
// must enable/disable both.
|
||||
switch (FPUNames[FPUKind].Restriction) {
|
||||
case FPURestriction::SP_D16:
|
||||
Features.push_back("+fp-only-sp");
|
||||
Features.push_back("+d16");
|
||||
break;
|
||||
case FPURestriction::D16:
|
||||
Features.push_back("-fp-only-sp");
|
||||
Features.push_back("+d16");
|
||||
break;
|
||||
case FPURestriction::None:
|
||||
Features.push_back("-fp-only-sp");
|
||||
Features.push_back("-d16");
|
||||
break;
|
||||
}
|
||||
|
||||
// FPU version subtarget features are inclusive of lower-numbered ones, so
|
||||
// enable the one corresponding to this version and disable all that are
|
||||
// higher. We also have to make sure to disable fp16 when vfp4 is disabled,
|
||||
// as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
|
||||
switch (FPUNames[FPUKind].FPUVer) {
|
||||
case FPUVersion::VFPV5:
|
||||
Features.push_back("+fp-armv8");
|
||||
break;
|
||||
case FPUVersion::VFPV4:
|
||||
Features.push_back("+vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
case FPUVersion::VFPV3_FP16:
|
||||
Features.push_back("+vfp3");
|
||||
Features.push_back("+fp16");
|
||||
Features.push_back("-vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
case FPUVersion::VFPV3:
|
||||
Features.push_back("+vfp3");
|
||||
Features.push_back("-fp16");
|
||||
Features.push_back("-vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
case FPUVersion::VFPV2:
|
||||
Features.push_back("+vfp2");
|
||||
Features.push_back("-vfp3");
|
||||
Features.push_back("-fp16");
|
||||
Features.push_back("-vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
case FPUVersion::NONE:
|
||||
Features.push_back("-vfp2");
|
||||
Features.push_back("-vfp3");
|
||||
Features.push_back("-fp16");
|
||||
Features.push_back("-vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
}
|
||||
|
||||
// crypto includes neon, so we handle this similarly to FPU version.
|
||||
switch (FPUNames[FPUKind].NeonSupport) {
|
||||
case NeonSupportLevel::Crypto:
|
||||
Features.push_back("+neon");
|
||||
Features.push_back("+crypto");
|
||||
break;
|
||||
case NeonSupportLevel::Neon:
|
||||
Features.push_back("+neon");
|
||||
Features.push_back("-crypto");
|
||||
break;
|
||||
case NeonSupportLevel::None:
|
||||
Features.push_back("-neon");
|
||||
Features.push_back("-crypto");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Little/Big endian
|
||||
ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {
|
||||
if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
|
||||
Arch.startswith("aarch64_be"))
|
||||
return EndianKind::BIG;
|
||||
|
||||
if (Arch.startswith("arm") || Arch.startswith("thumb")) {
|
||||
if (Arch.endswith("eb"))
|
||||
return EndianKind::BIG;
|
||||
else
|
||||
return EndianKind::LITTLE;
|
||||
}
|
||||
|
||||
if (Arch.startswith("aarch64"))
|
||||
return EndianKind::LITTLE;
|
||||
|
||||
return EndianKind::INVALID;
|
||||
}
|
||||
|
||||
// ARM, Thumb, AArch64
|
||||
ARM::ISAKind ARM::parseArchISA(StringRef Arch) {
|
||||
return StringSwitch<ISAKind>(Arch)
|
||||
.StartsWith("aarch64", ISAKind::AARCH64)
|
||||
.StartsWith("arm64", ISAKind::AARCH64)
|
||||
.StartsWith("thumb", ISAKind::THUMB)
|
||||
.StartsWith("arm", ISAKind::ARM)
|
||||
.Default(ISAKind::INVALID);
|
||||
}
|
||||
|
||||
unsigned ARM::parseFPU(StringRef FPU) {
|
||||
StringRef Syn = getFPUSynonym(FPU);
|
||||
for (const auto F : FPUNames) {
|
||||
if (Syn == F.getName())
|
||||
return F.ID;
|
||||
}
|
||||
return FK_INVALID;
|
||||
}
|
||||
|
||||
ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
|
||||
if (FPUKind >= FK_LAST)
|
||||
return NeonSupportLevel::None;
|
||||
return FPUNames[FPUKind].NeonSupport;
|
||||
}
|
||||
|
||||
// MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
|
||||
// (iwmmxt|xscale)(eb)? is also permitted. If the former, return
|
||||
// "v.+", if the latter, return unmodified string, minus 'eb'.
|
||||
// If invalid, return empty string.
|
||||
StringRef ARM::getCanonicalArchName(StringRef Arch) {
|
||||
size_t offset = StringRef::npos;
|
||||
StringRef A = Arch;
|
||||
StringRef Error = "";
|
||||
|
||||
// Begins with "arm" / "thumb", move past it.
|
||||
if (A.startswith("arm64"))
|
||||
offset = 5;
|
||||
else if (A.startswith("arm"))
|
||||
offset = 3;
|
||||
else if (A.startswith("thumb"))
|
||||
offset = 5;
|
||||
else if (A.startswith("aarch64")) {
|
||||
offset = 7;
|
||||
// AArch64 uses "_be", not "eb" suffix.
|
||||
if (A.find("eb") != StringRef::npos)
|
||||
return Error;
|
||||
if (A.substr(offset, 3) == "_be")
|
||||
offset += 3;
|
||||
}
|
||||
|
||||
// Ex. "armebv7", move past the "eb".
|
||||
if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
|
||||
offset += 2;
|
||||
// Or, if it ends with eb ("armv7eb"), chop it off.
|
||||
else if (A.endswith("eb"))
|
||||
A = A.substr(0, A.size() - 2);
|
||||
// Trim the head
|
||||
if (offset != StringRef::npos)
|
||||
A = A.substr(offset);
|
||||
|
||||
// Empty string means offset reached the end, which means it's valid.
|
||||
if (A.empty())
|
||||
return Arch;
|
||||
|
||||
// Only match non-marketing names
|
||||
if (offset != StringRef::npos) {
|
||||
// Must start with 'vN'.
|
||||
if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1])))
|
||||
return Error;
|
||||
// Can't have an extra 'eb'.
|
||||
if (A.find("eb") != StringRef::npos)
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Arch will either be a 'v' name (v7a) or a marketing name (xscale).
|
||||
return A;
|
||||
}
|
||||
|
||||
StringRef ARM::getFPUSynonym(StringRef FPU) {
|
||||
return StringSwitch<StringRef>(FPU)
|
||||
.Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
|
||||
.Case("vfp2", "vfpv2")
|
||||
.Case("vfp3", "vfpv3")
|
||||
.Case("vfp4", "vfpv4")
|
||||
.Case("vfp3-d16", "vfpv3-d16")
|
||||
.Case("vfp4-d16", "vfpv4-d16")
|
||||
.Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
|
||||
.Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
|
||||
.Case("fp5-sp-d16", "fpv5-sp-d16")
|
||||
.Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
|
||||
// FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
|
||||
.Case("neon-vfpv3", "neon")
|
||||
.Default(FPU);
|
||||
}
|
||||
|
||||
StringRef ARM::getFPUName(unsigned FPUKind) {
|
||||
if (FPUKind >= FK_LAST)
|
||||
return StringRef();
|
||||
return FPUNames[FPUKind].getName();
|
||||
}
|
||||
|
||||
ARM::FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
|
||||
if (FPUKind >= FK_LAST)
|
||||
return FPUVersion::NONE;
|
||||
return FPUNames[FPUKind].FPUVer;
|
||||
}
|
||||
|
||||
ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
|
||||
if (FPUKind >= FK_LAST)
|
||||
return FPURestriction::None;
|
||||
return FPUNames[FPUKind].Restriction;
|
||||
}
|
||||
|
||||
unsigned ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
|
||||
if (CPU == "generic")
|
||||
return ARM::ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
|
||||
|
||||
return StringSwitch<unsigned>(CPU)
|
||||
#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, DEFAULT_FPU)
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
.Default(ARM::FK_INVALID);
|
||||
}
|
||||
|
||||
unsigned ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) {
|
||||
if (CPU == "generic")
|
||||
return ARM::ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
|
||||
|
||||
return StringSwitch<unsigned>(CPU)
|
||||
#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, \
|
||||
ARCHNames[static_cast<unsigned>(ArchKind::ID)].ArchBaseExtensions | \
|
||||
DEFAULT_EXT)
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
.Default(ARM::AEK_INVALID);
|
||||
}
|
||||
|
||||
bool ARM::getHWDivFeatures(unsigned HWDivKind,
|
||||
std::vector<StringRef> &Features) {
|
||||
|
||||
if (HWDivKind == AEK_INVALID)
|
||||
return false;
|
||||
|
||||
if (HWDivKind & AEK_HWDIVARM)
|
||||
Features.push_back("+hwdiv-arm");
|
||||
else
|
||||
Features.push_back("-hwdiv-arm");
|
||||
|
||||
if (HWDivKind & AEK_HWDIVTHUMB)
|
||||
Features.push_back("+hwdiv");
|
||||
else
|
||||
Features.push_back("-hwdiv");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ARM::getExtensionFeatures(unsigned Extensions,
|
||||
std::vector<StringRef> &Features) {
|
||||
|
||||
if (Extensions == AEK_INVALID)
|
||||
return false;
|
||||
|
||||
if (Extensions & AEK_CRC)
|
||||
Features.push_back("+crc");
|
||||
else
|
||||
Features.push_back("-crc");
|
||||
|
||||
if (Extensions & AEK_DSP)
|
||||
Features.push_back("+dsp");
|
||||
else
|
||||
Features.push_back("-dsp");
|
||||
|
||||
if (Extensions & AEK_FP16FML)
|
||||
Features.push_back("+fp16fml");
|
||||
else
|
||||
Features.push_back("-fp16fml");
|
||||
|
||||
if (Extensions & AEK_RAS)
|
||||
Features.push_back("+ras");
|
||||
else
|
||||
Features.push_back("-ras");
|
||||
|
||||
if (Extensions & AEK_DOTPROD)
|
||||
Features.push_back("+dotprod");
|
||||
else
|
||||
Features.push_back("-dotprod");
|
||||
|
||||
return getHWDivFeatures(Extensions, Features);
|
||||
}
|
||||
|
||||
StringRef ARM::getArchName(ARM::ArchKind AK) {
|
||||
return ARCHNames[static_cast<unsigned>(AK)].getName();
|
||||
}
|
||||
|
||||
StringRef ARM::getCPUAttr(ARM::ArchKind AK) {
|
||||
return ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
|
||||
}
|
||||
|
||||
StringRef ARM::getSubArch(ARM::ArchKind AK) {
|
||||
return ARCHNames[static_cast<unsigned>(AK)].getSubArch();
|
||||
}
|
||||
|
||||
unsigned ARM::getArchAttr(ARM::ArchKind AK) {
|
||||
return ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
|
||||
}
|
||||
|
||||
StringRef ARM::getArchExtName(unsigned ArchExtKind) {
|
||||
for (const auto AE : ARCHExtNames) {
|
||||
if (ArchExtKind == AE.ID)
|
||||
return AE.getName();
|
||||
}
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef ARM::getArchExtFeature(StringRef ArchExt) {
|
||||
if (ArchExt.startswith("no")) {
|
||||
StringRef ArchExtBase(ArchExt.substr(2));
|
||||
for (const auto AE : ARCHExtNames) {
|
||||
if (AE.NegFeature && ArchExtBase == AE.getName())
|
||||
return StringRef(AE.NegFeature);
|
||||
}
|
||||
}
|
||||
for (const auto AE : ARCHExtNames) {
|
||||
if (AE.Feature && ArchExt == AE.getName())
|
||||
return StringRef(AE.Feature);
|
||||
}
|
||||
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef ARM::getHWDivName(unsigned HWDivKind) {
|
||||
for (const auto D : HWDivNames) {
|
||||
if (HWDivKind == D.ID)
|
||||
return D.getName();
|
||||
}
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef ARM::getDefaultCPU(StringRef Arch) {
|
||||
ArchKind AK = parseArch(Arch);
|
||||
if (AK == ArchKind::INVALID)
|
||||
return StringRef();
|
||||
|
||||
// Look for multiple AKs to find the default for pair AK+Name.
|
||||
for (const auto CPU : CPUNames) {
|
||||
if (CPU.ArchID == AK && CPU.Default)
|
||||
return CPU.getName();
|
||||
}
|
||||
|
||||
// If we can't find a default then target the architecture instead
|
||||
return "generic";
|
||||
}
|
||||
|
||||
unsigned ARM::parseHWDiv(StringRef HWDiv) {
|
||||
StringRef Syn = getHWDivSynonym(HWDiv);
|
||||
for (const auto D : HWDivNames) {
|
||||
if (Syn == D.getName())
|
||||
return D.ID;
|
||||
}
|
||||
return AEK_INVALID;
|
||||
}
|
||||
|
||||
unsigned ARM::parseArchExt(StringRef ArchExt) {
|
||||
for (const auto A : ARCHExtNames) {
|
||||
if (ArchExt == A.getName())
|
||||
return A.ID;
|
||||
}
|
||||
return AEK_INVALID;
|
||||
}
|
||||
|
||||
ARM::ArchKind ARM::parseCPUArch(StringRef CPU) {
|
||||
for (const auto C : CPUNames) {
|
||||
if (CPU == C.getName())
|
||||
return C.ArchID;
|
||||
}
|
||||
return ArchKind::INVALID;
|
||||
}
|
||||
|
||||
void ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
|
||||
for (const CpuNames<ArchKind> &Arch : CPUNames) {
|
||||
if (Arch.ArchID != ArchKind::INVALID)
|
||||
Values.push_back(Arch.getName());
|
||||
}
|
||||
}
|
||||
|
||||
StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
|
||||
StringRef ArchName =
|
||||
CPU.empty() ? TT.getArchName() : getArchName(parseCPUArch(CPU));
|
||||
|
||||
if (TT.isOSBinFormatMachO()) {
|
||||
if (TT.getEnvironment() == Triple::EABI ||
|
||||
TT.getOS() == Triple::UnknownOS ||
|
||||
parseArchProfile(ArchName) == ProfileKind::M)
|
||||
return "aapcs";
|
||||
if (TT.isWatchABI())
|
||||
return "aapcs16";
|
||||
return "apcs-gnu";
|
||||
} else if (TT.isOSWindows())
|
||||
// FIXME: this is invalid for WindowsCE.
|
||||
return "aapcs";
|
||||
|
||||
// Select the default based on the platform.
|
||||
switch (TT.getEnvironment()) {
|
||||
case Triple::Android:
|
||||
case Triple::GNUEABI:
|
||||
case Triple::GNUEABIHF:
|
||||
case Triple::MuslEABI:
|
||||
case Triple::MuslEABIHF:
|
||||
return "aapcs-linux";
|
||||
case Triple::EABIHF:
|
||||
case Triple::EABI:
|
||||
return "aapcs";
|
||||
default:
|
||||
if (TT.isOSNetBSD())
|
||||
return "apcs-gnu";
|
||||
if (TT.isOSOpenBSD())
|
||||
return "aapcs-linux";
|
||||
return "aapcs";
|
||||
}
|
||||
}
|
@ -45,6 +45,8 @@ if (MSVC)
|
||||
endif()
|
||||
|
||||
add_llvm_library(LLVMSupport
|
||||
AArch64TargetParser.cpp
|
||||
ARMTargetParser.cpp
|
||||
AMDGPUMetadata.cpp
|
||||
APFloat.cpp
|
||||
APInt.cpp
|
||||
|
@ -20,941 +20,10 @@
|
||||
#include <cctype>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace ARM;
|
||||
using namespace AArch64;
|
||||
using namespace AMDGPU;
|
||||
|
||||
namespace {
|
||||
|
||||
// List of canonical FPU names (use getFPUSynonym) and which architectural
|
||||
// features they correspond to (use getFPUFeatures).
|
||||
// FIXME: TableGen this.
|
||||
// The entries must appear in the order listed in ARM::FPUKind for correct indexing
|
||||
static const struct {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
ARM::FPUKind ID;
|
||||
ARM::FPUVersion FPUVersion;
|
||||
ARM::NeonSupportLevel NeonSupport;
|
||||
ARM::FPURestriction Restriction;
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
} FPUNames[] = {
|
||||
#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
|
||||
{ NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
};
|
||||
|
||||
// List of canonical arch names (use getArchSynonym).
|
||||
// This table also provides the build attribute fields for CPU arch
|
||||
// and Arch ID, according to the Addenda to the ARM ABI, chapters
|
||||
// 2.4 and 2.3.5.2 respectively.
|
||||
// FIXME: SubArch values were simplified to fit into the expectations
|
||||
// of the triples and are not conforming with their official names.
|
||||
// Check to see if the expectation should be changed.
|
||||
// FIXME: TableGen this.
|
||||
template <typename T> struct ArchNames {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
const char *CPUAttrCStr;
|
||||
size_t CPUAttrLength;
|
||||
const char *SubArchCStr;
|
||||
size_t SubArchLength;
|
||||
unsigned DefaultFPU;
|
||||
unsigned ArchBaseExtensions;
|
||||
T ID;
|
||||
ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
|
||||
// CPU class in build attributes.
|
||||
StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
|
||||
|
||||
// Sub-Arch name.
|
||||
StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
|
||||
};
|
||||
ArchNames<ARM::ArchKind> ARCHNames[] = {
|
||||
#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \
|
||||
{NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \
|
||||
sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ARM::ArchKind::ID, ARCH_ATTR},
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
};
|
||||
|
||||
ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = {
|
||||
#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \
|
||||
{NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \
|
||||
sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR},
|
||||
#include "llvm/Support/AArch64TargetParser.def"
|
||||
};
|
||||
|
||||
|
||||
// List of Arch Extension names.
|
||||
// FIXME: TableGen this.
|
||||
static const struct {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
unsigned ID;
|
||||
const char *Feature;
|
||||
const char *NegFeature;
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
} ARCHExtNames[] = {
|
||||
#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
|
||||
{ NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
},AArch64ARCHExtNames[] = {
|
||||
#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
|
||||
{ NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
|
||||
#include "llvm/Support/AArch64TargetParser.def"
|
||||
};
|
||||
|
||||
// List of HWDiv names (use getHWDivSynonym) and which architectural
|
||||
// features they correspond to (use getHWDivFeatures).
|
||||
// FIXME: TableGen this.
|
||||
static const struct {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
unsigned ID;
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
} HWDivNames[] = {
|
||||
#define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
};
|
||||
|
||||
// List of CPU names and their arches.
|
||||
// The same CPU can have multiple arches and can be default on multiple arches.
|
||||
// When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
|
||||
// When this becomes table-generated, we'd probably need two tables.
|
||||
// FIXME: TableGen this.
|
||||
template <typename T> struct CpuNames {
|
||||
const char *NameCStr;
|
||||
size_t NameLength;
|
||||
T ArchID;
|
||||
bool Default; // is $Name the default CPU for $ArchID ?
|
||||
unsigned DefaultExtensions;
|
||||
|
||||
StringRef getName() const { return StringRef(NameCStr, NameLength); }
|
||||
};
|
||||
CpuNames<ARM::ArchKind> CPUNames[] = {
|
||||
#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
{ NAME, sizeof(NAME) - 1, ARM::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT },
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
};
|
||||
|
||||
CpuNames<AArch64::ArchKind> AArch64CPUNames[] = {
|
||||
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
{ NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT },
|
||||
#include "llvm/Support/AArch64TargetParser.def"
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// ======================================================= //
|
||||
// Information by ID
|
||||
// ======================================================= //
|
||||
|
||||
StringRef ARM::getFPUName(unsigned FPUKind) {
|
||||
if (FPUKind >= ARM::FK_LAST)
|
||||
return StringRef();
|
||||
return FPUNames[FPUKind].getName();
|
||||
}
|
||||
|
||||
FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
|
||||
if (FPUKind >= ARM::FK_LAST)
|
||||
return FPUVersion::NONE;
|
||||
return FPUNames[FPUKind].FPUVersion;
|
||||
}
|
||||
|
||||
ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
|
||||
if (FPUKind >= ARM::FK_LAST)
|
||||
return ARM::NeonSupportLevel::None;
|
||||
return FPUNames[FPUKind].NeonSupport;
|
||||
}
|
||||
|
||||
ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
|
||||
if (FPUKind >= ARM::FK_LAST)
|
||||
return ARM::FPURestriction::None;
|
||||
return FPUNames[FPUKind].Restriction;
|
||||
}
|
||||
|
||||
unsigned llvm::ARM::getDefaultFPU(StringRef CPU, ArchKind AK) {
|
||||
if (CPU == "generic")
|
||||
return ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
|
||||
|
||||
return StringSwitch<unsigned>(CPU)
|
||||
#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, DEFAULT_FPU)
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
.Default(ARM::FK_INVALID);
|
||||
}
|
||||
|
||||
unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, ArchKind AK) {
|
||||
if (CPU == "generic")
|
||||
return ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
|
||||
|
||||
return StringSwitch<unsigned>(CPU)
|
||||
#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, ARCHNames[static_cast<unsigned>(ARM::ArchKind::ID)]\
|
||||
.ArchBaseExtensions | DEFAULT_EXT)
|
||||
#include "llvm/Support/ARMTargetParser.def"
|
||||
.Default(ARM::AEK_INVALID);
|
||||
}
|
||||
|
||||
bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
|
||||
std::vector<StringRef> &Features) {
|
||||
|
||||
if (HWDivKind == ARM::AEK_INVALID)
|
||||
return false;
|
||||
|
||||
if (HWDivKind & ARM::AEK_HWDIVARM)
|
||||
Features.push_back("+hwdiv-arm");
|
||||
else
|
||||
Features.push_back("-hwdiv-arm");
|
||||
|
||||
if (HWDivKind & ARM::AEK_HWDIVTHUMB)
|
||||
Features.push_back("+hwdiv");
|
||||
else
|
||||
Features.push_back("-hwdiv");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool llvm::ARM::getExtensionFeatures(unsigned Extensions,
|
||||
std::vector<StringRef> &Features) {
|
||||
|
||||
if (Extensions == ARM::AEK_INVALID)
|
||||
return false;
|
||||
|
||||
if (Extensions & ARM::AEK_CRC)
|
||||
Features.push_back("+crc");
|
||||
else
|
||||
Features.push_back("-crc");
|
||||
|
||||
if (Extensions & ARM::AEK_DSP)
|
||||
Features.push_back("+dsp");
|
||||
else
|
||||
Features.push_back("-dsp");
|
||||
|
||||
if (Extensions & ARM::AEK_FP16FML)
|
||||
Features.push_back("+fp16fml");
|
||||
else
|
||||
Features.push_back("-fp16fml");
|
||||
|
||||
if (Extensions & ARM::AEK_RAS)
|
||||
Features.push_back("+ras");
|
||||
else
|
||||
Features.push_back("-ras");
|
||||
|
||||
if (Extensions & ARM::AEK_DOTPROD)
|
||||
Features.push_back("+dotprod");
|
||||
else
|
||||
Features.push_back("-dotprod");
|
||||
|
||||
return getHWDivFeatures(Extensions, Features);
|
||||
}
|
||||
|
||||
bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
|
||||
std::vector<StringRef> &Features) {
|
||||
|
||||
if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
|
||||
return false;
|
||||
|
||||
// fp-only-sp and d16 subtarget features are independent of each other, so we
|
||||
// must enable/disable both.
|
||||
switch (FPUNames[FPUKind].Restriction) {
|
||||
case ARM::FPURestriction::SP_D16:
|
||||
Features.push_back("+fp-only-sp");
|
||||
Features.push_back("+d16");
|
||||
break;
|
||||
case ARM::FPURestriction::D16:
|
||||
Features.push_back("-fp-only-sp");
|
||||
Features.push_back("+d16");
|
||||
break;
|
||||
case ARM::FPURestriction::None:
|
||||
Features.push_back("-fp-only-sp");
|
||||
Features.push_back("-d16");
|
||||
break;
|
||||
}
|
||||
|
||||
// FPU version subtarget features are inclusive of lower-numbered ones, so
|
||||
// enable the one corresponding to this version and disable all that are
|
||||
// higher. We also have to make sure to disable fp16 when vfp4 is disabled,
|
||||
// as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
|
||||
switch (FPUNames[FPUKind].FPUVersion) {
|
||||
case ARM::FPUVersion::VFPV5:
|
||||
Features.push_back("+fp-armv8");
|
||||
break;
|
||||
case ARM::FPUVersion::VFPV4:
|
||||
Features.push_back("+vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
case ARM::FPUVersion::VFPV3_FP16:
|
||||
Features.push_back("+vfp3");
|
||||
Features.push_back("+fp16");
|
||||
Features.push_back("-vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
case ARM::FPUVersion::VFPV3:
|
||||
Features.push_back("+vfp3");
|
||||
Features.push_back("-fp16");
|
||||
Features.push_back("-vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
case ARM::FPUVersion::VFPV2:
|
||||
Features.push_back("+vfp2");
|
||||
Features.push_back("-vfp3");
|
||||
Features.push_back("-fp16");
|
||||
Features.push_back("-vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
case ARM::FPUVersion::NONE:
|
||||
Features.push_back("-vfp2");
|
||||
Features.push_back("-vfp3");
|
||||
Features.push_back("-fp16");
|
||||
Features.push_back("-vfp4");
|
||||
Features.push_back("-fp-armv8");
|
||||
break;
|
||||
}
|
||||
|
||||
// crypto includes neon, so we handle this similarly to FPU version.
|
||||
switch (FPUNames[FPUKind].NeonSupport) {
|
||||
case ARM::NeonSupportLevel::Crypto:
|
||||
Features.push_back("+neon");
|
||||
Features.push_back("+crypto");
|
||||
break;
|
||||
case ARM::NeonSupportLevel::Neon:
|
||||
Features.push_back("+neon");
|
||||
Features.push_back("-crypto");
|
||||
break;
|
||||
case ARM::NeonSupportLevel::None:
|
||||
Features.push_back("-neon");
|
||||
Features.push_back("-crypto");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
StringRef llvm::ARM::getArchName(ArchKind AK) {
|
||||
return ARCHNames[static_cast<unsigned>(AK)].getName();
|
||||
}
|
||||
|
||||
StringRef llvm::ARM::getCPUAttr(ArchKind AK) {
|
||||
return ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
|
||||
}
|
||||
|
||||
StringRef llvm::ARM::getSubArch(ArchKind AK) {
|
||||
return ARCHNames[static_cast<unsigned>(AK)].getSubArch();
|
||||
}
|
||||
|
||||
unsigned llvm::ARM::getArchAttr(ArchKind AK) {
|
||||
return ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
|
||||
}
|
||||
|
||||
StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
|
||||
for (const auto AE : ARCHExtNames) {
|
||||
if (ArchExtKind == AE.ID)
|
||||
return AE.getName();
|
||||
}
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef llvm::ARM::getArchExtFeature(StringRef ArchExt) {
|
||||
if (ArchExt.startswith("no")) {
|
||||
StringRef ArchExtBase(ArchExt.substr(2));
|
||||
for (const auto AE : ARCHExtNames) {
|
||||
if (AE.NegFeature && ArchExtBase == AE.getName())
|
||||
return StringRef(AE.NegFeature);
|
||||
}
|
||||
}
|
||||
for (const auto AE : ARCHExtNames) {
|
||||
if (AE.Feature && ArchExt == AE.getName())
|
||||
return StringRef(AE.Feature);
|
||||
}
|
||||
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
|
||||
for (const auto D : HWDivNames) {
|
||||
if (HWDivKind == D.ID)
|
||||
return D.getName();
|
||||
}
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
|
||||
ArchKind AK = parseArch(Arch);
|
||||
if (AK == ARM::ArchKind::INVALID)
|
||||
return StringRef();
|
||||
|
||||
// Look for multiple AKs to find the default for pair AK+Name.
|
||||
for (const auto CPU : CPUNames) {
|
||||
if (CPU.ArchID == AK && CPU.Default)
|
||||
return CPU.getName();
|
||||
}
|
||||
|
||||
// If we can't find a default then target the architecture instead
|
||||
return "generic";
|
||||
}
|
||||
|
||||
StringRef llvm::AArch64::getFPUName(unsigned FPUKind) {
|
||||
return ARM::getFPUName(FPUKind);
|
||||
}
|
||||
|
||||
ARM::FPUVersion AArch64::getFPUVersion(unsigned FPUKind) {
|
||||
return ARM::getFPUVersion(FPUKind);
|
||||
}
|
||||
|
||||
ARM::NeonSupportLevel AArch64::getFPUNeonSupportLevel(unsigned FPUKind) {
|
||||
return ARM::getFPUNeonSupportLevel( FPUKind);
|
||||
}
|
||||
|
||||
ARM::FPURestriction AArch64::getFPURestriction(unsigned FPUKind) {
|
||||
return ARM::getFPURestriction(FPUKind);
|
||||
}
|
||||
|
||||
unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, ArchKind AK) {
|
||||
if (CPU == "generic")
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
|
||||
|
||||
return StringSwitch<unsigned>(CPU)
|
||||
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, DEFAULT_FPU)
|
||||
#include "llvm/Support/AArch64TargetParser.def"
|
||||
.Default(ARM::FK_INVALID);
|
||||
}
|
||||
|
||||
unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, ArchKind AK) {
|
||||
if (CPU == "generic")
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
|
||||
|
||||
return StringSwitch<unsigned>(CPU)
|
||||
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, \
|
||||
AArch64ARCHNames[static_cast<unsigned>(AArch64::ArchKind::ID)] \
|
||||
.ArchBaseExtensions | \
|
||||
DEFAULT_EXT)
|
||||
#include "llvm/Support/AArch64TargetParser.def"
|
||||
.Default(AArch64::AEK_INVALID);
|
||||
}
|
||||
|
||||
AArch64::ArchKind llvm::AArch64::getCPUArchKind(StringRef CPU) {
|
||||
if (CPU == "generic")
|
||||
return AArch64::ArchKind::ARMV8A;
|
||||
|
||||
return StringSwitch<AArch64::ArchKind>(CPU)
|
||||
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
|
||||
.Case(NAME, AArch64::ArchKind:: ID)
|
||||
#include "llvm/Support/AArch64TargetParser.def"
|
||||
.Default(AArch64::ArchKind::INVALID);
|
||||
}
|
||||
|
||||
bool llvm::AArch64::getExtensionFeatures(unsigned Extensions,
|
||||
std::vector<StringRef> &Features) {
|
||||
|
||||
if (Extensions == AArch64::AEK_INVALID)
|
||||
return false;
|
||||
|
||||
if (Extensions & AArch64::AEK_FP)
|
||||
Features.push_back("+fp-armv8");
|
||||
if (Extensions & AArch64::AEK_SIMD)
|
||||
Features.push_back("+neon");
|
||||
if (Extensions & AArch64::AEK_CRC)
|
||||
Features.push_back("+crc");
|
||||
if (Extensions & AArch64::AEK_CRYPTO)
|
||||
Features.push_back("+crypto");
|
||||
if (Extensions & AArch64::AEK_DOTPROD)
|
||||
Features.push_back("+dotprod");
|
||||
if (Extensions & AArch64::AEK_FP16FML)
|
||||
Features.push_back("+fp16fml");
|
||||
if (Extensions & AArch64::AEK_FP16)
|
||||
Features.push_back("+fullfp16");
|
||||
if (Extensions & AArch64::AEK_PROFILE)
|
||||
Features.push_back("+spe");
|
||||
if (Extensions & AArch64::AEK_RAS)
|
||||
Features.push_back("+ras");
|
||||
if (Extensions & AArch64::AEK_LSE)
|
||||
Features.push_back("+lse");
|
||||
if (Extensions & AArch64::AEK_RDM)
|
||||
Features.push_back("+rdm");
|
||||
if (Extensions & AArch64::AEK_SVE)
|
||||
Features.push_back("+sve");
|
||||
if (Extensions & AArch64::AEK_RCPC)
|
||||
Features.push_back("+rcpc");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool llvm::AArch64::getFPUFeatures(unsigned FPUKind,
|
||||
std::vector<StringRef> &Features) {
|
||||
return ARM::getFPUFeatures(FPUKind, Features);
|
||||
}
|
||||
|
||||
bool llvm::AArch64::getArchFeatures(AArch64::ArchKind AK,
|
||||
std::vector<StringRef> &Features) {
|
||||
if (AK == AArch64::ArchKind::ARMV8_1A)
|
||||
Features.push_back("+v8.1a");
|
||||
if (AK == AArch64::ArchKind::ARMV8_2A)
|
||||
Features.push_back("+v8.2a");
|
||||
if (AK == AArch64::ArchKind::ARMV8_3A)
|
||||
Features.push_back("+v8.3a");
|
||||
if (AK == AArch64::ArchKind::ARMV8_4A)
|
||||
Features.push_back("+v8.4a");
|
||||
if (AK == AArch64::ArchKind::ARMV8_5A)
|
||||
Features.push_back("+v8.5a");
|
||||
|
||||
return AK != AArch64::ArchKind::INVALID;
|
||||
}
|
||||
|
||||
StringRef llvm::AArch64::getArchName(ArchKind AK) {
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].getName();
|
||||
}
|
||||
|
||||
StringRef llvm::AArch64::getCPUAttr(ArchKind AK) {
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
|
||||
}
|
||||
|
||||
StringRef llvm::AArch64::getSubArch(ArchKind AK) {
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch();
|
||||
}
|
||||
|
||||
unsigned llvm::AArch64::getArchAttr(ArchKind AK) {
|
||||
return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
|
||||
}
|
||||
|
||||
StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) {
|
||||
for (const auto &AE : AArch64ARCHExtNames)
|
||||
if (ArchExtKind == AE.ID)
|
||||
return AE.getName();
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef llvm::AArch64::getArchExtFeature(StringRef ArchExt) {
|
||||
if (ArchExt.startswith("no")) {
|
||||
StringRef ArchExtBase(ArchExt.substr(2));
|
||||
for (const auto &AE : AArch64ARCHExtNames) {
|
||||
if (AE.NegFeature && ArchExtBase == AE.getName())
|
||||
return StringRef(AE.NegFeature);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &AE : AArch64ARCHExtNames)
|
||||
if (AE.Feature && ArchExt == AE.getName())
|
||||
return StringRef(AE.Feature);
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) {
|
||||
AArch64::ArchKind AK = parseArch(Arch);
|
||||
if (AK == ArchKind::INVALID)
|
||||
return StringRef();
|
||||
|
||||
// Look for multiple AKs to find the default for pair AK+Name.
|
||||
for (const auto &CPU : AArch64CPUNames)
|
||||
if (CPU.ArchID == AK && CPU.Default)
|
||||
return CPU.getName();
|
||||
|
||||
// If we can't find a default then target the architecture instead
|
||||
return "generic";
|
||||
}
|
||||
|
||||
unsigned llvm::AArch64::checkArchVersion(StringRef Arch) {
|
||||
if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
|
||||
return (Arch[1] - 48);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ======================================================= //
|
||||
// Parsers
|
||||
// ======================================================= //
|
||||
|
||||
static StringRef getHWDivSynonym(StringRef HWDiv) {
|
||||
return StringSwitch<StringRef>(HWDiv)
|
||||
.Case("thumb,arm", "arm,thumb")
|
||||
.Default(HWDiv);
|
||||
}
|
||||
|
||||
static StringRef getFPUSynonym(StringRef FPU) {
|
||||
return StringSwitch<StringRef>(FPU)
|
||||
.Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
|
||||
.Case("vfp2", "vfpv2")
|
||||
.Case("vfp3", "vfpv3")
|
||||
.Case("vfp4", "vfpv4")
|
||||
.Case("vfp3-d16", "vfpv3-d16")
|
||||
.Case("vfp4-d16", "vfpv4-d16")
|
||||
.Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
|
||||
.Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
|
||||
.Case("fp5-sp-d16", "fpv5-sp-d16")
|
||||
.Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
|
||||
// FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
|
||||
.Case("neon-vfpv3", "neon")
|
||||
.Default(FPU);
|
||||
}
|
||||
|
||||
static StringRef getArchSynonym(StringRef Arch) {
|
||||
return StringSwitch<StringRef>(Arch)
|
||||
.Case("v5", "v5t")
|
||||
.Case("v5e", "v5te")
|
||||
.Case("v6j", "v6")
|
||||
.Case("v6hl", "v6k")
|
||||
.Cases("v6m", "v6sm", "v6s-m", "v6-m")
|
||||
.Cases("v6z", "v6zk", "v6kz")
|
||||
.Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
|
||||
.Case("v7r", "v7-r")
|
||||
.Case("v7m", "v7-m")
|
||||
.Case("v7em", "v7e-m")
|
||||
.Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a")
|
||||
.Case("v8.1a", "v8.1-a")
|
||||
.Case("v8.2a", "v8.2-a")
|
||||
.Case("v8.3a", "v8.3-a")
|
||||
.Case("v8.4a", "v8.4-a")
|
||||
.Case("v8.5a", "v8.5-a")
|
||||
.Case("v8r", "v8-r")
|
||||
.Case("v8m.base", "v8-m.base")
|
||||
.Case("v8m.main", "v8-m.main")
|
||||
.Default(Arch);
|
||||
}
|
||||
|
||||
// MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
|
||||
// (iwmmxt|xscale)(eb)? is also permitted. If the former, return
|
||||
// "v.+", if the latter, return unmodified string, minus 'eb'.
|
||||
// If invalid, return empty string.
|
||||
StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
|
||||
size_t offset = StringRef::npos;
|
||||
StringRef A = Arch;
|
||||
StringRef Error = "";
|
||||
|
||||
// Begins with "arm" / "thumb", move past it.
|
||||
if (A.startswith("arm64"))
|
||||
offset = 5;
|
||||
else if (A.startswith("arm"))
|
||||
offset = 3;
|
||||
else if (A.startswith("thumb"))
|
||||
offset = 5;
|
||||
else if (A.startswith("aarch64")) {
|
||||
offset = 7;
|
||||
// AArch64 uses "_be", not "eb" suffix.
|
||||
if (A.find("eb") != StringRef::npos)
|
||||
return Error;
|
||||
if (A.substr(offset, 3) == "_be")
|
||||
offset += 3;
|
||||
}
|
||||
|
||||
// Ex. "armebv7", move past the "eb".
|
||||
if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
|
||||
offset += 2;
|
||||
// Or, if it ends with eb ("armv7eb"), chop it off.
|
||||
else if (A.endswith("eb"))
|
||||
A = A.substr(0, A.size() - 2);
|
||||
// Trim the head
|
||||
if (offset != StringRef::npos)
|
||||
A = A.substr(offset);
|
||||
|
||||
// Empty string means offset reached the end, which means it's valid.
|
||||
if (A.empty())
|
||||
return Arch;
|
||||
|
||||
// Only match non-marketing names
|
||||
if (offset != StringRef::npos) {
|
||||
// Must start with 'vN'.
|
||||
if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1])))
|
||||
return Error;
|
||||
// Can't have an extra 'eb'.
|
||||
if (A.find("eb") != StringRef::npos)
|
||||
return Error;
|
||||
}
|
||||
|
||||
// Arch will either be a 'v' name (v7a) or a marketing name (xscale).
|
||||
return A;
|
||||
}
|
||||
|
||||
unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
|
||||
StringRef Syn = getHWDivSynonym(HWDiv);
|
||||
for (const auto D : HWDivNames) {
|
||||
if (Syn == D.getName())
|
||||
return D.ID;
|
||||
}
|
||||
return ARM::AEK_INVALID;
|
||||
}
|
||||
|
||||
unsigned llvm::ARM::parseFPU(StringRef FPU) {
|
||||
StringRef Syn = getFPUSynonym(FPU);
|
||||
for (const auto F : FPUNames) {
|
||||
if (Syn == F.getName())
|
||||
return F.ID;
|
||||
}
|
||||
return ARM::FK_INVALID;
|
||||
}
|
||||
|
||||
// Allows partial match, ex. "v7a" matches "armv7a".
|
||||
ARM::ArchKind ARM::parseArch(StringRef Arch) {
|
||||
Arch = getCanonicalArchName(Arch);
|
||||
StringRef Syn = getArchSynonym(Arch);
|
||||
for (const auto A : ARCHNames) {
|
||||
if (A.getName().endswith(Syn))
|
||||
return A.ID;
|
||||
}
|
||||
return ARM::ArchKind::INVALID;
|
||||
}
|
||||
|
||||
unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
|
||||
for (const auto A : ARCHExtNames) {
|
||||
if (ArchExt == A.getName())
|
||||
return A.ID;
|
||||
}
|
||||
return ARM::AEK_INVALID;
|
||||
}
|
||||
|
||||
ARM::ArchKind llvm::ARM::parseCPUArch(StringRef CPU) {
|
||||
for (const auto C : CPUNames) {
|
||||
if (CPU == C.getName())
|
||||
return C.ArchID;
|
||||
}
|
||||
return ARM::ArchKind::INVALID;
|
||||
}
|
||||
|
||||
void llvm::ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
|
||||
for (const CpuNames<ARM::ArchKind> &Arch : CPUNames) {
|
||||
if (Arch.ArchID != ARM::ArchKind::INVALID)
|
||||
Values.push_back(Arch.getName());
|
||||
}
|
||||
}
|
||||
|
||||
void llvm::AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
|
||||
for (const CpuNames<AArch64::ArchKind> &Arch : AArch64CPUNames) {
|
||||
if (Arch.ArchID != AArch64::ArchKind::INVALID)
|
||||
Values.push_back(Arch.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// ARM, Thumb, AArch64
|
||||
ARM::ISAKind ARM::parseArchISA(StringRef Arch) {
|
||||
return StringSwitch<ARM::ISAKind>(Arch)
|
||||
.StartsWith("aarch64", ARM::ISAKind::AARCH64)
|
||||
.StartsWith("arm64", ARM::ISAKind::AARCH64)
|
||||
.StartsWith("thumb", ARM::ISAKind::THUMB)
|
||||
.StartsWith("arm", ARM::ISAKind::ARM)
|
||||
.Default(ARM::ISAKind::INVALID);
|
||||
}
|
||||
|
||||
// Little/Big endian
|
||||
ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {
|
||||
if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
|
||||
Arch.startswith("aarch64_be"))
|
||||
return ARM::EndianKind::BIG;
|
||||
|
||||
if (Arch.startswith("arm") || Arch.startswith("thumb")) {
|
||||
if (Arch.endswith("eb"))
|
||||
return ARM::EndianKind::BIG;
|
||||
else
|
||||
return ARM::EndianKind::LITTLE;
|
||||
}
|
||||
|
||||
if (Arch.startswith("aarch64"))
|
||||
return ARM::EndianKind::LITTLE;
|
||||
|
||||
return ARM::EndianKind::INVALID;
|
||||
}
|
||||
|
||||
// Profile A/R/M
|
||||
ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) {
|
||||
Arch = getCanonicalArchName(Arch);
|
||||
switch (parseArch(Arch)) {
|
||||
case ARM::ArchKind::ARMV6M:
|
||||
case ARM::ArchKind::ARMV7M:
|
||||
case ARM::ArchKind::ARMV7EM:
|
||||
case ARM::ArchKind::ARMV8MMainline:
|
||||
case ARM::ArchKind::ARMV8MBaseline:
|
||||
return ARM::ProfileKind::M;
|
||||
case ARM::ArchKind::ARMV7R:
|
||||
case ARM::ArchKind::ARMV8R:
|
||||
return ARM::ProfileKind::R;
|
||||
case ARM::ArchKind::ARMV7A:
|
||||
case ARM::ArchKind::ARMV7VE:
|
||||
case ARM::ArchKind::ARMV7K:
|
||||
case ARM::ArchKind::ARMV8A:
|
||||
case ARM::ArchKind::ARMV8_1A:
|
||||
case ARM::ArchKind::ARMV8_2A:
|
||||
case ARM::ArchKind::ARMV8_3A:
|
||||
case ARM::ArchKind::ARMV8_4A:
|
||||
case ARM::ArchKind::ARMV8_5A:
|
||||
return ARM::ProfileKind::A;
|
||||
case ARM::ArchKind::ARMV2:
|
||||
case ARM::ArchKind::ARMV2A:
|
||||
case ARM::ArchKind::ARMV3:
|
||||
case ARM::ArchKind::ARMV3M:
|
||||
case ARM::ArchKind::ARMV4:
|
||||
case ARM::ArchKind::ARMV4T:
|
||||
case ARM::ArchKind::ARMV5T:
|
||||
case ARM::ArchKind::ARMV5TE:
|
||||
case ARM::ArchKind::ARMV5TEJ:
|
||||
case ARM::ArchKind::ARMV6:
|
||||
case ARM::ArchKind::ARMV6K:
|
||||
case ARM::ArchKind::ARMV6T2:
|
||||
case ARM::ArchKind::ARMV6KZ:
|
||||
case ARM::ArchKind::ARMV7S:
|
||||
case ARM::ArchKind::IWMMXT:
|
||||
case ARM::ArchKind::IWMMXT2:
|
||||
case ARM::ArchKind::XSCALE:
|
||||
case ARM::ArchKind::INVALID:
|
||||
return ARM::ProfileKind::INVALID;
|
||||
}
|
||||
llvm_unreachable("Unhandled architecture");
|
||||
}
|
||||
|
||||
// Version number (ex. v7 = 7).
|
||||
unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
|
||||
Arch = getCanonicalArchName(Arch);
|
||||
switch (parseArch(Arch)) {
|
||||
case ARM::ArchKind::ARMV2:
|
||||
case ARM::ArchKind::ARMV2A:
|
||||
return 2;
|
||||
case ARM::ArchKind::ARMV3:
|
||||
case ARM::ArchKind::ARMV3M:
|
||||
return 3;
|
||||
case ARM::ArchKind::ARMV4:
|
||||
case ARM::ArchKind::ARMV4T:
|
||||
return 4;
|
||||
case ARM::ArchKind::ARMV5T:
|
||||
case ARM::ArchKind::ARMV5TE:
|
||||
case ARM::ArchKind::IWMMXT:
|
||||
case ARM::ArchKind::IWMMXT2:
|
||||
case ARM::ArchKind::XSCALE:
|
||||
case ARM::ArchKind::ARMV5TEJ:
|
||||
return 5;
|
||||
case ARM::ArchKind::ARMV6:
|
||||
case ARM::ArchKind::ARMV6K:
|
||||
case ARM::ArchKind::ARMV6T2:
|
||||
case ARM::ArchKind::ARMV6KZ:
|
||||
case ARM::ArchKind::ARMV6M:
|
||||
return 6;
|
||||
case ARM::ArchKind::ARMV7A:
|
||||
case ARM::ArchKind::ARMV7VE:
|
||||
case ARM::ArchKind::ARMV7R:
|
||||
case ARM::ArchKind::ARMV7M:
|
||||
case ARM::ArchKind::ARMV7S:
|
||||
case ARM::ArchKind::ARMV7EM:
|
||||
case ARM::ArchKind::ARMV7K:
|
||||
return 7;
|
||||
case ARM::ArchKind::ARMV8A:
|
||||
case ARM::ArchKind::ARMV8_1A:
|
||||
case ARM::ArchKind::ARMV8_2A:
|
||||
case ARM::ArchKind::ARMV8_3A:
|
||||
case ARM::ArchKind::ARMV8_4A:
|
||||
case ARM::ArchKind::ARMV8_5A:
|
||||
case ARM::ArchKind::ARMV8R:
|
||||
case ARM::ArchKind::ARMV8MBaseline:
|
||||
case ARM::ArchKind::ARMV8MMainline:
|
||||
return 8;
|
||||
case ARM::ArchKind::INVALID:
|
||||
return 0;
|
||||
}
|
||||
llvm_unreachable("Unhandled architecture");
|
||||
}
|
||||
|
||||
StringRef llvm::ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
|
||||
StringRef ArchName =
|
||||
CPU.empty() ? TT.getArchName() : ARM::getArchName(ARM::parseCPUArch(CPU));
|
||||
|
||||
if (TT.isOSBinFormatMachO()) {
|
||||
if (TT.getEnvironment() == Triple::EABI ||
|
||||
TT.getOS() == Triple::UnknownOS ||
|
||||
llvm::ARM::parseArchProfile(ArchName) == ARM::ProfileKind::M)
|
||||
return "aapcs";
|
||||
if (TT.isWatchABI())
|
||||
return "aapcs16";
|
||||
return "apcs-gnu";
|
||||
} else if (TT.isOSWindows())
|
||||
// FIXME: this is invalid for WindowsCE.
|
||||
return "aapcs";
|
||||
|
||||
// Select the default based on the platform.
|
||||
switch (TT.getEnvironment()) {
|
||||
case Triple::Android:
|
||||
case Triple::GNUEABI:
|
||||
case Triple::GNUEABIHF:
|
||||
case Triple::MuslEABI:
|
||||
case Triple::MuslEABIHF:
|
||||
return "aapcs-linux";
|
||||
case Triple::EABIHF:
|
||||
case Triple::EABI:
|
||||
return "aapcs";
|
||||
default:
|
||||
if (TT.isOSNetBSD())
|
||||
return "apcs-gnu";
|
||||
if (TT.isOSOpenBSD())
|
||||
return "aapcs-linux";
|
||||
return "aapcs";
|
||||
}
|
||||
}
|
||||
|
||||
StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) {
|
||||
return ARM::getCanonicalArchName(Arch);
|
||||
}
|
||||
|
||||
unsigned llvm::AArch64::parseFPU(StringRef FPU) {
|
||||
return ARM::parseFPU(FPU);
|
||||
}
|
||||
|
||||
// Allows partial match, ex. "v8a" matches "armv8a".
|
||||
AArch64::ArchKind AArch64::parseArch(StringRef Arch) {
|
||||
Arch = getCanonicalArchName(Arch);
|
||||
if (checkArchVersion(Arch) < 8)
|
||||
return ArchKind::INVALID;
|
||||
|
||||
StringRef Syn = getArchSynonym(Arch);
|
||||
for (const auto A : AArch64ARCHNames) {
|
||||
if (A.getName().endswith(Syn))
|
||||
return A.ID;
|
||||
}
|
||||
return ArchKind::INVALID;
|
||||
}
|
||||
|
||||
AArch64::ArchExtKind llvm::AArch64::parseArchExt(StringRef ArchExt) {
|
||||
for (const auto A : AArch64ARCHExtNames) {
|
||||
if (ArchExt == A.getName())
|
||||
return static_cast<ArchExtKind>(A.ID);
|
||||
}
|
||||
return AArch64::AEK_INVALID;
|
||||
}
|
||||
|
||||
AArch64::ArchKind llvm::AArch64::parseCPUArch(StringRef CPU) {
|
||||
for (const auto C : AArch64CPUNames) {
|
||||
if (CPU == C.getName())
|
||||
return C.ArchID;
|
||||
}
|
||||
return ArchKind::INVALID;
|
||||
}
|
||||
|
||||
// ARM, Thumb, AArch64
|
||||
ARM::ISAKind AArch64::parseArchISA(StringRef Arch) {
|
||||
return ARM::parseArchISA(Arch);
|
||||
}
|
||||
|
||||
// Little/Big endian
|
||||
ARM::EndianKind AArch64::parseArchEndian(StringRef Arch) {
|
||||
return ARM::parseArchEndian(Arch);
|
||||
}
|
||||
|
||||
// Profile A/R/M
|
||||
ARM::ProfileKind AArch64::parseArchProfile(StringRef Arch) {
|
||||
return ARM::parseArchProfile(Arch);
|
||||
}
|
||||
|
||||
// Version number (ex. v8 = 8).
|
||||
unsigned llvm::AArch64::parseArchVersion(StringRef Arch) {
|
||||
return ARM::parseArchVersion(Arch);
|
||||
}
|
||||
|
||||
bool llvm::AArch64::isX18ReservedByDefault(const Triple &TT) {
|
||||
return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
|
||||
TT.isOSWindows();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct GPUInfo {
|
||||
StringLiteral Name;
|
||||
StringLiteral CanonicalName;
|
||||
|
@ -690,8 +690,6 @@ bool testAArch64CPU(StringRef CPUName, StringRef ExpectedArch,
|
||||
StringRef CPUAttr) {
|
||||
AArch64::ArchKind AK = AArch64::parseCPUArch(CPUName);
|
||||
bool pass = AArch64::getArchName(AK).equals(ExpectedArch);
|
||||
unsigned FPUKind = AArch64::getDefaultFPU(CPUName, AK);
|
||||
pass &= AArch64::getFPUName(FPUKind).equals(ExpectedFPU);
|
||||
|
||||
unsigned ExtKind = AArch64::getDefaultExtensions(CPUName, AK);
|
||||
if (ExtKind > 1 && (ExtKind & AArch64::AEK_NONE))
|
||||
|
Loading…
Reference in New Issue
Block a user