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