Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/TargetParser/ARMTargetParserCommon.cpp
35233 views
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
13
#include "llvm/TargetParser/ARMTargetParserCommon.h"
14
#include "llvm/ADT/SmallVector.h"
15
#include "llvm/ADT/StringSwitch.h"
16
17
using namespace llvm;
18
19
StringRef 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("v8m.base", "v8-m.base")
49
.Case("v8m.main", "v8-m.main")
50
.Case("v8.1m.main", "v8.1-m.main")
51
.Default(Arch);
52
}
53
54
StringRef ARM::getCanonicalArchName(StringRef Arch) {
55
size_t offset = StringRef::npos;
56
StringRef A = Arch;
57
StringRef Error = "";
58
59
// Begins with "arm" / "thumb", move past it.
60
if (A.starts_with("arm64_32"))
61
offset = 8;
62
else if (A.starts_with("arm64e"))
63
offset = 6;
64
else if (A.starts_with("arm64"))
65
offset = 5;
66
else if (A.starts_with("aarch64_32"))
67
offset = 10;
68
else if (A.starts_with("arm"))
69
offset = 3;
70
else if (A.starts_with("thumb"))
71
offset = 5;
72
else if (A.starts_with("aarch64")) {
73
offset = 7;
74
// AArch64 uses "_be", not "eb" suffix.
75
if (A.contains("eb"))
76
return Error;
77
if (A.substr(offset, 3) == "_be")
78
offset += 3;
79
}
80
81
// Ex. "armebv7", move past the "eb".
82
if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
83
offset += 2;
84
// Or, if it ends with eb ("armv7eb"), chop it off.
85
else if (A.ends_with("eb"))
86
A = A.substr(0, A.size() - 2);
87
// Trim the head
88
if (offset != StringRef::npos)
89
A = A.substr(offset);
90
91
// Empty string means offset reached the end, which means it's valid.
92
if (A.empty())
93
return Arch;
94
95
// Only match non-marketing names
96
if (offset != StringRef::npos) {
97
// Must start with 'vN'.
98
if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1])))
99
return Error;
100
// Can't have an extra 'eb'.
101
if (A.contains("eb"))
102
return Error;
103
}
104
105
// Arch will either be a 'v' name (v7a) or a marketing name (xscale).
106
return A;
107
}
108
109
ARM::ISAKind ARM::parseArchISA(StringRef Arch) {
110
return StringSwitch<ISAKind>(Arch)
111
.StartsWith("aarch64", ISAKind::AARCH64)
112
.StartsWith("arm64", ISAKind::AARCH64)
113
.StartsWith("thumb", ISAKind::THUMB)
114
.StartsWith("arm", ISAKind::ARM)
115
.Default(ISAKind::INVALID);
116
}
117
118
ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {
119
if (Arch.starts_with("armeb") || Arch.starts_with("thumbeb") ||
120
Arch.starts_with("aarch64_be"))
121
return EndianKind::BIG;
122
123
if (Arch.starts_with("arm") || Arch.starts_with("thumb")) {
124
if (Arch.ends_with("eb"))
125
return EndianKind::BIG;
126
else
127
return EndianKind::LITTLE;
128
}
129
130
if (Arch.starts_with("aarch64") || Arch.starts_with("aarch64_32"))
131
return EndianKind::LITTLE;
132
133
return EndianKind::INVALID;
134
}
135
136
// Parse a branch protection specification, which has the form
137
// standard | none | [bti,pac-ret[+b-key,+leaf,+pc]*]
138
// Returns true on success, with individual elements of the specification
139
// returned in `PBP`. Returns false in error, with `Err` containing
140
// an erroneous part of the spec.
141
bool ARM::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP,
142
StringRef &Err, bool EnablePAuthLR) {
143
PBP = {"none", "a_key", false, false, false};
144
if (Spec == "none")
145
return true; // defaults are ok
146
147
if (Spec == "standard") {
148
PBP.Scope = "non-leaf";
149
PBP.BranchTargetEnforcement = true;
150
PBP.GuardedControlStack = true;
151
PBP.BranchProtectionPAuthLR = EnablePAuthLR;
152
return true;
153
}
154
155
SmallVector<StringRef, 4> Opts;
156
Spec.split(Opts, "+");
157
for (int I = 0, E = Opts.size(); I != E; ++I) {
158
StringRef Opt = Opts[I].trim();
159
if (Opt == "bti") {
160
PBP.BranchTargetEnforcement = true;
161
continue;
162
}
163
if (Opt == "pac-ret") {
164
PBP.Scope = "non-leaf";
165
for (; I + 1 != E; ++I) {
166
StringRef PACOpt = Opts[I + 1].trim();
167
if (PACOpt == "leaf")
168
PBP.Scope = "all";
169
else if (PACOpt == "b-key")
170
PBP.Key = "b_key";
171
else if (PACOpt == "pc")
172
PBP.BranchProtectionPAuthLR = true;
173
else
174
break;
175
}
176
continue;
177
}
178
if (Opt == "gcs") {
179
PBP.GuardedControlStack = true;
180
continue;
181
}
182
if (Opt == "")
183
Err = "<empty>";
184
else
185
Err = Opt;
186
return false;
187
}
188
189
return true;
190
}
191
192