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
20using namespace clang;
21using namespace clang::targets;
22
23static constexpr int NumBuiltins =
24 clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin;
25
26static 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
33static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>(Infos: {
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(S: "atomics", Value: HasAtomics)
56 .Case(S: "bulk-memory", Value: HasBulkMemory)
57 .Case(S: "bulk-memory-opt", Value: HasBulkMemoryOpt)
58 .Case(S: "call-indirect-overlong", Value: HasCallIndirectOverlong)
59 .Case(S: "exception-handling", Value: HasExceptionHandling)
60 .Case(S: "extended-const", Value: HasExtendedConst)
61 .Case(S: "fp16", Value: HasFP16)
62 .Case(S: "multimemory", Value: HasMultiMemory)
63 .Case(S: "multivalue", Value: HasMultivalue)
64 .Case(S: "mutable-globals", Value: HasMutableGlobals)
65 .Case(S: "nontrapping-fptoint", Value: HasNontrappingFPToInt)
66 .Case(S: "reference-types", Value: HasReferenceTypes)
67 .Case(S: "relaxed-simd", Value: SIMDLevel >= RelaxedSIMD)
68 .Case(S: "sign-ext", Value: HasSignExt)
69 .Case(S: "simd128", Value: SIMDLevel >= SIMD128)
70 .Case(S: "tail-call", Value: HasTailCall)
71 .Case(S: "wide-arithmetic", Value: HasWideArithmetic)
72 .Default(Value: false);
73}
74
75bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
76 return llvm::is_contained(Range: ValidCPUNames, Element: Name);
77}
78
79void WebAssemblyTargetInfo::fillValidCPUList(
80 SmallVectorImpl<StringRef> &Values) const {
81 Values.append(in_start: std::begin(arr: ValidCPUNames), in_end: std::end(arr: ValidCPUNames));
82}
83
84void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
85 MacroBuilder &Builder) const {
86 defineCPUMacros(Builder, CPUName: "wasm", /*Tuning=*/false);
87 if (HasAtomics)
88 Builder.defineMacro(Name: "__wasm_atomics__");
89 if (HasBulkMemory)
90 Builder.defineMacro(Name: "__wasm_bulk_memory__");
91 if (HasBulkMemoryOpt)
92 Builder.defineMacro(Name: "__wasm_bulk_memory_opt__");
93 if (HasExceptionHandling)
94 Builder.defineMacro(Name: "__wasm_exception_handling__");
95 if (HasExtendedConst)
96 Builder.defineMacro(Name: "__wasm_extended_const__");
97 if (HasMultiMemory)
98 Builder.defineMacro(Name: "__wasm_multimemory__");
99 if (HasFP16)
100 Builder.defineMacro(Name: "__wasm_fp16__");
101 if (HasMultivalue)
102 Builder.defineMacro(Name: "__wasm_multivalue__");
103 if (HasMutableGlobals)
104 Builder.defineMacro(Name: "__wasm_mutable_globals__");
105 if (HasNontrappingFPToInt)
106 Builder.defineMacro(Name: "__wasm_nontrapping_fptoint__");
107 if (HasReferenceTypes)
108 Builder.defineMacro(Name: "__wasm_reference_types__");
109 if (SIMDLevel >= RelaxedSIMD)
110 Builder.defineMacro(Name: "__wasm_relaxed_simd__");
111 if (HasSignExt)
112 Builder.defineMacro(Name: "__wasm_sign_ext__");
113 if (SIMDLevel >= SIMD128)
114 Builder.defineMacro(Name: "__wasm_simd128__");
115 if (HasTailCall)
116 Builder.defineMacro(Name: "__wasm_tail_call__");
117 if (HasWideArithmetic)
118 Builder.defineMacro(Name: "__wasm_wide_arithmetic__");
119
120 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
121 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
122 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
123 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
124}
125
126void 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
153void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
154 StringRef Name,
155 bool Enabled) const {
156 if (Name == "simd128")
157 setSIMDLevel(Features, Level: SIMD128, Enabled);
158 else if (Name == "relaxed-simd")
159 setSIMDLevel(Features, Level: RelaxedSIMD, Enabled);
160 else
161 Features[Name] = Enabled;
162}
163
164bool 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, Level: RelaxedSIMD, Enabled: 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, FeatureVec: FeaturesVec);
208}
209
210bool 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(a: SIMDLevel, b: 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(a: SIMDLevel, b: RelaxedSIMD);
312 continue;
313 }
314 if (Feature == "-relaxed-simd") {
315 SIMDLevel = std::min(a: SIMDLevel, b: 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(a: SIMDLevel, b: SIMD128);
328 continue;
329 }
330 if (Feature == "-simd128") {
331 SIMDLevel = std::min(a: SIMDLevel, b: 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
370llvm::SmallVector<Builtin::InfosShard>
371WebAssemblyTargetInfo::getTargetBuiltins() const {
372 return {{&BuiltinStrings, BuiltinInfos}};
373}
374
375void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags,
376 LangOptions &Opts) {
377 TargetInfo::adjust(Diags, Opts);
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
388void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
389 MacroBuilder &Builder) const {
390 WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
391 defineCPUMacros(Builder, CPUName: "wasm32", /*Tuning=*/false);
392}
393
394void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
395 MacroBuilder &Builder) const {
396 WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
397 defineCPUMacros(Builder, CPUName: "wasm64", /*Tuning=*/false);
398}
399

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Basic/Targets/WebAssembly.cpp