clang  19.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"
15 #include "clang/Basic/Builtins.h"
16 #include "clang/Basic/Diagnostic.h"
18 #include "llvm/ADT/StringSwitch.h"
19 
20 using namespace clang;
21 using namespace clang::targets;
22 
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"
31 };
32 
33 static constexpr llvm::StringLiteral ValidCPUNames[] = {
34  {"mvp"}, {"bleeding-edge"}, {"generic"}};
35 
36 StringRef WebAssemblyTargetInfo::getABI() const { return ABI; }
37 
38 bool WebAssemblyTargetInfo::setABI(const std::string &Name) {
39  if (Name != "mvp" && Name != "experimental-mv")
40  return false;
41 
42  ABI = Name;
43  return true;
44 }
45 
46 bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
47  return llvm::StringSwitch<bool>(Feature)
48  .Case("atomics", HasAtomics)
49  .Case("bulk-memory", HasBulkMemory)
50  .Case("exception-handling", HasExceptionHandling)
51  .Case("extended-const", HasExtendedConst)
52  .Case("half-precision", HasHalfPrecision)
53  .Case("multimemory", HasMultiMemory)
54  .Case("multivalue", HasMultivalue)
55  .Case("mutable-globals", HasMutableGlobals)
56  .Case("nontrapping-fptoint", HasNontrappingFPToInt)
57  .Case("reference-types", HasReferenceTypes)
58  .Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
59  .Case("sign-ext", HasSignExt)
60  .Case("simd128", SIMDLevel >= SIMD128)
61  .Case("tail-call", HasTailCall)
62  .Default(false);
63 }
64 
65 bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
66  return llvm::is_contained(ValidCPUNames, Name);
67 }
68 
69 void WebAssemblyTargetInfo::fillValidCPUList(
70  SmallVectorImpl<StringRef> &Values) const {
71  Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
72 }
73 
75  MacroBuilder &Builder) const {
76  defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
77  if (HasAtomics)
78  Builder.defineMacro("__wasm_atomics__");
79  if (HasBulkMemory)
80  Builder.defineMacro("__wasm_bulk_memory__");
81  if (HasExceptionHandling)
82  Builder.defineMacro("__wasm_exception_handling__");
83  if (HasExtendedConst)
84  Builder.defineMacro("__wasm_extended_const__");
85  if (HasMultiMemory)
86  Builder.defineMacro("__wasm_multimemory__");
87  if (HasHalfPrecision)
88  Builder.defineMacro("__wasm_half_precision__");
89  if (HasMultivalue)
90  Builder.defineMacro("__wasm_multivalue__");
91  if (HasMutableGlobals)
92  Builder.defineMacro("__wasm_mutable_globals__");
93  if (HasNontrappingFPToInt)
94  Builder.defineMacro("__wasm_nontrapping_fptoint__");
95  if (HasReferenceTypes)
96  Builder.defineMacro("__wasm_reference_types__");
97  if (SIMDLevel >= RelaxedSIMD)
98  Builder.defineMacro("__wasm_relaxed_simd__");
99  if (HasSignExt)
100  Builder.defineMacro("__wasm_sign_ext__");
101  if (SIMDLevel >= SIMD128)
102  Builder.defineMacro("__wasm_simd128__");
103  if (HasTailCall)
104  Builder.defineMacro("__wasm_tail_call__");
105 
106  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
107  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
108  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
109  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
110 }
111 
112 void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
113  SIMDEnum Level, bool Enabled) {
114  if (Enabled) {
115  switch (Level) {
116  case RelaxedSIMD:
117  Features["relaxed-simd"] = true;
118  [[fallthrough]];
119  case SIMD128:
120  Features["simd128"] = true;
121  [[fallthrough]];
122  case NoSIMD:
123  break;
124  }
125  return;
126  }
127 
128  switch (Level) {
129  case NoSIMD:
130  case SIMD128:
131  Features["simd128"] = false;
132  [[fallthrough]];
133  case RelaxedSIMD:
134  Features["relaxed-simd"] = false;
135  break;
136  }
137 }
138 
139 void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
140  StringRef Name,
141  bool Enabled) const {
142  if (Name == "simd128")
143  setSIMDLevel(Features, SIMD128, Enabled);
144  else if (Name == "relaxed-simd")
145  setSIMDLevel(Features, RelaxedSIMD, Enabled);
146  else
147  Features[Name] = Enabled;
148 }
149 
150 bool WebAssemblyTargetInfo::initFeatureMap(
151  llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
152  const std::vector<std::string> &FeaturesVec) const {
153  auto addGenericFeatures = [&]() {
154  Features["multivalue"] = true;
155  Features["mutable-globals"] = true;
156  Features["sign-ext"] = true;
157  };
158  auto addBleedingEdgeFeatures = [&]() {
159  addGenericFeatures();
160  Features["atomics"] = true;
161  Features["bulk-memory"] = true;
162  Features["exception-handling"] = true;
163  Features["extended-const"] = true;
164  Features["half-precision"] = true;
165  Features["multimemory"] = true;
166  Features["nontrapping-fptoint"] = true;
167  Features["reference-types"] = true;
168  Features["tail-call"] = true;
169  setSIMDLevel(Features, RelaxedSIMD, true);
170  };
171  if (CPU == "generic") {
172  addGenericFeatures();
173  } else if (CPU == "bleeding-edge") {
174  addBleedingEdgeFeatures();
175  }
176 
177  return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
178 }
179 
180 bool WebAssemblyTargetInfo::handleTargetFeatures(
181  std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
182  for (const auto &Feature : Features) {
183  if (Feature == "+atomics") {
184  HasAtomics = true;
185  continue;
186  }
187  if (Feature == "-atomics") {
188  HasAtomics = false;
189  continue;
190  }
191  if (Feature == "+bulk-memory") {
192  HasBulkMemory = true;
193  continue;
194  }
195  if (Feature == "-bulk-memory") {
196  HasBulkMemory = false;
197  continue;
198  }
199  if (Feature == "+exception-handling") {
200  HasExceptionHandling = true;
201  continue;
202  }
203  if (Feature == "-exception-handling") {
204  HasExceptionHandling = false;
205  continue;
206  }
207  if (Feature == "+extended-const") {
208  HasExtendedConst = true;
209  continue;
210  }
211  if (Feature == "-extended-const") {
212  HasExtendedConst = false;
213  continue;
214  }
215  if (Feature == "+half-precision") {
216  SIMDLevel = std::max(SIMDLevel, SIMD128);
217  HasHalfPrecision = true;
218  continue;
219  }
220  if (Feature == "-half-precision") {
221  HasHalfPrecision = false;
222  continue;
223  }
224  if (Feature == "+multimemory") {
225  HasMultiMemory = true;
226  continue;
227  }
228  if (Feature == "-multimemory") {
229  HasMultiMemory = false;
230  continue;
231  }
232  if (Feature == "+multivalue") {
233  HasMultivalue = true;
234  continue;
235  }
236  if (Feature == "-multivalue") {
237  HasMultivalue = false;
238  continue;
239  }
240  if (Feature == "+mutable-globals") {
241  HasMutableGlobals = true;
242  continue;
243  }
244  if (Feature == "-mutable-globals") {
245  HasMutableGlobals = false;
246  continue;
247  }
248  if (Feature == "+nontrapping-fptoint") {
249  HasNontrappingFPToInt = true;
250  continue;
251  }
252  if (Feature == "-nontrapping-fptoint") {
253  HasNontrappingFPToInt = false;
254  continue;
255  }
256  if (Feature == "+reference-types") {
257  HasReferenceTypes = true;
258  continue;
259  }
260  if (Feature == "-reference-types") {
261  HasReferenceTypes = false;
262  continue;
263  }
264  if (Feature == "+relaxed-simd") {
265  SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);
266  continue;
267  }
268  if (Feature == "-relaxed-simd") {
269  SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));
270  continue;
271  }
272  if (Feature == "+sign-ext") {
273  HasSignExt = true;
274  continue;
275  }
276  if (Feature == "-sign-ext") {
277  HasSignExt = false;
278  continue;
279  }
280  if (Feature == "+simd128") {
281  SIMDLevel = std::max(SIMDLevel, SIMD128);
282  continue;
283  }
284  if (Feature == "-simd128") {
285  SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
286  continue;
287  }
288  if (Feature == "+tail-call") {
289  HasTailCall = true;
290  continue;
291  }
292  if (Feature == "-tail-call") {
293  HasTailCall = false;
294  continue;
295  }
296 
297  Diags.Report(diag::err_opt_not_valid_with_opt)
298  << Feature << "-target-feature";
299  return false;
300  }
301  return true;
302 }
303 
304 ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
307 }
308 
309 void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags,
310  LangOptions &Opts) {
311  TargetInfo::adjust(Diags, Opts);
312  // Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
313  // or __STDCPP_THREADS__ if we will eventually end up stripping atomics
314  // because they are unsupported.
315  if (!HasAtomics || !HasBulkMemory) {
316  Opts.POSIXThreads = false;
317  Opts.setThreadModel(LangOptions::ThreadModelKind::Single);
318  Opts.ThreadsafeStatics = false;
319  }
320 }
321 
323  MacroBuilder &Builder) const {
325  defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
326 }
327 
329  MacroBuilder &Builder) const {
331  defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
332 }
Defines the Diagnostic-related interfaces.
static constexpr Builtin::Info BuiltinInfo[]
Definition: WebAssembly.cpp:23
static constexpr llvm::StringLiteral ValidCPUNames[]
Definition: WebAssembly.cpp:33
Defines enum values for all the target-independent builtin functions.
Enumerates target-specific builtins in their own namespaces within namespace clang.
__DEVICE__ int min(int __a, int __b)
__DEVICE__ int max(int __a, int __b)
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:193
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1553
@ Single
Single Threaded Environment.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:482
virtual void adjust(DiagnosticsEngine &Diags, LangOptions &Opts)
Set forced language options.
Definition: TargetInfo.cpp:392
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 ...
Definition: TargetInfo.cpp:566
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 -----------------------—===//
Definition: WebAssembly.cpp:74
StringRef getABI() const override
Get the ABI currently in use.
Definition: WebAssembly.cpp:36
bool setABI(const std::string &Name) override
Use the specified ABI.
Definition: WebAssembly.cpp:38
void defineCPUMacros(MacroBuilder &Builder, StringRef CPUName, bool Tuning)
Definition: Targets.cpp:76
The JSON file list parser is used to communicate input to InstallAPI.