llvm-project/llvm/lib/TargetParser/AArch64TargetParser.cpp
Lucas Prates 9ea00fc74c [NFC][AArch64] Use optional returns in target parser instead of 'invalid' objects
This updates the parsing methods in AArch64's Target Parser to make use
of optional returns instead of "invalid" enum values, making the API's
behaviour clearer.

Reviewed By: lenary, tmatheson

Differential Revision: https://reviews.llvm.org/D142539
2023-01-27 12:35:58 +00:00

159 lines
4.3 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
std::optional<CpuInfo> Cpu = parseCpu(CPU);
if (!Cpu)
return AI.DefaultExts;
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();
}
std::optional<AArch64::ArchInfo> AArch64::getArchForCpu(StringRef CPU) {
if (CPU == "generic")
return ARMV8A;
// Note: this now takes cpu aliases into account
std::optional<CpuInfo> Cpu = parseCpu(CPU);
if (!Cpu)
return {};
return Cpu->Arch;
}
std::optional<AArch64::ArchInfo> AArch64::ArchInfo::findBySubArch(StringRef SubArch) {
for (const auto *A : AArch64::ArchInfos)
if (A->getSubArch() == SubArch)
return *A;
return {};
}
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) {
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)
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".
std::optional<AArch64::ArchInfo> AArch64::parseArch(StringRef Arch) {
Arch = llvm::ARM::getCanonicalArchName(Arch);
if (checkArchVersion(Arch) < 8)
return {};
StringRef Syn = llvm::ARM::getArchSynonym(Arch);
for (const auto *A : ArchInfos) {
if (A->Name.endswith(Syn))
return *A;
}
return {};
}
std::optional<AArch64::ExtensionInfo> AArch64::parseArchExtension(StringRef ArchExt) {
for (const auto &A : Extensions) {
if (ArchExt == A.Name)
return A;
}
return {};
}
std::optional<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;
return {};
}