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