Clang Project

clang_source_code/lib/Basic/Targets/WebAssembly.cpp
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
20using namespace clang;
21using namespace clang::targets;
22
23const 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"
31};
32
33static constexpr llvm::StringLiteral ValidCPUNames[] = {
34    {"mvp"}, {"bleeding-edge"}, {"generic"}};
35
36bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
37  return llvm::StringSwitch<bool>(Feature)
38      .Case("simd128", SIMDLevel >= SIMD128)
39      .Case("unimplemented-simd128", SIMDLevel >= UnimplementedSIMD128)
40      .Case("nontrapping-fptoint", HasNontrappingFPToInt)
41      .Case("sign-ext", HasSignExt)
42      .Case("exception-handling", HasExceptionHandling)
43      .Case("bulk-memory", HasBulkMemory)
44      .Case("atomics", HasAtomics)
45      .Default(false);
46}
47
48bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
49  return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
50}
51
52void WebAssemblyTargetInfo::fillValidCPUList(
53    SmallVectorImpl<StringRef> &Values) const {
54  Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
55}
56
57void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
58                                             MacroBuilder &Builder) const {
59  defineCPUMacros(Builder, "wasm"/*Tuning=*/false);
60  if (SIMDLevel >= SIMD128)
61    Builder.defineMacro("__wasm_simd128__");
62  if (SIMDLevel >= UnimplementedSIMD128)
63    Builder.defineMacro("__wasm_unimplemented_simd128__");
64  if (HasNontrappingFPToInt)
65    Builder.defineMacro("__wasm_nontrapping_fptoint__");
66  if (HasSignExt)
67    Builder.defineMacro("__wasm_sign_ext__");
68  if (HasExceptionHandling)
69    Builder.defineMacro("__wasm_exception_handling__");
70  if (HasBulkMemory)
71    Builder.defineMacro("__wasm_bulk_memory__");
72  if (HasAtomics)
73    Builder.defineMacro("__wasm_atomics__");
74}
75
76void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
77                                         SIMDEnum Level) {
78  switch (Level) {
79  case UnimplementedSIMD128:
80    Features["unimplemented-simd128"] = true;
81    LLVM_FALLTHROUGH;
82  case SIMD128:
83    Features["simd128"] = true;
84    LLVM_FALLTHROUGH;
85  case NoSIMD:
86    break;
87  }
88}
89
90bool WebAssemblyTargetInfo::initFeatureMap(
91    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
92    const std::vector<std::string> &FeaturesVec) const {
93  if (CPU == "bleeding-edge") {
94    Features["nontrapping-fptoint"] = true;
95    Features["sign-ext"] = true;
96    Features["atomics"] = true;
97    setSIMDLevel(Features, SIMD128);
98  }
99  // Other targets do not consider user-configured features here, but while we
100  // are actively developing new features it is useful to let user-configured
101  // features control availability of builtins
102  setSIMDLevel(Features, SIMDLevel);
103  if (HasNontrappingFPToInt)
104    Features["nontrapping-fptoint"] = true;
105  if (HasSignExt)
106    Features["sign-ext"] = true;
107  if (HasExceptionHandling)
108    Features["exception-handling"] = true;
109  if (HasBulkMemory)
110    Features["bulk-memory"] = true;
111  if (HasAtomics)
112    Features["atomics"] = true;
113
114  return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
115}
116
117bool WebAssemblyTargetInfo::handleTargetFeatures(
118    std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
119  for (const auto &Feature : Features) {
120    if (Feature == "+simd128") {
121      SIMDLevel = std::max(SIMDLevel, SIMD128);
122      continue;
123    }
124    if (Feature == "-simd128") {
125      SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
126      continue;
127    }
128    if (Feature == "+unimplemented-simd128") {
129      SIMDLevel = std::max(SIMDLevel, SIMDEnum(UnimplementedSIMD128));
130      continue;
131    }
132    if (Feature == "-unimplemented-simd128") {
133      SIMDLevel = std::min(SIMDLevel, SIMDEnum(UnimplementedSIMD128 - 1));
134      continue;
135    }
136    if (Feature == "+nontrapping-fptoint") {
137      HasNontrappingFPToInt = true;
138      continue;
139    }
140    if (Feature == "-nontrapping-fptoint") {
141      HasNontrappingFPToInt = false;
142      continue;
143    }
144    if (Feature == "+sign-ext") {
145      HasSignExt = true;
146      continue;
147    }
148    if (Feature == "-sign-ext") {
149      HasSignExt = false;
150      continue;
151    }
152    if (Feature == "+exception-handling") {
153      HasExceptionHandling = true;
154      continue;
155    }
156    if (Feature == "-exception-handling") {
157      HasExceptionHandling = false;
158      continue;
159    }
160    if (Feature == "+bulk-memory") {
161      HasBulkMemory = true;
162      continue;
163    }
164    if (Feature == "-bulk-memory") {
165      HasBulkMemory = false;
166      continue;
167    }
168    if (Feature == "+atomics") {
169      HasAtomics = true;
170      continue;
171    }
172    if (Feature == "-atomics") {
173      HasAtomics = false;
174      continue;
175    }
176
177    Diags.Report(diag::err_opt_not_valid_with_opt)
178        << Feature << "-target-feature";
179    return false;
180  }
181  return true;
182}
183
184ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
185  return llvm::makeArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -
186                                             Builtin::FirstTSBuiltin);
187}
188
189void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
190                                               MacroBuilder &Builder) const {
191  WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
192  defineCPUMacros(Builder, "wasm32"/*Tuning=*/false);
193}
194
195void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
196                                               MacroBuilder &Builder) const {
197  WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
198  defineCPUMacros(Builder, "wasm64"/*Tuning=*/false);
199}
200