Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Basic/Targets/WebAssembly.cpp
Line
Count
Source (jump to first uncovered line)
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
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
0
StringRef WebAssemblyTargetInfo::getABI() const { return ABI; }
37
38
0
bool WebAssemblyTargetInfo::setABI(const std::string &Name) {
39
0
  if (Name != "mvp" && Name != "experimental-mv")
40
0
    return false;
41
42
0
  ABI = Name;
43
0
  return true;
44
0
}
45
46
0
bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
47
0
  return llvm::StringSwitch<bool>(Feature)
48
0
      .Case("simd128", SIMDLevel >= SIMD128)
49
0
      .Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
50
0
      .Case("nontrapping-fptoint", HasNontrappingFPToInt)
51
0
      .Case("sign-ext", HasSignExt)
52
0
      .Case("exception-handling", HasExceptionHandling)
53
0
      .Case("bulk-memory", HasBulkMemory)
54
0
      .Case("atomics", HasAtomics)
55
0
      .Case("mutable-globals", HasMutableGlobals)
56
0
      .Case("multivalue", HasMultivalue)
57
0
      .Case("tail-call", HasTailCall)
58
0
      .Case("reference-types", HasReferenceTypes)
59
0
      .Case("extended-const", HasExtendedConst)
60
0
      .Case("multimemory", HasMultiMemory)
61
0
      .Default(false);
62
0
}
63
64
0
bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
65
0
  return llvm::is_contained(ValidCPUNames, Name);
66
0
}
67
68
void WebAssemblyTargetInfo::fillValidCPUList(
69
0
    SmallVectorImpl<StringRef> &Values) const {
70
0
  Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
71
0
}
72
73
void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
74
0
                                             MacroBuilder &Builder) const {
75
0
  defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
76
0
  if (SIMDLevel >= SIMD128)
77
0
    Builder.defineMacro("__wasm_simd128__");
78
0
  if (SIMDLevel >= RelaxedSIMD)
79
0
    Builder.defineMacro("__wasm_relaxed_simd__");
80
0
  if (HasNontrappingFPToInt)
81
0
    Builder.defineMacro("__wasm_nontrapping_fptoint__");
82
0
  if (HasSignExt)
83
0
    Builder.defineMacro("__wasm_sign_ext__");
84
0
  if (HasExceptionHandling)
85
0
    Builder.defineMacro("__wasm_exception_handling__");
86
0
  if (HasBulkMemory)
87
0
    Builder.defineMacro("__wasm_bulk_memory__");
88
0
  if (HasAtomics)
89
0
    Builder.defineMacro("__wasm_atomics__");
90
0
  if (HasMutableGlobals)
91
0
    Builder.defineMacro("__wasm_mutable_globals__");
92
0
  if (HasMultivalue)
93
0
    Builder.defineMacro("__wasm_multivalue__");
94
0
  if (HasTailCall)
95
0
    Builder.defineMacro("__wasm_tail_call__");
96
0
  if (HasReferenceTypes)
97
0
    Builder.defineMacro("__wasm_reference_types__");
98
0
  if (HasExtendedConst)
99
0
    Builder.defineMacro("__wasm_extended_const__");
100
0
  if (HasMultiMemory)
101
0
    Builder.defineMacro("__wasm_multimemory__");
102
103
0
  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
104
0
  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
105
0
  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
106
0
  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
107
0
}
108
109
void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
110
0
                                         SIMDEnum Level, bool Enabled) {
111
0
  if (Enabled) {
112
0
    switch (Level) {
113
0
    case RelaxedSIMD:
114
0
      Features["relaxed-simd"] = true;
115
0
      [[fallthrough]];
116
0
    case SIMD128:
117
0
      Features["simd128"] = true;
118
0
      [[fallthrough]];
119
0
    case NoSIMD:
120
0
      break;
121
0
    }
122
0
    return;
123
0
  }
124
125
0
  switch (Level) {
126
0
  case NoSIMD:
127
0
  case SIMD128:
128
0
    Features["simd128"] = false;
129
0
    [[fallthrough]];
130
0
  case RelaxedSIMD:
131
0
    Features["relaxed-simd"] = false;
132
0
    break;
133
0
  }
134
0
}
135
136
void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
137
                                              StringRef Name,
