clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
290 lines
11 KiB
C++
290 lines
11 KiB
C++
//===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements a target parser to recognise AArch64 hardware features
|
|
// such as FPU/CPU/ARCH and extension names.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_TARGETPARSER_AARCH64TARGETPARSER_H
|
|
#define LLVM_TARGETPARSER_AARCH64TARGETPARSER_H
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/Bitset.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/VersionTuple.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/TargetParser/SubtargetFeature.h"
|
|
#include <array>
|
|
#include <set>
|
|
#include <vector>
|
|
|
|
namespace llvm {
|
|
|
|
class Triple;
|
|
|
|
namespace AArch64 {
|
|
|
|
struct ArchInfo;
|
|
struct CpuInfo;
|
|
|
|
#include "llvm/TargetParser/AArch64CPUFeatures.inc"
|
|
|
|
static_assert(FEAT_MAX < 62,
|
|
"Number of features in CPUFeatures are limited to 62 entries");
|
|
|
|
// Each ArchExtKind correponds directly to a possible -target-feature.
|
|
#define EMIT_ARCHEXTKIND_ENUM
|
|
#include "llvm/TargetParser/AArch64TargetParserDef.inc"
|
|
|
|
using ExtensionBitset = Bitset<AEK_NUM_EXTENSIONS>;
|
|
|
|
// Represents an extension that can be enabled with -march=<arch>+<extension>.
|
|
// Typically these correspond to Arm Architecture extensions, unlike
|
|
// SubtargetFeature which may represent either an actual extension or some
|
|
// internal LLVM property.
|
|
struct ExtensionInfo {
|
|
StringRef UserVisibleName; // Human readable name used in -march, -cpu
|
|
// and target func attribute, e.g. "profile".
|
|
std::optional<StringRef> Alias; // An alias for this extension, if one exists.
|
|
ArchExtKind ID; // Corresponding to the ArchExtKind, this
|
|
// extensions representation in the bitfield.
|
|
StringRef ArchFeatureName; // The feature name defined by the
|
|
// Architecture, e.g. FEAT_AdvSIMD.
|
|
StringRef Description; // The textual description of the extension.
|
|
StringRef PosTargetFeature; // -target-feature/-mattr enable string,
|
|
// e.g. "+spe".
|
|
StringRef NegTargetFeature; // -target-feature/-mattr disable string,
|
|
// e.g. "-spe".
|
|
};
|
|
|
|
#define EMIT_EXTENSIONS
|
|
#include "llvm/TargetParser/AArch64TargetParserDef.inc"
|
|
|
|
struct FMVInfo {
|
|
StringRef Name; // The target_version/target_clones spelling.
|
|
CPUFeatures Bit; // Index of the bit in the FMV feature bitset.
|
|
StringRef Features; // List of SubtargetFeatures to enable.
|
|
unsigned Priority; // FMV priority.
|
|
FMVInfo(StringRef Name, CPUFeatures Bit, StringRef Features,
|
|
unsigned Priority)
|
|
: Name(Name), Bit(Bit), Features(Features), Priority(Priority){};
|
|
|
|
SmallVector<StringRef, 8> getImpliedFeatures() {
|
|
SmallVector<StringRef, 8> Feats;
|
|
Features.split(Feats, ',', -1, false); // discard empty strings
|
|
return Feats;
|
|
}
|
|
};
|
|
|
|
const std::vector<FMVInfo> &getFMVInfo();
|
|
|
|
// Represents a dependency between two architecture extensions. Later is the
|
|
// feature which was added to the architecture after Earlier, and expands the
|
|
// functionality provided by it. If Later is enabled, then Earlier will also be
|
|
// enabled. If Earlier is disabled, then Later will also be disabled.
|
|
struct ExtensionDependency {
|
|
ArchExtKind Earlier;
|
|
ArchExtKind Later;
|
|
};
|
|
|
|
#define EMIT_EXTENSION_DEPENDENCIES
|
|
#include "llvm/TargetParser/AArch64TargetParserDef.inc"
|
|
|
|
enum ArchProfile { AProfile = 'A', RProfile = 'R', InvalidProfile = '?' };
|
|
|
|
// Information about a specific architecture, e.g. V8.1-A
|
|
struct ArchInfo {
|
|
VersionTuple Version; // Architecture version, major + minor.
|
|
ArchProfile Profile; // Architecuture profile
|
|
StringRef Name; // Name as supplied to -march e.g. "armv8.1-a"
|
|
StringRef ArchFeature; // Name as supplied to -target-feature, e.g. "+v8a"
|
|
AArch64::ExtensionBitset
|
|
DefaultExts; // bitfield of default extensions ArchExtKind
|
|
|
|
bool operator==(const ArchInfo &Other) const {
|
|
return this->Name == Other.Name;
|
|
}
|
|
bool operator!=(const ArchInfo &Other) const {
|
|
return this->Name != Other.Name;
|
|
}
|
|
|
|
// Defines the following partial order, indicating when an architecture is
|
|
// a superset of another:
|
|
//
|
|
// v9.5a > v9.4a > v9.3a > v9.2a > v9.1a > v9a;
|
|
// v v v v v
|
|
// v8.9a > v8.8a > v8.7a > v8.6a > v8.5a > v8.4a > ... > v8a;
|
|
//
|
|
// v8r has no relation to anything. This is used to determine which
|
|
// features to enable for a given architecture. See
|
|
// AArch64TargetInfo::setFeatureEnabled.
|
|
bool implies(const ArchInfo &Other) const {
|
|
if (this->Profile != Other.Profile)
|
|
return false; // ARMV8R
|
|
if (this->Version.getMajor() == Other.Version.getMajor()) {
|
|
return this->Version > Other.Version;
|
|
}
|
|
if (this->Version.getMajor() == 9 && Other.Version.getMajor() == 8) {
|
|
assert(this->Version.getMinor() && Other.Version.getMinor() &&
|
|
"AArch64::ArchInfo should have a minor version.");
|
|
return this->Version.getMinor().value_or(0) + 5 >=
|
|
Other.Version.getMinor().value_or(0);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// True if this architecture is a superset of Other (including being equal to
|
|
// it).
|
|
bool is_superset(const ArchInfo &Other) const {
|
|
return (*this == Other) || implies(Other);
|
|
}
|
|
|
|
// Return ArchFeature without the leading "+".
|
|
StringRef getSubArch() const { return ArchFeature.substr(1); }
|
|
|
|
// Search for ArchInfo by SubArch name
|
|
static std::optional<ArchInfo> findBySubArch(StringRef SubArch);
|
|
};
|
|
|
|
#define EMIT_ARCHITECTURES
|
|
#include "llvm/TargetParser/AArch64TargetParserDef.inc"
|
|
|
|
// Details of a specific CPU.
|
|
struct CpuInfo {
|
|
StringRef Name; // Name, as written for -mcpu.
|
|
const ArchInfo &Arch;
|
|
AArch64::ExtensionBitset
|
|
DefaultExtensions; // Default extensions for this CPU.
|
|
|
|
AArch64::ExtensionBitset getImpliedExtensions() const {
|
|
return DefaultExtensions;
|
|
}
|
|
};
|
|
|
|
#define EMIT_CPU_INFO
|
|
#include "llvm/TargetParser/AArch64TargetParserDef.inc"
|
|
|
|
struct ExtensionSet {
|
|
// Set of extensions which are currently enabled.
|
|
ExtensionBitset Enabled;
|
|
// Set of extensions which have been enabled or disabled at any point. Used
|
|
// to avoid cluttering the cc1 command-line with lots of unneeded features.
|
|
ExtensionBitset Touched;
|
|
// Base architecture version, which we need to know because some feature
|
|
// dependencies change depending on this.
|
|
const ArchInfo *BaseArch;
|
|
|
|
ExtensionSet() : Enabled(), Touched(), BaseArch(nullptr) {}
|
|
|
|
// Enable the given architecture extension, and any other extensions it
|
|
// depends on. Does not change the base architecture, or follow dependencies
|
|
// between features which are only related by required arcitecture versions.
|
|
void enable(ArchExtKind E);
|
|
|
|
// Disable the given architecture extension, and any other extensions which
|
|
// depend on it. Does not change the base architecture, or follow
|
|
// dependencies between features which are only related by required
|
|
// arcitecture versions.
|
|
void disable(ArchExtKind E);
|
|
|
|
// Add default extensions for the given CPU. Records the base architecture,
|
|
// to later resolve dependencies which depend on it.
|
|
void addCPUDefaults(const CpuInfo &CPU);
|
|
|
|
// Add default extensions for the given architecture version. Records the
|
|
// base architecture, to later resolve dependencies which depend on it.
|
|
void addArchDefaults(const ArchInfo &Arch);
|
|
|
|
// Add or remove a feature based on a modifier string. The string must be of
|
|
// the form "<name>" to enable a feature or "no<name>" to disable it. This
|
|
// will also enable or disable any features as required by the dependencies
|
|
// between them.
|
|
bool parseModifier(StringRef Modifier, const bool AllowNoDashForm = false);
|
|
|
|
// Constructs a new ExtensionSet by toggling the corresponding bits for every
|
|
// feature in the \p Features list without expanding their dependencies. Used
|
|
// for reconstructing an ExtensionSet from the output of toLLVMFeatures().
|
|
// Features that are not recognized are pushed back to \p NonExtensions.
|
|
void reconstructFromParsedFeatures(const std::vector<std::string> &Features,
|
|
std::vector<std::string> &NonExtensions);
|
|
|
|
// Convert the set of enabled extension to an LLVM feature list, appending
|
|
// them to Features.
|
|
template <typename T> void toLLVMFeatureList(std::vector<T> &Features) const {
|
|
if (BaseArch && !BaseArch->ArchFeature.empty())
|
|
Features.emplace_back(T(BaseArch->ArchFeature));
|
|
|
|
for (const auto &E : Extensions) {
|
|
if (E.PosTargetFeature.empty() || !Touched.test(E.ID))
|
|
continue;
|
|
if (Enabled.test(E.ID))
|
|
Features.emplace_back(T(E.PosTargetFeature));
|
|
else
|
|
Features.emplace_back(T(E.NegTargetFeature));
|
|
}
|
|
}
|
|
|
|
void dump() const;
|
|
};
|
|
|
|
// Name alias.
|
|
struct Alias {
|
|
StringRef AltName;
|
|
StringRef Name;
|
|
};
|
|
|
|
#define EMIT_CPU_ALIAS
|
|
#include "llvm/TargetParser/AArch64TargetParserDef.inc"
|
|
|
|
const ExtensionInfo &getExtensionByID(ArchExtKind(ExtID));
|
|
|
|
bool getExtensionFeatures(
|
|
const AArch64::ExtensionBitset &Extensions,
|
|
std::vector<StringRef> &Features);
|
|
|
|
StringRef getArchExtFeature(StringRef ArchExt);
|
|
StringRef resolveCPUAlias(StringRef CPU);
|
|
|
|
// Information by Name
|
|
const ArchInfo *getArchForCpu(StringRef CPU);
|
|
|
|
// Parser
|
|
const ArchInfo *parseArch(StringRef Arch);
|
|
|
|
// Return the extension which has the given -target-feature name.
|
|
std::optional<ExtensionInfo> targetFeatureToExtension(StringRef TargetFeature);
|
|
|
|
// Parse a name as defined by the Extension class in tablegen.
|
|
std::optional<ExtensionInfo> parseArchExtension(StringRef Extension);
|
|
|
|
// Parse a name as defined by the FMVInfo class in tablegen.
|
|
std::optional<FMVInfo> parseFMVExtension(StringRef Extension);
|
|
|
|
// Given the name of a CPU or alias, return the correponding CpuInfo.
|
|
std::optional<CpuInfo> parseCpu(StringRef Name);
|
|
// Used by target parser tests
|
|
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
|
|
|
|
bool isX18ReservedByDefault(const Triple &TT);
|
|
|
|
// For given feature names, return a bitmask corresponding to the entries of
|
|
// AArch64::CPUFeatures. The values in CPUFeatures are not bitmasks
|
|
// themselves, they are sequential (0, 1, 2, 3, ...).
|
|
uint64_t getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
|
|
|
|
void PrintSupportedExtensions();
|
|
|
|
void printEnabledExtensions(const std::set<StringRef> &EnabledFeatureNames);
|
|
|
|
} // namespace AArch64
|
|
} // namespace llvm
|
|
|
|
#endif
|