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