brintos

brintos / llvm-project-archived public Read only

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