LLVM  17.0.0git
ARMTargetParserCommon.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Code that is common to ARMTargetParser and AArch64TargetParser.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringSwitch.h"
16 
17 using namespace llvm;
18 
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("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 }
52 
54  size_t offset = StringRef::npos;
55  StringRef A = Arch;
56  StringRef Error = "";
57 
58  // Begins with "arm" / "thumb", move past it.
59  if (A.startswith("arm64_32"))
60  offset = 8;
61  else if (A.startswith("arm64e"))
62  offset = 6;
63  else if (A.startswith("arm64"))
64  offset = 5;
65  else if (A.startswith("aarch64_32"))
66  offset = 10;
67  else if (A.startswith("arm"))
68  offset = 3;
69  else if (A.startswith("thumb"))
70  offset = 5;
71  else if (A.startswith("aarch64")) {
72  offset = 7;
73  // AArch64 uses "_be", not "eb" suffix.
74  if (A.contains("eb"))
75  return Error;
76  if (A.substr(offset, 3) == "_be")
77  offset += 3;
78  }
79 
80  // Ex. "armebv7", move past the "eb".
81  if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
82  offset += 2;
83  // Or, if it ends with eb ("armv7eb"), chop it off.
84  else if (A.endswith("eb"))
85  A = A.substr(0, A.size() - 2);
86  // Trim the head
87  if (offset != StringRef::npos)
88  A = A.substr(offset);
89 
90  // Empty string means offset reached the end, which means it's valid.
91  if (A.empty())
92  return Arch;
93 
94  // Only match non-marketing names
95  if (offset != StringRef::npos) {
96  // Must start with 'vN'.
97  if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1])))
98  return Error;
99  // Can't have an extra 'eb'.
100  if (A.contains("eb"))
101  return Error;
102  }
103 
104  // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
105  return A;
106 }
107 
109  return 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 }
116 
118  if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
119  Arch.startswith("aarch64_be"))
120  return EndianKind::BIG;
121 
122  if (Arch.startswith("arm") || Arch.startswith("thumb")) {
123  if (Arch.endswith("eb"))
124  return EndianKind::BIG;
125  else
126  return EndianKind::LITTLE;
127  }
128 
129  if (Arch.startswith("aarch64") || Arch.startswith("aarch64_32"))
130  return EndianKind::LITTLE;
131 
132  return EndianKind::INVALID;
133 }
134 
135 // Parse a branch protection specification, which has the form
136 // standard | none | [bti,pac-ret[+b-key,+leaf]*]
137 // Returns true on success, with individual elements of the specification
138 // returned in `PBP`. Returns false in error, with `Err` containing
139 // an erroneous part of the spec.
141  StringRef &Err) {
142  PBP = {"none", "a_key", false};
143  if (Spec == "none")
144  return true; // defaults are ok
145 
146  if (Spec == "standard") {
147  PBP.Scope = "non-leaf";
148  PBP.BranchTargetEnforcement = true;
149  return true;
150  }
151 
153  Spec.split(Opts, "+");
154  for (int I = 0, E = Opts.size(); I != E; ++I) {
155  StringRef Opt = Opts[I].trim();
156  if (Opt == "bti") {
157  PBP.BranchTargetEnforcement = true;
158  continue;
159  }
160  if (Opt == "pac-ret") {
161  PBP.Scope = "non-leaf";
162  for (; I + 1 != E; ++I) {
163  StringRef PACOpt = Opts[I + 1].trim();
164  if (PACOpt == "leaf")
165  PBP.Scope = "all";
166  else if (PACOpt == "b-key")
167  PBP.Key = "b_key";
168  else
169  break;
170  }
171  continue;
172  }
173  if (Opt == "")
174  Err = "<empty>";
175  else
176  Err = Opt;
177  return false;
178  }
179 
180  return true;
181 }
llvm::StringSwitch::Case
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
llvm::StringSwitch::StartsWith
StringSwitch & StartsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:83
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::ARM::EndianKind
EndianKind
Definition: ARMTargetParserCommon.h:23
llvm::ARM::getCanonicalArchName
StringRef getCanonicalArchName(StringRef Arch)
MArch is expected to be of the form (arm|thumb)?(eb)?(v.
Definition: ARMTargetParserCommon.cpp:53
llvm::StringRef::npos
static constexpr size_t npos
Definition: StringRef.h:52
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::ARM::getArchSynonym
StringRef getArchSynonym(StringRef Arch)
Converts e.g. "armv8" -> "armv8-a".
Definition: ARMTargetParserCommon.cpp:19
llvm::StringRef::startswith
bool startswith(StringRef Prefix) const
Definition: StringRef.h:261
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::ARM::ParsedBranchProtection::Scope
StringRef Scope
Definition: ARMTargetParserCommon.h:41
llvm::ARM::parseArchEndian
EndianKind parseArchEndian(StringRef Arch)
Definition: ARMTargetParserCommon.cpp:117
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::ARM::parseBranchProtection
bool parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP, StringRef &Err)
Definition: ARMTargetParserCommon.cpp:140
llvm::ARM::ISAKind
ISAKind
Definition: ARMTargetParserCommon.h:21
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::ARM::parseArchISA
ISAKind parseArchISA(StringRef Arch)
Definition: ARMTargetParserCommon.cpp:108
llvm::StringSwitch::Cases
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
Definition: StringSwitch.h:90
ARMTargetParserCommon.h
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
llvm::StringRef::endswith
bool endswith(StringRef Suffix) const
Definition: StringRef.h:277
llvm::ARM::ParsedBranchProtection::Key
StringRef Key
Definition: ARMTargetParserCommon.h:42
llvm::Spec
Definition: FunctionSpecialization.h:87
StringSwitch.h
llvm::ARM::ParsedBranchProtection
Definition: ARMTargetParserCommon.h:40
SmallVector.h
llvm::StringSwitch::Default
R Default(T Value)
Definition: StringSwitch.h:182
llvm::StringSwitch
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
llvm::ARM::ParsedBranchProtection::BranchTargetEnforcement
bool BranchTargetEnforcement
Definition: ARMTargetParserCommon.h:43