138
0
                                              bool Enabled) const {
139
0
  if (Name == "simd128")
140
0
    setSIMDLevel(Features, SIMD128, Enabled);
141
0
  else if (Name == "relaxed-simd")
142
0
    setSIMDLevel(Features, RelaxedSIMD, Enabled);
143
0
  else
144
0
    Features[Name] = Enabled;
145
0
}
146
147
bool WebAssemblyTargetInfo::initFeatureMap(
148
    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
149
0
    const std::vector<std::string> &FeaturesVec) const {
150
0
  if (CPU == "bleeding-edge") {
151
0
    Features["nontrapping-fptoint"] = true;
152
0
    Features["sign-ext"] = true;
153
0
    Features["bulk-memory"] = true;
154
0
    Features["atomics"] = true;
155
0
    Features["mutable-globals"] = true;
156
0
    Features["tail-call"] = true;
157
0
    Features["reference-types"] = true;
158
0
    Features["multimemory"] = true;
159
0
    setSIMDLevel(Features, SIMD128, true);
160
0
  } else if (CPU == "generic") {
161
0
    Features["sign-ext"] = true;
162
0
    Features["mutable-globals"] = true;
163
0
  }
164
165
0
  return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
166
0
}
167
168
bool WebAssemblyTargetInfo::handleTargetFeatures(
169
0
    std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
170
0
  for (const auto &Feature : Features) {
171
0
    if (Feature == "+simd128") {
172
0
      SIMDLevel = std::max(SIMDLevel, SIMD128);
173
0
      continue;
174
0
    }
175
0
    if (Feature == "-simd128") {
176
0
      SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
177
0
      continue;
178
0
    }
179
0
    if (Feature == "+relaxed-simd") {
180
0
      SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);
181
0
      continue;
182
0
    }
183
0
    if (Feature == "-relaxed-simd") {
184
0
      SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));
185
0
      continue;
186
0
    }
187
0
    if (Feature == "+nontrapping-fptoint") {
188
0
      HasNontrappingFPToInt = true;
189
0
      continue;
190
0
    }
191
0
    if (Feature == "-nontrapping-fptoint") {
192
0
      HasNontrappingFPToInt = false;
193
0
      continue;
194
0
    }
195
0
    if (Feature == "+sign-ext") {
196
0
      HasSignExt = true;
197
0
      continue;
198
0
    }
199
0
    if (Feature == "-sign-ext") {
200
0
      HasSignExt = false;
201
0
      continue;
202
0
    }
203
0
    if (Feature == "+exception-handling") {
204
0
      HasExceptionHandling = true;
205
0
      continue;
206
0
    }
207
0
    if (Feature == "-exception-handling") {
208
0
      HasExceptionHandling = false;
209
0
      continue;
210
0
    }
211
0
    if (Feature == "+bulk-memory") {
212
0
      HasBulkMemory = true;
213
0
      continue;
214
0
    }
215
0
    if (Feature == "-bulk-memory") {
216
0
      HasBulkMemory = false;
217
0
      continue;
218
0
    }
219
0
    if (Feature == "+atomics") {
220
0
      HasAtomics = true;
221
0
      continue;
222
0
    }
223
0
    if (Feature == "-atomics") {
224
0
      HasAtomics = false;
225
0
      continue;
226
0
    }
227
0
    if (Feature == "+mutable-globals") {
228
0
      HasMutableGlobals = true;
229
0
      continue;
230
0
    }
231
0
    if (Feature == "-mutable-globals") {
232
0
      HasMutableGlobals = false;
233
0
      continue;
234
0
    }
235
0
    if (Feature == "+multivalue") {
236
0
      HasMultivalue = true;
237
0
      continue;
238
0
    }
239
0
    if (Feature == "-multivalue") {
240
0
      HasMultivalue = false;
241
0
      continue;
242
0
    }
243
0
    if (Feature == "+tail-call") {
244
0
      HasTailCall = true;
245
0
      continue;
246
0
    }
247
0
    if (Feature == "-tail-call") {
248
0
      HasTailCall = false;
249
0
      continue;
250
0
    }
251
0
    if (Feature == "+reference-types") {
252
0
      HasReferenceTypes = true;
253
0
      continue;
254
0
    }
255
0
    if (Feature == "-reference-types") {
256
0
      HasReferenceTypes = false;
257
0
      continue;
258
0
    }
259
0
    if (Feature == "+extended-const") {
260
0
      HasExtendedConst = true;
261
0
      continue;
262
0
    }
263
0
    if (Feature == "-extended-const") {
264
0
      HasExtendedConst = false;
265
0
      continue;
266
0
    }
267
0
    if (Feature == "+multimemory") {
268
0
      HasMultiMemory = true;
269
0
      continue;
270
0
    }
271
0
    if (Feature == "-multimemory") {
272
0
      HasMultiMemory = false;
273
0
      continue;
274
0
    }
275
276
0
    Diags.Report(diag::err_opt_not_valid_with_opt)
277
0
        << Feature << "-target-feature";
278
0
    return false;
279
0
  }
280
0
  return true;
281
0
}
282
283
0
ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
284
0
  return llvm::ArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -
285
0
                                         Builtin::FirstTSBuiltin);
286
0
}
287
288
void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags,
289
0
                                   LangOptions &Opts) {
290
0
  TargetInfo::adjust(Diags, Opts);
291
  // Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT
292
  // or __STDCPP_THREADS__ if we will eventually end up stripping atomics
293
  // because they are unsupported.
294
0
  if (!HasAtomics || !HasBulkMemory) {
295
0
    Opts.POSIXThreads = false;
296
0
    Opts.setThreadModel(LangOptions::ThreadModelKind::Single);
297
0
    Opts.ThreadsafeStatics = false;
298
0
  }
299
0
}
300
301
void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
302
0
                                               MacroBuilder &Builder) const {
303
0
  WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
304
0
  defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
305
0
}
306
307
void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
308
0
                                               MacroBuilder &Builder) const {
309
0
  WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
310
0
  defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
311
0
}