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