clang 24.0.0git
WebAssembly.cpp
Go to the documentation of this file.
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"
18#include "llvm/ADT/StringSwitch.h"
19
20using namespace clang;
21using namespace clang::targets;
22
23static constexpr int NumBuiltins =
25
26static constexpr llvm::StringTable BuiltinStrings =
28#define BUILTIN CLANG_BUILTIN_STR_TABLE
29#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
30#include "clang/Basic/BuiltinsWebAssembly.def"
31 ;
32
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
40static constexpr llvm::StringLiteral ValidCPUNames[] = {
41 {"mvp"}, {"bleeding-edge"}, {"generic"}, {"lime1"}};
42
43StringRef WebAssemblyTargetInfo::getABI() const { return ABI; }
44
45bool 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
53bool 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("compact-imports", HasCompactImports)
60 .Case("exception-handling", HasExceptionHandling)
61 .Case("extended-const", HasExtendedConst)
62 .Case("fp16", HasFP16)
63 .Case("gc", HasGC)
64 .Case("multimemory", HasMultiMemory)
65 .Case("multivalue", HasMultivalue)
66 .Case("mutable-globals", HasMutableGlobals)
67 .Case("nontrapping-fptoint", HasNontrappingFPToInt)
68 .Case("reference-types", HasReferenceTypes)
69 .Case("relaxed-atomics", HasRelaxedAtomics)
70 .Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
71 .Case("sign-ext", HasSignExt)
72 .Case("simd128", SIMDLevel >= SIMD128)
73 .Case("tail-call", HasTailCall)
74 .Case("wide-arithmetic", HasWideArithmetic)
75 .Default(false);
76}
77
78bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
79 return llvm::is_contained(ValidCPUNames, Name);
80}
81
82void WebAssemblyTargetInfo::fillValidCPUList(
83 SmallVectorImpl<StringRef> &Values) const {
84 Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
85}
86
88 MacroBuilder &Builder) const {
89 defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
90 if (HasAtomics)
91 Builder.defineMacro("__wasm_atomics__");
92 if (HasBulkMemory)
93 Builder.defineMacro("__wasm_bulk_memory__");
94 if (HasBulkMemoryOpt)
95 Builder.defineMacro("__wasm_bulk_memory_opt__");
96 if (HasExceptionHandling)
97 Builder.defineMacro("__wasm_exception_handling__");
98 if (HasExtendedConst)
99 Builder.defineMacro("__wasm_extended_const__");
100 if (HasMultiMemory)
101 Builder.defineMacro("__wasm_multimemory__");
102 if (HasFP16)
103 Builder.defineMacro("__wasm_fp16__");
104 if (HasGC)
105 Builder.defineMacro("__wasm_gc__");
106 if (HasMultivalue)
107 Builder.defineMacro("__wasm_multivalue__");
108 if (HasMutableGlobals)
109 Builder.defineMacro("__wasm_mutable_globals__");
110 if (HasNontrappingFPToInt)
111 Builder.defineMacro("__wasm_nontrapping_fptoint__");
112 if (HasReferenceTypes)
113 Builder.defineMacro("__wasm_reference_types__");
114 if (HasRelaxedAtomics)
115 Builder.defineMacro("__wasm_relaxed_atomics__");
116 if (SIMDLevel >= RelaxedSIMD)
117 Builder.defineMacro("__wasm_relaxed_simd__");
118 if (HasSignExt)
119 Builder.defineMacro("__wasm_sign_ext__");
120 if (SIMDLevel >= SIMD128)
121 Builder.defineMacro("__wasm_simd128__");
122 if (HasTailCall)
123 Builder.defineMacro("__wasm_tail_call__");
124 if (HasWideArithmetic)
125 Builder.defineMacro("__wasm_wide_arithmetic__");
126 if (HasLibcallThreadContext)
127 Builder.defineMacro("__wasm_libcall_thread_context__");
128 // Note that not all wasm features appear here. For example,
129 // HasCompatctImports
130
131 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
132 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
133 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
134 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
135}
136
137void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
138 SIMDEnum Level, bool Enabled) {
139 if (Enabled) {
140 switch (Level) {
141 case RelaxedSIMD:
142 Features["relaxed-simd"] = true;
143 [[fallthrough]];
144 case SIMD128:
145 Features["simd128"] = true;
146 [[fallthrough]];
147 case NoSIMD:
148 break;
149 }
150 return;
151 }
152
153 switch (Level) {
154 case NoSIMD:
155 case SIMD128:
156 Features["simd128"] = false;
157 [[fallthrough]];
158 case RelaxedSIMD:
159 Features["relaxed-simd"] = false;
160 break;
161 }
162}
163
164void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
165 StringRef Name,
166 bool Enabled) const {
167 if (Name == "simd128")
168 setSIMDLevel(Features, SIMD128, Enabled);
169 else if (Name == "relaxed-simd")
170 setSIMDLevel(Features, RelaxedSIMD, Enabled);
171 else
172 Features[Name] = Enabled;
173}
174
175bool WebAssemblyTargetInfo::initFeatureMap(
176 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
177 const std::vector<std::string> &FeaturesVec) const {
178 auto addGenericFeatures = [&]() {
179 Features["bulk-memory"] = true;
180 Features["bulk-memory-opt"] = true;
181 Features["call-indirect-overlong"] = true;
182 Features["multivalue"] = true;
183 Features["mutable-globals"] = true;
184 Features["nontrapping-fptoint"] = true;
185 Features["reference-types"] = true;
186 Features["sign-ext"] = true;
187 };
188 auto addLime1Features = [&]() {
189 // Lime1:
190 // <https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#lime1>
191 Features["bulk-memory-opt"] = true;
192 Features["call-indirect-overlong"] = true;
193 Features["extended-const"] = true;
194 Features["multivalue"] = true;
195 Features["mutable-globals"] = true;
196 Features["nontrapping-fptoint"] = true;
197 Features["sign-ext"] = true;
198 };
199 auto addBleedingEdgeFeatures = [&]() {
200 addGenericFeatures();
201 Features["atomics"] = true;
202 Features["compact-imports"] = true;
203 Features["exception-handling"] = true;
204 Features["extended-const"] = true;
205 Features["fp16"] = true;
206 Features["gc"] = true;
207 Features["multimemory"] = true;
208 Features["relaxed-atomics"] = true;
209 Features["tail-call"] = true;
210 Features["wide-arithmetic"] = true;
211 setSIMDLevel(Features, RelaxedSIMD, true);
212 };
213 if (CPU == "generic") {
214 addGenericFeatures();
215 } else if (CPU == "lime1") {
216 addLime1Features();
217 } else if (CPU == "bleeding-edge") {
218 addBleedingEdgeFeatures();
219 }
220
221 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
222}
223
224bool WebAssemblyTargetInfo::handleTargetFeatures(
225 std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
226 HasMustTail = false;
227 for (const auto &Feature : Features) {
228 if (Feature == "+atomics") {
229 HasAtomics = true;
230 continue;
231 }
232 if (Feature == "-atomics") {
233 HasAtomics = false;
234 continue;
235 }
236 if (Feature == "+bulk-memory") {
237 HasBulkMemory = true;
238 continue;
239 }
240 if (Feature == "-bulk-memory") {
241 HasBulkMemory = false;
242 continue;
243 }
244 if (Feature == "+bulk-memory-opt") {
245 HasBulkMemoryOpt = true;
246 continue;
247 }
248 if (Feature == "-bulk-memory-opt") {
249 HasBulkMemoryOpt = false;
250 continue;
251 }
252 if (Feature == "+call-indirect-overlong") {
253 HasCallIndirectOverlong = true;
254 continue;
255 }
256 if (Feature == "-call-indirect-overlong") {
257 HasCallIndirectOverlong = false;
258 continue;
259 }
260 if (Feature == "+compact-imports") {
261 HasCompactImports = true;
262 continue;
263 }
264 if (Feature == "-compact-imports") {
265 HasCompactImports = false;
266 continue;
267 }
268 if (Feature == "+exception-handling") {
269 HasExceptionHandling = true;
270 continue;
271 }
272 if (Feature == "-exception-handling") {
273 HasExceptionHandling = false;
274 continue;
275 }
276 if (Feature == "+extended-const") {
277 HasExtendedConst = true;
278 continue;
279 }
280 if (Feature == "-extended-const") {
281 HasExtendedConst = false;
282 continue;
283 }
284 if (Feature == "+fp16") {
285 SIMDLevel = std::max(SIMDLevel, SIMD128);
286 HasFP16 = true;
287 continue;
288 }
289 if (Feature == "-fp16") {
290 HasFP16 = false;
291 continue;
292 }
293 if (Feature == "+gc") {
294 HasGC = true;
295 continue;
296 }
297 if (Feature == "-gc") {
298 HasGC = false;
299 continue;
300 }
301 if (Feature == "+multimemory") {
302 HasMultiMemory = true;
303 continue;
304 }
305 if (Feature == "-multimemory") {
306 HasMultiMemory = false;
307 continue;
308 }
309 if (Feature == "+multivalue") {
310 HasMultivalue = true;
311 continue;
312 }
313 if (Feature == "-multivalue") {
314 HasMultivalue = false;
315 continue;
316 }
317 if (Feature == "+mutable-globals") {
318 HasMutableGlobals = true;
319 continue;
320 }
321 if (Feature == "-mutable-globals") {
322 HasMutableGlobals = false;
323 continue;
324 }
325 if (Feature == "+nontrapping-fptoint") {
326 HasNontrappingFPToInt = true;
327 continue;
328 }
329 if (Feature == "-nontrapping-fptoint") {
330 HasNontrappingFPToInt = false;
331 continue;
332 }
333 if (Feature == "+reference-types") {
334 HasReferenceTypes = true;
335 continue;
336 }
337 if (Feature == "-reference-types") {
338 HasReferenceTypes = false;
339 continue;
340 }
341 if (Feature == "+relaxed-atomics") {
342 HasRelaxedAtomics = true;
343 continue;
344 }
345 if (Feature == "-relaxed-atomics") {
346 HasRelaxedAtomics = false;
347 continue;
348 }
349 if (Feature == "+relaxed-simd") {
350 SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);
351 continue;
352 }
353 if (Feature == "-relaxed-simd") {
354 SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));
355 continue;
356 }
357 if (Feature == "+sign-ext") {
358 HasSignExt = true;
359 continue;
360 }
361 if (Feature == "-sign-ext") {
362 HasSignExt = false;
363 continue;
364 }
365 if (Feature == "+simd128") {
366 SIMDLevel = std::max(SIMDLevel, SIMD128);
367 continue;
368 }
369 if (Feature == "-simd128") {
370 SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
371 continue;
372 }
373 if (Feature == "+tail-call") {
374 HasTailCall = true;
375 HasMustTail = true;
376 continue;
377 }
378 if (Feature == "-tail-call") {
379 HasTailCall = false;
380 HasMustTail = false;
381 continue;
382 }
383 if (Feature == "+wide-arithmetic") {
384 HasWideArithmetic = true;
385 continue;
386 }
387 if (Feature == "-wide-arithmetic") {
388 HasWideArithmetic = false;
389 continue;
390 }
391
392 Diags.Report(diag::err_opt_not_valid_with_opt)
393 << Feature << "-target-feature";
394 return false;
395 }
396
397 // gc implies reference-types
398 if (HasGC) {
399 HasReferenceTypes = true;
400 }
401
402 // bulk-memory-opt is a subset of bulk-memory.
403 if (HasBulkMemory) {
404 HasBulkMemoryOpt = true;
405 }
406
407 // The reference-types feature included the change to `call_indirect`
408 // encodings to support overlong immediates.
409 if (HasReferenceTypes) {
410 HasCallIndirectOverlong = true;
411 }
412
413 return true;
414}
415
416llvm::SmallVector<Builtin::InfosShard>
418 return {{&BuiltinStrings, BuiltinInfos}};
419}
420
422 MacroBuilder &Builder) const {
424 defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
425}
426
428 MacroBuilder &Builder) const {
430 defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
431}
Defines the Diagnostic-related interfaces.
static constexpr llvm::StringTable BuiltinStrings
Definition AVR.cpp:24
static constexpr llvm::StringLiteral ValidCPUNames[]
Definition BPF.cpp:83
static constexpr Builtin::Info BuiltinInfos[]
Definition Builtins.cpp:39
static constexpr unsigned NumBuiltins
Definition Builtins.cpp:33
Defines enum values for all the target-independent builtin functions.
#define CLANG_BUILTIN_STR_TABLE_START
Definition Builtins.h:167
Enumerates target-specific builtins in their own namespaces within namespace clang.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
virtual llvm::SmallVector< Builtin::InfosShard > getTargetBuiltins() const =0
Return information about target-specific builtins for the current primary target, and info about whic...
virtual bool initFeatureMap(llvm::StringMap< bool > &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector< std::string > &FeatureVec) const
Initialize the map with the default set of target features for the CPU this should include all legal ...
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override
===-— Other target property query methods -----------------------—===//
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override
===-— Other target property query methods -----------------------—===//
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override
===-— Other target property query methods -----------------------—===//
StringRef getABI() const override
Get the ABI currently in use.
bool setABI(const std::string &Name) override
Use the specified ABI.
static constexpr std::array< Info, N > MakeInfos(std::array< Info, N > Infos)
A constexpr function to construct an infos array from X-macros.
Definition Builtins.h:116
LLVM_LIBRARY_VISIBILITY void defineCPUMacros(clang::MacroBuilder &Builder, llvm::StringRef CPUName, bool Tuning=true)
Top level wrappers for InstallAPI frontend operations.