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 const Builtin::Info
WebAssemblyTargetInfo::BuiltinInfo
[] = {
24 #define BUILTIN(ID, TYPE, ATTRS) \
25 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
26 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
27 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
28 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
29 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
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__");
101 void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap
<bool> &Features
,
102 SIMDEnum Level
, bool Enabled
) {
106 Features
["relaxed-simd"] = true;
109 Features
["simd128"] = true;
120 Features
["simd128"] = false;
123 Features
["relaxed-simd"] = false;
128 void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap
<bool> &Features
,
130 bool Enabled
) const {
131 if (Name
== "simd128")
132 setSIMDLevel(Features
, SIMD128
, Enabled
);
133 else if (Name
== "relaxed-simd")
134 setSIMDLevel(Features
, RelaxedSIMD
, Enabled
);
136 Features
[Name
] = Enabled
;
139 bool WebAssemblyTargetInfo::initFeatureMap(
140 llvm::StringMap
<bool> &Features
, DiagnosticsEngine
&Diags
, StringRef CPU
,
141 const std::vector
<std::string
> &FeaturesVec
) const {
142 if (CPU
== "bleeding-edge") {
143 Features
["nontrapping-fptoint"] = true;
144 Features
["sign-ext"] = true;
145 Features
["bulk-memory"] = true;
146 Features
["atomics"] = true;
147 Features
["mutable-globals"] = true;
148 Features
["tail-call"] = true;
149 setSIMDLevel(Features
, SIMD128
, true);
152 return TargetInfo::initFeatureMap(Features
, Diags
, CPU
, FeaturesVec
);
155 bool WebAssemblyTargetInfo::handleTargetFeatures(
156 std::vector
<std::string
> &Features
, DiagnosticsEngine
&Diags
) {
157 for (const auto &Feature
: Features
) {
158 if (Feature
== "+simd128") {
159 SIMDLevel
= std::max(SIMDLevel
, SIMD128
);
162 if (Feature
== "-simd128") {
163 SIMDLevel
= std::min(SIMDLevel
, SIMDEnum(SIMD128
- 1));
166 if (Feature
== "+relaxed-simd") {
167 SIMDLevel
= std::max(SIMDLevel
, RelaxedSIMD
);
170 if (Feature
== "-relaxed-simd") {
171 SIMDLevel
= std::min(SIMDLevel
, SIMDEnum(RelaxedSIMD
- 1));
174 if (Feature
== "+nontrapping-fptoint") {
175 HasNontrappingFPToInt
= true;
178 if (Feature
== "-nontrapping-fptoint") {
179 HasNontrappingFPToInt
= false;
182 if (Feature
== "+sign-ext") {
186 if (Feature
== "-sign-ext") {
190 if (Feature
== "+exception-handling") {
191 HasExceptionHandling
= true;
194 if (Feature
== "-exception-handling") {
195 HasExceptionHandling
= false;
198 if (Feature
== "+bulk-memory") {
199 HasBulkMemory
= true;
202 if (Feature
== "-bulk-memory") {
203 HasBulkMemory
= false;
206 if (Feature
== "+atomics") {
210 if (Feature
== "-atomics") {
214 if (Feature
== "+mutable-globals") {
215 HasMutableGlobals
= true;
218 if (Feature
== "-mutable-globals") {
219 HasMutableGlobals
= false;
222 if (Feature
== "+multivalue") {
223 HasMultivalue
= true;
226 if (Feature
== "-multivalue") {
227 HasMultivalue
= false;
230 if (Feature
== "+tail-call") {
234 if (Feature
== "-tail-call") {
238 if (Feature
== "+reference-types") {
239 HasReferenceTypes
= true;
242 if (Feature
== "-reference-types") {
243 HasReferenceTypes
= false;
246 if (Feature
== "+extended-const") {
247 HasExtendedConst
= true;
250 if (Feature
== "-extended-const") {
251 HasExtendedConst
= false;
255 Diags
.Report(diag::err_opt_not_valid_with_opt
)
256 << Feature
<< "-target-feature";
262 ArrayRef
<Builtin::Info
> WebAssemblyTargetInfo::getTargetBuiltins() const {
263 return llvm::makeArrayRef(BuiltinInfo
, clang::WebAssembly::LastTSBuiltin
-
264 Builtin::FirstTSBuiltin
);
267 void WebAssemblyTargetInfo::adjust(DiagnosticsEngine
&Diags
,
269 TargetInfo::adjust(Diags
, Opts
);
270 // Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
271 // or __STDCPP_THREADS__ if we will eventually end up stripping atomics
272 // because they are unsupported.
273 if (!HasAtomics
|| !HasBulkMemory
) {
274 Opts
.POSIXThreads
= false;
275 Opts
.setThreadModel(LangOptions::ThreadModelKind::Single
);
276 Opts
.ThreadsafeStatics
= false;
280 void WebAssembly32TargetInfo::getTargetDefines(const LangOptions
&Opts
,
281 MacroBuilder
&Builder
) const {
282 WebAssemblyTargetInfo::getTargetDefines(Opts
, Builder
);
283 defineCPUMacros(Builder
, "wasm32", /*Tuning=*/false);
286 void WebAssembly64TargetInfo::getTargetDefines(const LangOptions
&Opts
,
287 MacroBuilder
&Builder
) const {
288 WebAssemblyTargetInfo::getTargetDefines(Opts
, Builder
);
289 defineCPUMacros(Builder
, "wasm64", /*Tuning=*/false);