Files
llvm/llvm/lib/TargetParser/AArch64TargetParser.cpp
Tomas Matheson f4225d325c [AArch64] Reland "Improve TargetParser API"
Reworked after several other major changes to the TargetParser since
this was reverted. Combined with several other changes.

Inline calls for the following macros and delete AArch64TargetParser.def:
 AARCH64_ARCH,  AARCH64_CPU_NAME,  AARCH64_CPU_ALIAS, AARCH64_ARCH_EXT_NAME

Squashed changes from D139278 and D139102.

Differential Revision: https://reviews.llvm.org/D138792
2023-01-14 14:43:38 +00:00

160 lines
4.5 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.
//
//===----------------------------------------------------------------------===//
#include "llvm/TargetParser/AArch64TargetParser.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/TargetParser/ARMTargetParserCommon.h"
#include "llvm/TargetParser/Triple.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;
}
uint64_t AArch64::getDefaultExtensions(StringRef CPU,
const AArch64::ArchInfo &AI) {
if (CPU == "generic")
return AI.DefaultExts;
// Note: this now takes cpu aliases into account
const CpuInfo &Cpu = parseCpu(CPU);
return Cpu.Arch.DefaultExts | Cpu.DefaultExtensions;
}
void AArch64::getFeatureOption(StringRef Name, std::string &Feature) {
for (const auto &E : llvm::AArch64::Extensions) {
if (Name == E.Name) {
Feature = E.Feature;
return;
}
}
Feature = Name.str();
}
const AArch64::ArchInfo &AArch64::getArchForCpu(StringRef CPU) {
if (CPU == "generic")
return ARMV8A;
// Note: this now takes cpu aliases into account
const CpuInfo &Cpu = parseCpu(CPU);
return Cpu.Arch;
}
const AArch64::ArchInfo &AArch64::ArchInfo::findBySubArch(StringRef SubArch) {
for (const auto *A : AArch64::ArchInfos)
if (A->getSubArch() == SubArch)
return *A;
return AArch64::INVALID;
}
uint64_t AArch64::getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs) {
uint64_t FeaturesMask = 0;
for (const StringRef &FeatureStr : FeatureStrs) {
for (const auto &E : llvm::AArch64::Extensions)
if (FeatureStr == E.Name) {
FeaturesMask |= (1ULL << E.CPUFeature);
break;
}
}
return FeaturesMask;
}
bool AArch64::getExtensionFeatures(uint64_t InputExts,
std::vector<StringRef> &Features) {
if (InputExts == AArch64::AEK_INVALID)
return false;
for (const auto &E : Extensions)
/* INVALID and NONE have no feature name. */
if ((InputExts & E.ID) && !E.Feature.empty())
Features.push_back(E.Feature);
return true;
}
StringRef AArch64::resolveCPUAlias(StringRef Name) {
for (const auto &A : CpuAliases)
if (A.Alias == Name)
return A.Name;
return Name;
}
StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
if (ArchExt.startswith("no")) {
StringRef ArchExtBase(ArchExt.substr(2));
for (const auto &AE : Extensions) {
if (!AE.NegFeature.empty() && ArchExtBase == AE.Name)
return AE.NegFeature;
}
}
for (const auto &AE : Extensions)
if (!AE.Feature.empty() && ArchExt == AE.Name)
return AE.Feature;
return StringRef();
}
void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
for (const auto &C : CpuInfos)
if (C.Arch != INVALID)
Values.push_back(C.Name);
for (const auto &Alias : CpuAliases)
Values.push_back(Alias.Alias);
}
bool AArch64::isX18ReservedByDefault(const Triple &TT) {
return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
TT.isOSWindows();
}
// Allows partial match, ex. "v8a" matches "armv8a".
const AArch64::ArchInfo &AArch64::parseArch(StringRef Arch) {
Arch = llvm::ARM::getCanonicalArchName(Arch);
if (checkArchVersion(Arch) < 8)
return AArch64::INVALID;
StringRef Syn = llvm::ARM::getArchSynonym(Arch);
for (const auto *A : ArchInfos) {
if (A->Name.endswith(Syn))
return *A;
}
return AArch64::INVALID;
}
AArch64::ArchExtKind AArch64::parseArchExt(StringRef ArchExt) {
for (const auto &A : Extensions) {
if (ArchExt == A.Name)
return static_cast<ArchExtKind>(A.ID);
}
return AArch64::AEK_INVALID;
}
const AArch64::CpuInfo &AArch64::parseCpu(StringRef Name) {
// Resolve aliases first.
Name = resolveCPUAlias(Name);
// Then find the CPU name.
for (const auto &C : CpuInfos)
if (Name == C.Name)
return C;
// "generic" returns invalid.
assert(Name != "invalid" && "Unexpected recursion.");
return parseCpu("invalid");
}