1 //===--- WebAssembly.cpp - Implement WebAssembly target feature support ---===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements WebAssembly TargetInfo objects.
11 //===----------------------------------------------------------------------===//
13 #include "WebAssembly.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"
20 using namespace clang
;
21 using namespace clang::targets
;
23 static constexpr Builtin::Info BuiltinInfo
[] = {
24 #define BUILTIN(ID, TYPE, ATTRS) \
25 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
26 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
27 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
28 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
29 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
30 #include "clang/Basic/BuiltinsWebAssembly.def"
33 static constexpr llvm::StringLiteral ValidCPUNames
[] = {
34 {"mvp"}, {"bleeding-edge"}, {"generic"}};
36 StringRef
WebAssemblyTargetInfo::getABI() const { return ABI
; }
38 bool WebAssemblyTargetInfo::setABI(const std::string
&Name
) {
39 if (Name
!= "mvp" && Name
!= "experimental-mv")
46 bool WebAssemblyTargetInfo::hasFeature(StringRef Feature
) const {
47 return llvm::StringSwitch
<bool>(Feature
)
48 .Case("simd128", SIMDLevel
>= SIMD128
)
49 .Case("relaxed-simd", SIMDLevel
>= RelaxedSIMD
)
50 .Case("nontrapping-fptoint", HasNontrappingFPToInt
)
51 .Case("sign-ext", HasSignExt
)
52 .Case("exception-handling", HasExceptionHandling
)
53 .Case("bulk-memory", HasBulkMemory
)
54 .Case("atomics", HasAtomics
)
55 .Case("mutable-globals", HasMutableGlobals
)
56 .Case("multivalue", HasMultivalue
)
57 .Case("tail-call", HasTailCall
)
58 .Case("reference-types", HasReferenceTypes
)
59 .Case("extended-const", HasExtendedConst
)
63 bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name
) const {
64 return llvm::is_contained(ValidCPUNames
, Name
);
67 void WebAssemblyTargetInfo::fillValidCPUList(
68 SmallVectorImpl
<StringRef
> &Values
) const {
69 Values
.append(std::begin(ValidCPUNames
), std::end(ValidCPUNames
));
72 void WebAssemblyTargetInfo::getTargetDefines(const LangOptions
&Opts
,
73 MacroBuilder
&Builder
) const {
74 defineCPUMacros(Builder
, "wasm", /*Tuning=*/false);
75 if (SIMDLevel
>= SIMD128
)
76 Builder
.defineMacro("__wasm_simd128__");
77 if (SIMDLevel
>= RelaxedSIMD
)
78 Builder
.defineMacro("__wasm_relaxed_simd__");
79 if (HasNontrappingFPToInt
)
80 Builder
.defineMacro("__wasm_nontrapping_fptoint__");
82 Builder
.defineMacro("__wasm_sign_ext__");
83 if (HasExceptionHandling
)
84 Builder
.defineMacro("__wasm_exception_handling__");
86 Builder
.defineMacro("__wasm_bulk_memory__");
88 Builder
.defineMacro("__wasm_atomics__");
89 if (HasMutableGlobals
)
90 Builder
.defineMacro("__wasm_mutable_globals__");
92 Builder
.defineMacro("__wasm_multivalue__");
94 Builder
.defineMacro("__wasm_tail_call__");
95 if (HasReferenceTypes
)
96 Builder
.defineMacro("__wasm_reference_types__");
98 Builder
.defineMacro("__wasm_extended_const__");
100 Builder
.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
101 Builder
.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
102 Builder
.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
103 Builder
.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
106 void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap
<bool> &Features
,
107 SIMDEnum Level
, bool Enabled
) {
111 Features
["relaxed-simd"] = true;
114 Features
["simd128"] = true;
125 Features
["simd128"] = false;
128 Features
["relaxed-simd"] = false;
133 void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap
<bool> &Features
,
135 bool Enabled
) const {
136 if (Name
== "simd128")
137 setSIMDLevel(Features
, SIMD128
, Enabled
);
138 else if (Name
== "relaxed-simd")
139 setSIMDLevel(Features
, RelaxedSIMD
, Enabled
);
141 Features
[Name
] = Enabled
;
144 bool WebAssemblyTargetInfo::initFeatureMap(
145 llvm::StringMap
<bool> &Features
, DiagnosticsEngine
&Diags
, StringRef CPU
,
146 const std::vector
<std::string
> &FeaturesVec
) const {
147 if (CPU
== "bleeding-edge") {
148 Features
["nontrapping-fptoint"] = true;
149 Features
["sign-ext"] = true;
150 Features
["bulk-memory"] = true;
151 Features
["atomics"] = true;
152 Features
["mutable-globals"] = true;
153 Features
["tail-call"] = true;
154 setSIMDLevel(Features
, SIMD128
, true);
155 } else if (CPU
== "generic") {
156 Features
["sign-ext"] = true;
157 Features
["mutable-globals"] = true;
160 return TargetInfo::initFeatureMap(Features
, Diags
, CPU
, FeaturesVec
);
163 bool WebAssemblyTargetInfo::handleTargetFeatures(
164 std::vector
<std::string
> &Features
, DiagnosticsEngine
&Diags
) {
165 for (const auto &Feature
: Features
) {
166 if (Feature
== "+simd128") {
167 SIMDLevel
= std::max(SIMDLevel
, SIMD128
);
170 if (Feature
== "-simd128") {
171 SIMDLevel
= std::min(SIMDLevel
, SIMDEnum(SIMD128
- 1));
174 if (Feature
== "+relaxed-simd") {
175 SIMDLevel
= std::max(SIMDLevel
, RelaxedSIMD
);
178 if (Feature
== "-relaxed-simd") {
179 SIMDLevel
= std::min(SIMDLevel
, SIMDEnum(RelaxedSIMD
- 1));
182 if (Feature
== "+nontrapping-fptoint") {
183 HasNontrappingFPToInt
= true;
186 if (Feature
== "-nontrapping-fptoint") {
187 HasNontrappingFPToInt
= false;
190 if (Feature
== "+sign-ext") {
194 if (Feature
== "-sign-ext") {
198 if (Feature
== "+exception-handling") {
199 HasExceptionHandling
= true;
202 if (Feature
== "-exception-handling") {
203 HasExceptionHandling
= false;
206 if (Feature
== "+bulk-memory") {
207 HasBulkMemory
= true;
210 if (Feature
== "-bulk-memory") {
211 HasBulkMemory
= false;
214 if (Feature
== "+atomics") {
218 if (Feature
== "-atomics") {
222 if (Feature
== "+mutable-globals") {
223 HasMutableGlobals
= true;
226 if (Feature
== "-mutable-globals") {
227 HasMutableGlobals
= false;
230 if (Feature
== "+multivalue") {
231 HasMultivalue
= true;
234 if (Feature
== "-multivalue") {
235 HasMultivalue
= false;
238 if (Feature
== "+tail-call") {
242 if (Feature
== "-tail-call") {
246 if (Feature
== "+reference-types") {
247 HasReferenceTypes
= true;
250 if (Feature
== "-reference-types") {
251 HasReferenceTypes
= false;
254 if (Feature
== "+extended-const") {
255 HasExtendedConst
= true;
258 if (Feature
== "-extended-const") {
259 HasExtendedConst
= false;
263 Diags
.Report(diag::err_opt_not_valid_with_opt
)
264 << Feature
<< "-target-feature";
270 ArrayRef
<Builtin::Info
> WebAssemblyTargetInfo::getTargetBuiltins() const {
271 return llvm::ArrayRef(BuiltinInfo
, clang::WebAssembly::LastTSBuiltin
-
272 Builtin::FirstTSBuiltin
);
275 void WebAssemblyTargetInfo::adjust(DiagnosticsEngine
&Diags
,
277 TargetInfo::adjust(Diags
, Opts
);
278 // Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
279 // or __STDCPP_THREADS__ if we will eventually end up stripping atomics
280 // because they are unsupported.
281 if (!HasAtomics
|| !HasBulkMemory
) {
282 Opts
.POSIXThreads
= false;
283 Opts
.setThreadModel(LangOptions::ThreadModelKind::Single
);
284 Opts
.ThreadsafeStatics
= false;
288 void WebAssembly32TargetInfo::getTargetDefines(const LangOptions
&Opts
,
289 MacroBuilder
&Builder
) const {
290 WebAssemblyTargetInfo::getTargetDefines(Opts
, Builder
);
291 defineCPUMacros(Builder
, "wasm32", /*Tuning=*/false);
294 void WebAssembly64TargetInfo::getTargetDefines(const LangOptions
&Opts
,
295 MacroBuilder
&Builder
) const {
296 WebAssemblyTargetInfo::getTargetDefines(Opts
, Builder
);
297 defineCPUMacros(Builder
, "wasm64", /*Tuning=*/false);