xref: /openbsd-src/gnu/llvm/clang/lib/Basic/Targets/WebAssembly.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===--- WebAssembly.cpp - Implement WebAssembly target feature support ---===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements WebAssembly TargetInfo objects.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick 
13e5dd7070Spatrick #include "WebAssembly.h"
14e5dd7070Spatrick #include "Targets.h"
15e5dd7070Spatrick #include "clang/Basic/Builtins.h"
16e5dd7070Spatrick #include "clang/Basic/Diagnostic.h"
17e5dd7070Spatrick #include "clang/Basic/TargetBuiltins.h"
18e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
19e5dd7070Spatrick 
20e5dd7070Spatrick using namespace clang;
21e5dd7070Spatrick using namespace clang::targets;
22e5dd7070Spatrick 
23*12c85518Srobert static constexpr Builtin::Info BuiltinInfo[] = {
24e5dd7070Spatrick #define BUILTIN(ID, TYPE, ATTRS)                                               \
25*12c85518Srobert   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
26e5dd7070Spatrick #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
27*12c85518Srobert   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
28e5dd7070Spatrick #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
29*12c85518Srobert   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
30e5dd7070Spatrick #include "clang/Basic/BuiltinsWebAssembly.def"
31e5dd7070Spatrick };
32e5dd7070Spatrick 
33e5dd7070Spatrick static constexpr llvm::StringLiteral ValidCPUNames[] = {
34e5dd7070Spatrick     {"mvp"}, {"bleeding-edge"}, {"generic"}};
35e5dd7070Spatrick 
getABI() const36ec727ea7Spatrick StringRef WebAssemblyTargetInfo::getABI() const { return ABI; }
37ec727ea7Spatrick 
setABI(const std::string & Name)38ec727ea7Spatrick bool WebAssemblyTargetInfo::setABI(const std::string &Name) {
39ec727ea7Spatrick   if (Name != "mvp" && Name != "experimental-mv")
40ec727ea7Spatrick     return false;
41ec727ea7Spatrick 
42ec727ea7Spatrick   ABI = Name;
43ec727ea7Spatrick   return true;
44ec727ea7Spatrick }
45ec727ea7Spatrick 
hasFeature(StringRef Feature) const46e5dd7070Spatrick bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
47e5dd7070Spatrick   return llvm::StringSwitch<bool>(Feature)
48e5dd7070Spatrick       .Case("simd128", SIMDLevel >= SIMD128)
49*12c85518Srobert       .Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
50e5dd7070Spatrick       .Case("nontrapping-fptoint", HasNontrappingFPToInt)
51e5dd7070Spatrick       .Case("sign-ext", HasSignExt)
52e5dd7070Spatrick       .Case("exception-handling", HasExceptionHandling)
53e5dd7070Spatrick       .Case("bulk-memory", HasBulkMemory)
54e5dd7070Spatrick       .Case("atomics", HasAtomics)
55e5dd7070Spatrick       .Case("mutable-globals", HasMutableGlobals)
56e5dd7070Spatrick       .Case("multivalue", HasMultivalue)
57e5dd7070Spatrick       .Case("tail-call", HasTailCall)
58ec727ea7Spatrick       .Case("reference-types", HasReferenceTypes)
59*12c85518Srobert       .Case("extended-const", HasExtendedConst)
60e5dd7070Spatrick       .Default(false);
61e5dd7070Spatrick }
62e5dd7070Spatrick 
isValidCPUName(StringRef Name) const63e5dd7070Spatrick bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
64*12c85518Srobert   return llvm::is_contained(ValidCPUNames, Name);
65e5dd7070Spatrick }
66e5dd7070Spatrick 
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const67e5dd7070Spatrick void WebAssemblyTargetInfo::fillValidCPUList(
68e5dd7070Spatrick     SmallVectorImpl<StringRef> &Values) const {
69e5dd7070Spatrick   Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
70e5dd7070Spatrick }
71e5dd7070Spatrick 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const72e5dd7070Spatrick void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
73e5dd7070Spatrick                                              MacroBuilder &Builder) const {
74e5dd7070Spatrick   defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
75e5dd7070Spatrick   if (SIMDLevel >= SIMD128)
76e5dd7070Spatrick     Builder.defineMacro("__wasm_simd128__");
77*12c85518Srobert   if (SIMDLevel >= RelaxedSIMD)
78*12c85518Srobert     Builder.defineMacro("__wasm_relaxed_simd__");
79e5dd7070Spatrick   if (HasNontrappingFPToInt)
80e5dd7070Spatrick     Builder.defineMacro("__wasm_nontrapping_fptoint__");
81e5dd7070Spatrick   if (HasSignExt)
82e5dd7070Spatrick     Builder.defineMacro("__wasm_sign_ext__");
83e5dd7070Spatrick   if (HasExceptionHandling)
84e5dd7070Spatrick     Builder.defineMacro("__wasm_exception_handling__");
85e5dd7070Spatrick   if (HasBulkMemory)
86e5dd7070Spatrick     Builder.defineMacro("__wasm_bulk_memory__");
87e5dd7070Spatrick   if (HasAtomics)
88e5dd7070Spatrick     Builder.defineMacro("__wasm_atomics__");
89e5dd7070Spatrick   if (HasMutableGlobals)
90e5dd7070Spatrick     Builder.defineMacro("__wasm_mutable_globals__");
91e5dd7070Spatrick   if (HasMultivalue)
92e5dd7070Spatrick     Builder.defineMacro("__wasm_multivalue__");
93e5dd7070Spatrick   if (HasTailCall)
94e5dd7070Spatrick     Builder.defineMacro("__wasm_tail_call__");
95ec727ea7Spatrick   if (HasReferenceTypes)
96ec727ea7Spatrick     Builder.defineMacro("__wasm_reference_types__");
97*12c85518Srobert   if (HasExtendedConst)
98*12c85518Srobert     Builder.defineMacro("__wasm_extended_const__");
99*12c85518Srobert 
100*12c85518Srobert   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
101*12c85518Srobert   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
102*12c85518Srobert   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
103*12c85518Srobert   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
104e5dd7070Spatrick }
105e5dd7070Spatrick 
setSIMDLevel(llvm::StringMap<bool> & Features,SIMDEnum Level,bool Enabled)106e5dd7070Spatrick void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
107ec727ea7Spatrick                                          SIMDEnum Level, bool Enabled) {
108ec727ea7Spatrick   if (Enabled) {
109e5dd7070Spatrick     switch (Level) {
110*12c85518Srobert     case RelaxedSIMD:
111*12c85518Srobert       Features["relaxed-simd"] = true;
112*12c85518Srobert       [[fallthrough]];
113e5dd7070Spatrick     case SIMD128:
114e5dd7070Spatrick       Features["simd128"] = true;
115*12c85518Srobert       [[fallthrough]];
116e5dd7070Spatrick     case NoSIMD:
117e5dd7070Spatrick       break;
118e5dd7070Spatrick     }
119ec727ea7Spatrick     return;
120ec727ea7Spatrick   }
121ec727ea7Spatrick 
122ec727ea7Spatrick   switch (Level) {
123ec727ea7Spatrick   case NoSIMD:
124ec727ea7Spatrick   case SIMD128:
125ec727ea7Spatrick     Features["simd128"] = false;
126*12c85518Srobert     [[fallthrough]];
127*12c85518Srobert   case RelaxedSIMD:
128*12c85518Srobert     Features["relaxed-simd"] = false;
129ec727ea7Spatrick     break;
130ec727ea7Spatrick   }
131ec727ea7Spatrick }
132ec727ea7Spatrick 
setFeatureEnabled(llvm::StringMap<bool> & Features,StringRef Name,bool Enabled) const133ec727ea7Spatrick void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
134ec727ea7Spatrick                                               StringRef Name,
135ec727ea7Spatrick                                               bool Enabled) const {
136ec727ea7Spatrick   if (Name == "simd128")
137ec727ea7Spatrick     setSIMDLevel(Features, SIMD128, Enabled);
138*12c85518Srobert   else if (Name == "relaxed-simd")
139*12c85518Srobert     setSIMDLevel(Features, RelaxedSIMD, Enabled);
140ec727ea7Spatrick   else
141ec727ea7Spatrick     Features[Name] = Enabled;
142e5dd7070Spatrick }
143e5dd7070Spatrick 
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const144e5dd7070Spatrick bool WebAssemblyTargetInfo::initFeatureMap(
145e5dd7070Spatrick     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
146e5dd7070Spatrick     const std::vector<std::string> &FeaturesVec) const {
147e5dd7070Spatrick   if (CPU == "bleeding-edge") {
148e5dd7070Spatrick     Features["nontrapping-fptoint"] = true;
149e5dd7070Spatrick     Features["sign-ext"] = true;
150e5dd7070Spatrick     Features["bulk-memory"] = true;
151e5dd7070Spatrick     Features["atomics"] = true;
152e5dd7070Spatrick     Features["mutable-globals"] = true;
153e5dd7070Spatrick     Features["tail-call"] = true;
154ec727ea7Spatrick     setSIMDLevel(Features, SIMD128, true);
155*12c85518Srobert   } else if (CPU == "generic") {
156*12c85518Srobert     Features["sign-ext"] = true;
157*12c85518Srobert     Features["mutable-globals"] = true;
158ec727ea7Spatrick   }
159e5dd7070Spatrick 
160e5dd7070Spatrick   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
161e5dd7070Spatrick }
162e5dd7070Spatrick 
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)163e5dd7070Spatrick bool WebAssemblyTargetInfo::handleTargetFeatures(
164e5dd7070Spatrick     std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
165e5dd7070Spatrick   for (const auto &Feature : Features) {
166e5dd7070Spatrick     if (Feature == "+simd128") {
167e5dd7070Spatrick       SIMDLevel = std::max(SIMDLevel, SIMD128);
168e5dd7070Spatrick       continue;
169e5dd7070Spatrick     }
170e5dd7070Spatrick     if (Feature == "-simd128") {
171e5dd7070Spatrick       SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
172e5dd7070Spatrick       continue;
173e5dd7070Spatrick     }
174*12c85518Srobert     if (Feature == "+relaxed-simd") {
175*12c85518Srobert       SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);
176*12c85518Srobert       continue;
177*12c85518Srobert     }
178*12c85518Srobert     if (Feature == "-relaxed-simd") {
179*12c85518Srobert       SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));
180*12c85518Srobert       continue;
181*12c85518Srobert     }
182e5dd7070Spatrick     if (Feature == "+nontrapping-fptoint") {
183e5dd7070Spatrick       HasNontrappingFPToInt = true;
184e5dd7070Spatrick       continue;
185e5dd7070Spatrick     }
186e5dd7070Spatrick     if (Feature == "-nontrapping-fptoint") {
187e5dd7070Spatrick       HasNontrappingFPToInt = false;
188e5dd7070Spatrick       continue;
189e5dd7070Spatrick     }
190e5dd7070Spatrick     if (Feature == "+sign-ext") {
191e5dd7070Spatrick       HasSignExt = true;
192e5dd7070Spatrick       continue;
193e5dd7070Spatrick     }
194e5dd7070Spatrick     if (Feature == "-sign-ext") {
195e5dd7070Spatrick       HasSignExt = false;
196e5dd7070Spatrick       continue;
197e5dd7070Spatrick     }
198e5dd7070Spatrick     if (Feature == "+exception-handling") {
199e5dd7070Spatrick       HasExceptionHandling = true;
200e5dd7070Spatrick       continue;
201e5dd7070Spatrick     }
202e5dd7070Spatrick     if (Feature == "-exception-handling") {
203e5dd7070Spatrick       HasExceptionHandling = false;
204e5dd7070Spatrick       continue;
205e5dd7070Spatrick     }
206e5dd7070Spatrick     if (Feature == "+bulk-memory") {
207e5dd7070Spatrick       HasBulkMemory = true;
208e5dd7070Spatrick       continue;
209e5dd7070Spatrick     }
210e5dd7070Spatrick     if (Feature == "-bulk-memory") {
211e5dd7070Spatrick       HasBulkMemory = false;
212e5dd7070Spatrick       continue;
213e5dd7070Spatrick     }
214e5dd7070Spatrick     if (Feature == "+atomics") {
215e5dd7070Spatrick       HasAtomics = true;
216e5dd7070Spatrick       continue;
217e5dd7070Spatrick     }
218e5dd7070Spatrick     if (Feature == "-atomics") {
219e5dd7070Spatrick       HasAtomics = false;
220e5dd7070Spatrick       continue;
221e5dd7070Spatrick     }
222e5dd7070Spatrick     if (Feature == "+mutable-globals") {
223e5dd7070Spatrick       HasMutableGlobals = true;
224e5dd7070Spatrick       continue;
225e5dd7070Spatrick     }
226e5dd7070Spatrick     if (Feature == "-mutable-globals") {
227e5dd7070Spatrick       HasMutableGlobals = false;
228e5dd7070Spatrick       continue;
229e5dd7070Spatrick     }
230e5dd7070Spatrick     if (Feature == "+multivalue") {
231e5dd7070Spatrick       HasMultivalue = true;
232e5dd7070Spatrick       continue;
233e5dd7070Spatrick     }
234e5dd7070Spatrick     if (Feature == "-multivalue") {
235e5dd7070Spatrick       HasMultivalue = false;
236e5dd7070Spatrick       continue;
237e5dd7070Spatrick     }
238e5dd7070Spatrick     if (Feature == "+tail-call") {
239e5dd7070Spatrick       HasTailCall = true;
240e5dd7070Spatrick       continue;
241e5dd7070Spatrick     }
242e5dd7070Spatrick     if (Feature == "-tail-call") {
243e5dd7070Spatrick       HasTailCall = false;
244e5dd7070Spatrick       continue;
245e5dd7070Spatrick     }
246ec727ea7Spatrick     if (Feature == "+reference-types") {
247ec727ea7Spatrick       HasReferenceTypes = true;
248ec727ea7Spatrick       continue;
249ec727ea7Spatrick     }
250ec727ea7Spatrick     if (Feature == "-reference-types") {
251ec727ea7Spatrick       HasReferenceTypes = false;
252ec727ea7Spatrick       continue;
253ec727ea7Spatrick     }
254*12c85518Srobert     if (Feature == "+extended-const") {
255*12c85518Srobert       HasExtendedConst = true;
256*12c85518Srobert       continue;
257*12c85518Srobert     }
258*12c85518Srobert     if (Feature == "-extended-const") {
259*12c85518Srobert       HasExtendedConst = false;
260*12c85518Srobert       continue;
261*12c85518Srobert     }
262e5dd7070Spatrick 
263e5dd7070Spatrick     Diags.Report(diag::err_opt_not_valid_with_opt)
264e5dd7070Spatrick         << Feature << "-target-feature";
265e5dd7070Spatrick     return false;
266e5dd7070Spatrick   }
267e5dd7070Spatrick   return true;
268e5dd7070Spatrick }
269e5dd7070Spatrick 
getTargetBuiltins() const270e5dd7070Spatrick ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
271*12c85518Srobert   return llvm::ArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -
272e5dd7070Spatrick                                          Builtin::FirstTSBuiltin);
273e5dd7070Spatrick }
274e5dd7070Spatrick 
adjust(DiagnosticsEngine & Diags,LangOptions & Opts)275a9ac8606Spatrick void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags,
276a9ac8606Spatrick                                    LangOptions &Opts) {
277*12c85518Srobert   TargetInfo::adjust(Diags, Opts);
278*12c85518Srobert   // Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
279*12c85518Srobert   // or __STDCPP_THREADS__ if we will eventually end up stripping atomics
280*12c85518Srobert   // because they are unsupported.
281*12c85518Srobert   if (!HasAtomics || !HasBulkMemory) {
282a9ac8606Spatrick     Opts.POSIXThreads = false;
283a9ac8606Spatrick     Opts.setThreadModel(LangOptions::ThreadModelKind::Single);
284*12c85518Srobert     Opts.ThreadsafeStatics = false;
285a9ac8606Spatrick   }
286a9ac8606Spatrick }
287a9ac8606Spatrick 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const288e5dd7070Spatrick void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
289e5dd7070Spatrick                                                MacroBuilder &Builder) const {
290e5dd7070Spatrick   WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
291e5dd7070Spatrick   defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
292e5dd7070Spatrick }
293e5dd7070Spatrick 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const294e5dd7070Spatrick void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
295e5dd7070Spatrick                                                MacroBuilder &Builder) const {
296e5dd7070Spatrick   WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
297e5dd7070Spatrick   defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
298e5dd7070Spatrick }
299