Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Basic/Targets/WebAssembly.cpp
213799 views
1
//===--- WebAssembly.cpp - Implement WebAssembly target feature support ---===//
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
// This file implements WebAssembly TargetInfo objects.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "WebAssembly.h"
14
#include "Targets.h"
15
#include "clang/Basic/Builtins.h"
16
#include "clang/Basic/Diagnostic.h"
17
#include "clang/Basic/TargetBuiltins.h"
18
#include "llvm/ADT/StringSwitch.h"
19
20
using namespace clang;
21
using namespace clang::targets;
22
23
static constexpr int NumBuiltins =
24
clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin;
25
26
static constexpr llvm::StringTable BuiltinStrings =
27
CLANG_BUILTIN_STR_TABLE_START
28
#define BUILTIN CLANG_BUILTIN_STR_TABLE
29
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
30
#include "clang/Basic/BuiltinsWebAssembly.def"
31
;
32
33
static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({
34
#define BUILTIN CLANG_BUILTIN_ENTRY
35
#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
36
#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY
37
#include "clang/Basic/BuiltinsWebAssembly.def"
38
});
39
40
static constexpr llvm::StringLiteral ValidCPUNames[] = {
41
{"mvp"}, {"bleeding-edge"}, {"generic"}, {"lime1"}};
42
43
StringRef WebAssemblyTargetInfo::getABI() const { return ABI; }
44
45
bool WebAssemblyTargetInfo::setABI(const std::string &Name) {
46
if (Name != "mvp" && Name != "experimental-mv")
47
return false;
48
49
ABI = Name;
50
return true;
51
}
52
53
bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
54
return llvm::StringSwitch<bool>(Feature)
55
.Case("atomics", HasAtomics)
56
.Case("bulk-memory", HasBulkMemory)
57
.Case("bulk-memory-opt", HasBulkMemoryOpt)
58
.Case("call-indirect-overlong", HasCallIndirectOverlong)
59
.Case("exception-handling", HasExceptionHandling)
60
.Case("extended-const", HasExtendedConst)
61
.Case("fp16", HasFP16)
62
.Case("multimemory", HasMultiMemory)
63
.Case("multivalue", HasMultivalue)
64
.Case("mutable-globals", HasMutableGlobals)
65
.Case("nontrapping-fptoint", HasNontrappingFPToInt)
66
.Case("reference-types", HasReferenceTypes)
67
.Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
68
.Case("sign-ext", HasSignExt)
69
.Case("simd128", SIMDLevel >= SIMD128)
70
.Case("tail-call", HasTailCall)
71
.Case("wide-arithmetic", HasWideArithmetic)
72
.Default(false);
73
}
74
75
bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
76
return llvm::is_contained(ValidCPUNames, Name);
77
}
78
79
void WebAssemblyTargetInfo::fillValidCPUList(
80
SmallVectorImpl<StringRef> &Values) const {
81
Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
82
}
83
84
void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
85
MacroBuilder &Builder) const {
86
defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
87
if (HasAtomics)
88
Builder.defineMacro("__wasm_atomics__");
89
if (HasBulkMemory)
90
Builder.defineMacro("__wasm_bulk_memory__");
91
if (HasBulkMemoryOpt)
92
Builder.defineMacro("__wasm_bulk_memory_opt__");
93
if (HasExceptionHandling)
94
Builder.defineMacro("__wasm_exception_handling__");
95
if (HasExtendedConst)
96
Builder.defineMacro("__wasm_extended_const__");
97
if (HasMultiMemory)
98
Builder.defineMacro("__wasm_multimemory__");
99
if (HasFP16)
100
Builder.defineMacro("__wasm_fp16__");
101
if (HasMultivalue)
102
Builder.defineMacro("__wasm_multivalue__");
103
if (HasMutableGlobals)
104
Builder.defineMacro("__wasm_mutable_globals__");
105
if (HasNontrappingFPToInt)
106
Builder.defineMacro("__wasm_nontrapping_fptoint__");
107
if (HasReferenceTypes)
108
Builder.defineMacro("__wasm_reference_types__");
109
if (SIMDLevel >= RelaxedSIMD)
110
Builder.defineMacro("__wasm_relaxed_simd__");
111
if (HasSignExt)
112
Builder.defineMacro("__wasm_sign_ext__");
113
if (SIMDLevel >= SIMD128)
114
Builder.defineMacro("__wasm_simd128__");
115
if (HasTailCall)
116
Builder.defineMacro("__wasm_tail_call__");
117
if (HasWideArithmetic)
118
Builder.defineMacro("__wasm_wide_arithmetic__");
119
120
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
121
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
122
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
123
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
124
}
125
126
void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
127
SIMDEnum Level, bool Enabled) {
128
if (Enabled) {
129
switch (Level) {
130
case RelaxedSIMD:
131
Features["relaxed-simd"] = true;
132
[[fallthrough]];
133
case SIMD128:
134
Features["simd128"] = true;
135
[[fallthrough]];
136
case NoSIMD:
137
break;
138
}
139
return;
140
}
141
142
switch (Level) {
143
case NoSIMD:
144
case SIMD128:
145
Features["simd128"] = false;
146
[[fallthrough]];
147
case RelaxedSIMD:
148
Features["relaxed-simd"] = false;
149
break;
150
}
151
}
152
153
void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
154
StringRef Name,
155
bool Enabled) const {
156
if (Name == "simd128")
157
setSIMDLevel(Features, SIMD128, Enabled);
158
else if (Name == "relaxed-simd")
159
setSIMDLevel(Features, RelaxedSIMD, Enabled);
160
else
161
Features[Name] = Enabled;
162
}
163
164
bool WebAssemblyTargetInfo::initFeatureMap(
165
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
166
const std::vector<std::string> &FeaturesVec) const {
167
auto addGenericFeatures = [&]() {
168
Features["bulk-memory"] = true;
169
Features["bulk-memory-opt"] = true;
170
Features["call-indirect-overlong"] = true;
171
Features["multivalue"] = true;
172
Features["mutable-globals"] = true;
173
Features["nontrapping-fptoint"] = true;
174
Features["reference-types"] = true;
175
Features["sign-ext"] = true;
176
};
177
auto addLime1Features = [&]() {
178
// Lime1:
179
// <https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#lime1>
180
Features["bulk-memory-opt"] = true;
181
Features["call-indirect-overlong"] = true;
182
Features["extended-const"] = true;
183
Features["multivalue"] = true;
184
Features["mutable-globals"] = true;
185
Features["nontrapping-fptoint"] = true;
186
Features["sign-ext"] = true;
187
};
188
auto addBleedingEdgeFeatures = [&]() {
189
addGenericFeatures();
190
Features["atomics"] = true;
191
Features["exception-handling"] = true;
192
Features["extended-const"] = true;
193
Features["fp16"] = true;
194
Features["multimemory"] = true;
195
Features["tail-call"] = true;
196
Features["wide-arithmetic"] = true;
197
setSIMDLevel(Features, RelaxedSIMD, true);
198
};
199
if (CPU == "generic") {
200
addGenericFeatures();
201
} else if (CPU == "lime1") {
202
addLime1Features();
203
} else if (CPU == "bleeding-edge") {
204
addBleedingEdgeFeatures();
205
}
206
207
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
208
}
209
210
bool WebAssemblyTargetInfo::handleTargetFeatures(
211
std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
212
for (const auto &Feature : Features) {
213
if (Feature == "+atomics") {
214
HasAtomics = true;
215
continue;
216
}
217
if (Feature == "-atomics") {
218
HasAtomics = false;
219
continue;
220
}
221
if (Feature == "+bulk-memory") {
222
HasBulkMemory = true;
223
continue;
224
}
225
if (Feature == "-bulk-memory") {
226
HasBulkMemory = false;
227
continue;
228
}
229
if (Feature == "+bulk-memory-opt") {
230
HasBulkMemoryOpt = true;
231
continue;
232
}
233
if (Feature == "-bulk-memory-opt") {
234
HasBulkMemoryOpt = false;
235
continue;
236
}
237
if (Feature == "+call-indirect-overlong") {
238
HasCallIndirectOverlong = true;
239
continue;
240
}
241
if (Feature == "-call-indirect-overlong") {
242
HasCallIndirectOverlong = false;
243
continue;
244
}
245
if (Feature == "+exception-handling") {
246
HasExceptionHandling = true;
247
continue;
248
}
249
if (Feature == "-exception-handling") {
250
HasExceptionHandling = false;
251
continue;
252
}
253
if (Feature == "+extended-const") {
254
HasExtendedConst = true;
255
continue;
256
}
257
if (Feature == "-extended-const") {
258
HasExtendedConst = false;
259
continue;
260
}
261
if (Feature == "+fp16") {
262
SIMDLevel = std::max(SIMDLevel, SIMD128);
263
HasFP16 = true;
264
continue;
265
}
266
if (Feature == "-fp16") {
267
HasFP16 = false;
268
continue;
269
}
270
if (Feature == "+multimemory") {
271
HasMultiMemory = true;
272
continue;
273
}
274
if (Feature == "-multimemory") {
275
HasMultiMemory = false;
276
continue;
277
}
278
if (Feature == "+multivalue") {
279
HasMultivalue = true;
280
continue;
281
}
282
if (Feature == "-multivalue") {
283
HasMultivalue = false;
284
continue;
285
}
286
if (Feature == "+mutable-globals") {
287
HasMutableGlobals = true;
288
continue;
289
}
290
if (Feature == "-mutable-globals") {
291
HasMutableGlobals = false;
292
continue;
293
}
294
if (Feature == "+nontrapping-fptoint") {
295
HasNontrappingFPToInt = true;
296
continue;
297
}
298
if (Feature == "-nontrapping-fptoint") {
299
HasNontrappingFPToInt = false;
300
continue;
301
}
302
if (Feature == "+reference-types") {
303
HasReferenceTypes = true;
304
continue;
305
}
306
if (Feature == "-reference-types") {
307
HasReferenceTypes = false;
308
continue;
309
}
310
if (Feature == "+relaxed-simd") {
311
SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);
312
continue;
313
}
314
if (Feature == "-relaxed-simd") {
315
SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));
316
continue;
317
}
318
if (Feature == "+sign-ext") {
319
HasSignExt = true;
320
continue;
321
}
322
if (Feature == "-sign-ext") {
323
HasSignExt = false;
324
continue;
325
}
326
if (Feature == "+simd128") {
327
SIMDLevel = std::max(SIMDLevel, SIMD128);
328
continue;
329
}
330
if (Feature == "-simd128") {
331
SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
332
continue;
333
}
334
if (Feature == "+tail-call") {
335
HasTailCall = true;
336
continue;
337
}
338
if (Feature == "-tail-call") {
339
HasTailCall = false;
340
continue;
341
}
342
if (Feature == "+wide-arithmetic") {
343
HasWideArithmetic = true;
344
continue;
345
}
346
if (Feature == "-wide-arithmetic") {
347
HasWideArithmetic = false;
348
continue;
349
}
350
351
Diags.Report(diag::err_opt_not_valid_with_opt)
352
<< Feature << "-target-feature";
353
return false;
354
}
355
356
// bulk-memory-opt is a subset of bulk-memory.
357
if (HasBulkMemory) {
358
HasBulkMemoryOpt = true;
359
}
360
361
// The reference-types feature included the change to `call_indirect`
362
// encodings to support overlong immediates.
363
if (HasReferenceTypes) {
364
HasCallIndirectOverlong = true;
365
}
366
367
return true;
368
}
369
370
llvm::SmallVector<Builtin::InfosShard>
371
WebAssemblyTargetInfo::getTargetBuiltins() const {
372
return {{&BuiltinStrings, BuiltinInfos}};
373
}
374
375
void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts,
376
const TargetInfo *Aux) {
377
TargetInfo::adjust(Diags, Opts, Aux);
378
// Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
379
// or __STDCPP_THREADS__ if we will eventually end up stripping atomics
380
// because they are unsupported.
381
if (!HasAtomics || !HasBulkMemory) {
382
Opts.POSIXThreads = false;
383
Opts.setThreadModel(LangOptions::ThreadModelKind::Single);
384
Opts.ThreadsafeStatics = false;
385
}
386
}
387
388
void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
389
MacroBuilder &Builder) const {
390
WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
391
defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
392
}
393
394
void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
395
MacroBuilder &Builder) const {
396
WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
397
defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
398
}
399
400