Path: blob/main/contrib/llvm-project/llvm/lib/TargetParser/ARMTargetParserCommon.cpp
35233 views
//===---------------- ARMTargetParserCommon ---------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Code that is common to ARMTargetParser and AArch64TargetParser.9//10//===----------------------------------------------------------------------===//1112#include "llvm/TargetParser/ARMTargetParserCommon.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/ADT/StringSwitch.h"1516using namespace llvm;1718StringRef ARM::getArchSynonym(StringRef Arch) {19return StringSwitch<StringRef>(Arch)20.Case("v5", "v5t")21.Case("v5e", "v5te")22.Case("v6j", "v6")23.Case("v6hl", "v6k")24.Cases("v6m", "v6sm", "v6s-m", "v6-m")25.Cases("v6z", "v6zk", "v6kz")26.Cases("v7", "v7a", "v7hl", "v7l", "v7-a")27.Case("v7r", "v7-r")28.Case("v7m", "v7-m")29.Case("v7em", "v7e-m")30.Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a")31.Case("v8.1a", "v8.1-a")32.Case("v8.2a", "v8.2-a")33.Case("v8.3a", "v8.3-a")34.Case("v8.4a", "v8.4-a")35.Case("v8.5a", "v8.5-a")36.Case("v8.6a", "v8.6-a")37.Case("v8.7a", "v8.7-a")38.Case("v8.8a", "v8.8-a")39.Case("v8.9a", "v8.9-a")40.Case("v8r", "v8-r")41.Cases("v9", "v9a", "v9-a")42.Case("v9.1a", "v9.1-a")43.Case("v9.2a", "v9.2-a")44.Case("v9.3a", "v9.3-a")45.Case("v9.4a", "v9.4-a")46.Case("v9.5a", "v9.5-a")47.Case("v8m.base", "v8-m.base")48.Case("v8m.main", "v8-m.main")49.Case("v8.1m.main", "v8.1-m.main")50.Default(Arch);51}5253StringRef ARM::getCanonicalArchName(StringRef Arch) {54size_t offset = StringRef::npos;55StringRef A = Arch;56StringRef Error = "";5758// Begins with "arm" / "thumb", move past it.59if (A.starts_with("arm64_32"))60offset = 8;61else if (A.starts_with("arm64e"))62offset = 6;63else if (A.starts_with("arm64"))64offset = 5;65else if (A.starts_with("aarch64_32"))66offset = 10;67else if (A.starts_with("arm"))68offset = 3;69else if (A.starts_with("thumb"))70offset = 5;71else if (A.starts_with("aarch64")) {72offset = 7;73// AArch64 uses "_be", not "eb" suffix.74if (A.contains("eb"))75return Error;76if (A.substr(offset, 3) == "_be")77offset += 3;78}7980// Ex. "armebv7", move past the "eb".81if (offset != StringRef::npos && A.substr(offset, 2) == "eb")82offset += 2;83// Or, if it ends with eb ("armv7eb"), chop it off.84else if (A.ends_with("eb"))85A = A.substr(0, A.size() - 2);86// Trim the head87if (offset != StringRef::npos)88A = A.substr(offset);8990// Empty string means offset reached the end, which means it's valid.91if (A.empty())92return Arch;9394// Only match non-marketing names95if (offset != StringRef::npos) {96// Must start with 'vN'.97if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1])))98return Error;99// Can't have an extra 'eb'.100if (A.contains("eb"))101return Error;102}103104// Arch will either be a 'v' name (v7a) or a marketing name (xscale).105return A;106}107108ARM::ISAKind ARM::parseArchISA(StringRef Arch) {109return StringSwitch<ISAKind>(Arch)110.StartsWith("aarch64", ISAKind::AARCH64)111.StartsWith("arm64", ISAKind::AARCH64)112.StartsWith("thumb", ISAKind::THUMB)113.StartsWith("arm", ISAKind::ARM)114.Default(ISAKind::INVALID);115}116117ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {118if (Arch.starts_with("armeb") || Arch.starts_with("thumbeb") ||119Arch.starts_with("aarch64_be"))120return EndianKind::BIG;121122if (Arch.starts_with("arm") || Arch.starts_with("thumb")) {123if (Arch.ends_with("eb"))124return EndianKind::BIG;125else126return EndianKind::LITTLE;127}128129if (Arch.starts_with("aarch64") || Arch.starts_with("aarch64_32"))130return EndianKind::LITTLE;131132return EndianKind::INVALID;133}134135// Parse a branch protection specification, which has the form136// standard | none | [bti,pac-ret[+b-key,+leaf,+pc]*]137// Returns true on success, with individual elements of the specification138// returned in `PBP`. Returns false in error, with `Err` containing139// an erroneous part of the spec.140bool ARM::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP,141StringRef &Err, bool EnablePAuthLR) {142PBP = {"none", "a_key", false, false, false};143if (Spec == "none")144return true; // defaults are ok145146if (Spec == "standard") {147PBP.Scope = "non-leaf";148PBP.BranchTargetEnforcement = true;149PBP.GuardedControlStack = true;150PBP.BranchProtectionPAuthLR = EnablePAuthLR;151return true;152}153154SmallVector<StringRef, 4> Opts;155Spec.split(Opts, "+");156for (int I = 0, E = Opts.size(); I != E; ++I) {157StringRef Opt = Opts[I].trim();158if (Opt == "bti") {159PBP.BranchTargetEnforcement = true;160continue;161}162if (Opt == "pac-ret") {163PBP.Scope = "non-leaf";164for (; I + 1 != E; ++I) {165StringRef PACOpt = Opts[I + 1].trim();166if (PACOpt == "leaf")167PBP.Scope = "all";168else if (PACOpt == "b-key")169PBP.Key = "b_key";170else if (PACOpt == "pc")171PBP.BranchProtectionPAuthLR = true;172else173break;174}175continue;176}177if (Opt == "gcs") {178PBP.GuardedControlStack = true;179continue;180}181if (Opt == "")182Err = "<empty>";183else184Err = Opt;185return false;186}187188return true;189}190191192