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