1bdd1243dSDimitry Andric //===---------------- ARMTargetParserCommon ---------------------*- C++ -*-===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric // 9bdd1243dSDimitry Andric // Code that is common to ARMTargetParser and AArch64TargetParser. 10bdd1243dSDimitry Andric // 11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 12bdd1243dSDimitry Andric 13bdd1243dSDimitry Andric #include "llvm/TargetParser/ARMTargetParserCommon.h" 14bdd1243dSDimitry Andric #include "llvm/ADT/SmallVector.h" 15bdd1243dSDimitry Andric #include "llvm/ADT/StringSwitch.h" 16bdd1243dSDimitry Andric 17bdd1243dSDimitry Andric using namespace llvm; 18bdd1243dSDimitry Andric 19bdd1243dSDimitry Andric StringRef ARM::getArchSynonym(StringRef Arch) { 20bdd1243dSDimitry Andric return StringSwitch<StringRef>(Arch) 21bdd1243dSDimitry Andric .Case("v5", "v5t") 22bdd1243dSDimitry Andric .Case("v5e", "v5te") 23bdd1243dSDimitry Andric .Case("v6j", "v6") 24bdd1243dSDimitry Andric .Case("v6hl", "v6k") 25bdd1243dSDimitry Andric .Cases("v6m", "v6sm", "v6s-m", "v6-m") 26bdd1243dSDimitry Andric .Cases("v6z", "v6zk", "v6kz") 27bdd1243dSDimitry Andric .Cases("v7", "v7a", "v7hl", "v7l", "v7-a") 28bdd1243dSDimitry Andric .Case("v7r", "v7-r") 29bdd1243dSDimitry Andric .Case("v7m", "v7-m") 30bdd1243dSDimitry Andric .Case("v7em", "v7e-m") 31bdd1243dSDimitry Andric .Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a") 32bdd1243dSDimitry Andric .Case("v8.1a", "v8.1-a") 33bdd1243dSDimitry Andric .Case("v8.2a", "v8.2-a") 34bdd1243dSDimitry Andric .Case("v8.3a", "v8.3-a") 35bdd1243dSDimitry Andric .Case("v8.4a", "v8.4-a") 36bdd1243dSDimitry Andric .Case("v8.5a", "v8.5-a") 37bdd1243dSDimitry Andric .Case("v8.6a", "v8.6-a") 38bdd1243dSDimitry Andric .Case("v8.7a", "v8.7-a") 39bdd1243dSDimitry Andric .Case("v8.8a", "v8.8-a") 40bdd1243dSDimitry Andric .Case("v8.9a", "v8.9-a") 41bdd1243dSDimitry Andric .Case("v8r", "v8-r") 42bdd1243dSDimitry Andric .Cases("v9", "v9a", "v9-a") 43bdd1243dSDimitry Andric .Case("v9.1a", "v9.1-a") 44bdd1243dSDimitry Andric .Case("v9.2a", "v9.2-a") 45bdd1243dSDimitry Andric .Case("v9.3a", "v9.3-a") 46bdd1243dSDimitry Andric .Case("v9.4a", "v9.4-a") 475f757f3fSDimitry Andric .Case("v9.5a", "v9.5-a") 48bdd1243dSDimitry Andric .Case("v8m.base", "v8-m.base") 49bdd1243dSDimitry Andric .Case("v8m.main", "v8-m.main") 50bdd1243dSDimitry Andric .Case("v8.1m.main", "v8.1-m.main") 51bdd1243dSDimitry Andric .Default(Arch); 52bdd1243dSDimitry Andric } 53bdd1243dSDimitry Andric 54bdd1243dSDimitry Andric StringRef ARM::getCanonicalArchName(StringRef Arch) { 55bdd1243dSDimitry Andric size_t offset = StringRef::npos; 56bdd1243dSDimitry Andric StringRef A = Arch; 57bdd1243dSDimitry Andric StringRef Error = ""; 58bdd1243dSDimitry Andric 59bdd1243dSDimitry Andric // Begins with "arm" / "thumb", move past it. 605f757f3fSDimitry Andric if (A.starts_with("arm64_32")) 61bdd1243dSDimitry Andric offset = 8; 625f757f3fSDimitry Andric else if (A.starts_with("arm64e")) 63bdd1243dSDimitry Andric offset = 6; 645f757f3fSDimitry Andric else if (A.starts_with("arm64")) 65bdd1243dSDimitry Andric offset = 5; 665f757f3fSDimitry Andric else if (A.starts_with("aarch64_32")) 67bdd1243dSDimitry Andric offset = 10; 685f757f3fSDimitry Andric else if (A.starts_with("arm")) 69bdd1243dSDimitry Andric offset = 3; 705f757f3fSDimitry Andric else if (A.starts_with("thumb")) 71bdd1243dSDimitry Andric offset = 5; 725f757f3fSDimitry Andric else if (A.starts_with("aarch64")) { 73bdd1243dSDimitry Andric offset = 7; 74bdd1243dSDimitry Andric // AArch64 uses "_be", not "eb" suffix. 75bdd1243dSDimitry Andric if (A.contains("eb")) 76bdd1243dSDimitry Andric return Error; 77bdd1243dSDimitry Andric if (A.substr(offset, 3) == "_be") 78bdd1243dSDimitry Andric offset += 3; 79bdd1243dSDimitry Andric } 80bdd1243dSDimitry Andric 81bdd1243dSDimitry Andric // Ex. "armebv7", move past the "eb". 82bdd1243dSDimitry Andric if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 83bdd1243dSDimitry Andric offset += 2; 84bdd1243dSDimitry Andric // Or, if it ends with eb ("armv7eb"), chop it off. 855f757f3fSDimitry Andric else if (A.ends_with("eb")) 86bdd1243dSDimitry Andric A = A.substr(0, A.size() - 2); 87bdd1243dSDimitry Andric // Trim the head 88bdd1243dSDimitry Andric if (offset != StringRef::npos) 89bdd1243dSDimitry Andric A = A.substr(offset); 90bdd1243dSDimitry Andric 91bdd1243dSDimitry Andric // Empty string means offset reached the end, which means it's valid. 92bdd1243dSDimitry Andric if (A.empty()) 93bdd1243dSDimitry Andric return Arch; 94bdd1243dSDimitry Andric 95bdd1243dSDimitry Andric // Only match non-marketing names 96bdd1243dSDimitry Andric if (offset != StringRef::npos) { 97bdd1243dSDimitry Andric // Must start with 'vN'. 98bdd1243dSDimitry Andric if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1]))) 99bdd1243dSDimitry Andric return Error; 100bdd1243dSDimitry Andric // Can't have an extra 'eb'. 101bdd1243dSDimitry Andric if (A.contains("eb")) 102bdd1243dSDimitry Andric return Error; 103bdd1243dSDimitry Andric } 104bdd1243dSDimitry Andric 105bdd1243dSDimitry Andric // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 106bdd1243dSDimitry Andric return A; 107bdd1243dSDimitry Andric } 108bdd1243dSDimitry Andric 109bdd1243dSDimitry Andric ARM::ISAKind ARM::parseArchISA(StringRef Arch) { 110bdd1243dSDimitry Andric return StringSwitch<ISAKind>(Arch) 111bdd1243dSDimitry Andric .StartsWith("aarch64", ISAKind::AARCH64) 112bdd1243dSDimitry Andric .StartsWith("arm64", ISAKind::AARCH64) 113bdd1243dSDimitry Andric .StartsWith("thumb", ISAKind::THUMB) 114bdd1243dSDimitry Andric .StartsWith("arm", ISAKind::ARM) 115bdd1243dSDimitry Andric .Default(ISAKind::INVALID); 116bdd1243dSDimitry Andric } 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric ARM::EndianKind ARM::parseArchEndian(StringRef Arch) { 1195f757f3fSDimitry Andric if (Arch.starts_with("armeb") || Arch.starts_with("thumbeb") || 1205f757f3fSDimitry Andric Arch.starts_with("aarch64_be")) 121bdd1243dSDimitry Andric return EndianKind::BIG; 122bdd1243dSDimitry Andric 1235f757f3fSDimitry Andric if (Arch.starts_with("arm") || Arch.starts_with("thumb")) { 1245f757f3fSDimitry Andric if (Arch.ends_with("eb")) 125bdd1243dSDimitry Andric return EndianKind::BIG; 126bdd1243dSDimitry Andric else 127bdd1243dSDimitry Andric return EndianKind::LITTLE; 128bdd1243dSDimitry Andric } 129bdd1243dSDimitry Andric 1305f757f3fSDimitry Andric if (Arch.starts_with("aarch64") || Arch.starts_with("aarch64_32")) 131bdd1243dSDimitry Andric return EndianKind::LITTLE; 132bdd1243dSDimitry Andric 133bdd1243dSDimitry Andric return EndianKind::INVALID; 134bdd1243dSDimitry Andric } 135bdd1243dSDimitry Andric 136bdd1243dSDimitry Andric // Parse a branch protection specification, which has the form 137cb14a3feSDimitry Andric // standard | none | [bti,pac-ret[+b-key,+leaf,+pc]*] 138bdd1243dSDimitry Andric // Returns true on success, with individual elements of the specification 139bdd1243dSDimitry Andric // returned in `PBP`. Returns false in error, with `Err` containing 140bdd1243dSDimitry Andric // an erroneous part of the spec. 141bdd1243dSDimitry Andric bool ARM::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP, 142*0fca6ea1SDimitry Andric StringRef &Err, bool EnablePAuthLR) { 143297eecfbSDimitry Andric PBP = {"none", "a_key", false, false, false}; 144bdd1243dSDimitry Andric if (Spec == "none") 145bdd1243dSDimitry Andric return true; // defaults are ok 146bdd1243dSDimitry Andric 147bdd1243dSDimitry Andric if (Spec == "standard") { 148bdd1243dSDimitry Andric PBP.Scope = "non-leaf"; 149bdd1243dSDimitry Andric PBP.BranchTargetEnforcement = true; 150297eecfbSDimitry Andric PBP.GuardedControlStack = true; 151*0fca6ea1SDimitry Andric PBP.BranchProtectionPAuthLR = EnablePAuthLR; 152bdd1243dSDimitry Andric return true; 153bdd1243dSDimitry Andric } 154bdd1243dSDimitry Andric 155bdd1243dSDimitry Andric SmallVector<StringRef, 4> Opts; 156bdd1243dSDimitry Andric Spec.split(Opts, "+"); 157bdd1243dSDimitry Andric for (int I = 0, E = Opts.size(); I != E; ++I) { 158bdd1243dSDimitry Andric StringRef Opt = Opts[I].trim(); 159bdd1243dSDimitry Andric if (Opt == "bti") { 160bdd1243dSDimitry Andric PBP.BranchTargetEnforcement = true; 161bdd1243dSDimitry Andric continue; 162bdd1243dSDimitry Andric } 163bdd1243dSDimitry Andric if (Opt == "pac-ret") { 164bdd1243dSDimitry Andric PBP.Scope = "non-leaf"; 165bdd1243dSDimitry Andric for (; I + 1 != E; ++I) { 166bdd1243dSDimitry Andric StringRef PACOpt = Opts[I + 1].trim(); 167bdd1243dSDimitry Andric if (PACOpt == "leaf") 168bdd1243dSDimitry Andric PBP.Scope = "all"; 169bdd1243dSDimitry Andric else if (PACOpt == "b-key") 170bdd1243dSDimitry Andric PBP.Key = "b_key"; 171cb14a3feSDimitry Andric else if (PACOpt == "pc") 172cb14a3feSDimitry Andric PBP.BranchProtectionPAuthLR = true; 173bdd1243dSDimitry Andric else 174bdd1243dSDimitry Andric break; 175bdd1243dSDimitry Andric } 176bdd1243dSDimitry Andric continue; 177bdd1243dSDimitry Andric } 178297eecfbSDimitry Andric if (Opt == "gcs") { 179297eecfbSDimitry Andric PBP.GuardedControlStack = true; 180297eecfbSDimitry Andric continue; 181297eecfbSDimitry Andric } 182bdd1243dSDimitry Andric if (Opt == "") 183bdd1243dSDimitry Andric Err = "<empty>"; 184bdd1243dSDimitry Andric else 185bdd1243dSDimitry Andric Err = Opt; 186bdd1243dSDimitry Andric return false; 187bdd1243dSDimitry Andric } 188bdd1243dSDimitry Andric 189bdd1243dSDimitry Andric return true; 190bdd1243dSDimitry Andric } 191