xref: /openbsd-src/gnu/llvm/clang/lib/Basic/Targets/WebAssembly.cpp (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
1*e5dd7070Spatrick //===--- WebAssembly.cpp - Implement WebAssembly target feature support ---===//
2*e5dd7070Spatrick //
3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e5dd7070Spatrick //
7*e5dd7070Spatrick //===----------------------------------------------------------------------===//
8*e5dd7070Spatrick //
9*e5dd7070Spatrick // This file implements WebAssembly TargetInfo objects.
10*e5dd7070Spatrick //
11*e5dd7070Spatrick //===----------------------------------------------------------------------===//
12*e5dd7070Spatrick 
13*e5dd7070Spatrick #include "WebAssembly.h"
14*e5dd7070Spatrick #include "Targets.h"
15*e5dd7070Spatrick #include "clang/Basic/Builtins.h"
16*e5dd7070Spatrick #include "clang/Basic/Diagnostic.h"
17*e5dd7070Spatrick #include "clang/Basic/TargetBuiltins.h"
18*e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
19*e5dd7070Spatrick 
20*e5dd7070Spatrick using namespace clang;
21*e5dd7070Spatrick using namespace clang::targets;
22*e5dd7070Spatrick 
23*e5dd7070Spatrick const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = {
24*e5dd7070Spatrick #define BUILTIN(ID, TYPE, ATTRS)                                               \
25*e5dd7070Spatrick   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
26*e5dd7070Spatrick #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
27*e5dd7070Spatrick   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
28*e5dd7070Spatrick #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
29*e5dd7070Spatrick   {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
30*e5dd7070Spatrick #include "clang/Basic/BuiltinsWebAssembly.def"
31*e5dd7070Spatrick };
32*e5dd7070Spatrick 
33*e5dd7070Spatrick static constexpr llvm::StringLiteral ValidCPUNames[] = {
34*e5dd7070Spatrick     {"mvp"}, {"bleeding-edge"}, {"generic"}};
35*e5dd7070Spatrick 
36*e5dd7070Spatrick bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
37*e5dd7070Spatrick   return llvm::StringSwitch<bool>(Feature)
38*e5dd7070Spatrick       .Case("simd128", SIMDLevel >= SIMD128)
39*e5dd7070Spatrick       .Case("unimplemented-simd128", SIMDLevel >= UnimplementedSIMD128)
40*e5dd7070Spatrick       .Case("nontrapping-fptoint", HasNontrappingFPToInt)
41*e5dd7070Spatrick       .Case("sign-ext", HasSignExt)
42*e5dd7070Spatrick       .Case("exception-handling", HasExceptionHandling)
43*e5dd7070Spatrick       .Case("bulk-memory", HasBulkMemory)
44*e5dd7070Spatrick       .Case("atomics", HasAtomics)
45*e5dd7070Spatrick       .Case("mutable-globals", HasMutableGlobals)
46*e5dd7070Spatrick       .Case("multivalue", HasMultivalue)
47*e5dd7070Spatrick       .Case("tail-call", HasTailCall)
48*e5dd7070Spatrick       .Default(false);
49*e5dd7070Spatrick }
50*e5dd7070Spatrick 
51*e5dd7070Spatrick bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
52*e5dd7070Spatrick   return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
53*e5dd7070Spatrick }
54*e5dd7070Spatrick 
55*e5dd7070Spatrick void WebAssemblyTargetInfo::fillValidCPUList(
56*e5dd7070Spatrick     SmallVectorImpl<StringRef> &Values) const {
57*e5dd7070Spatrick   Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
58*e5dd7070Spatrick }
59*e5dd7070Spatrick 
60*e5dd7070Spatrick void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
61*e5dd7070Spatrick                                              MacroBuilder &Builder) const {
62*e5dd7070Spatrick   defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
63*e5dd7070Spatrick   if (SIMDLevel >= SIMD128)
64*e5dd7070Spatrick     Builder.defineMacro("__wasm_simd128__");
65*e5dd7070Spatrick   if (SIMDLevel >= UnimplementedSIMD128)
66*e5dd7070Spatrick     Builder.defineMacro("__wasm_unimplemented_simd128__");
67*e5dd7070Spatrick   if (HasNontrappingFPToInt)
68*e5dd7070Spatrick     Builder.defineMacro("__wasm_nontrapping_fptoint__");
69*e5dd7070Spatrick   if (HasSignExt)
70*e5dd7070Spatrick     Builder.defineMacro("__wasm_sign_ext__");
71*e5dd7070Spatrick   if (HasExceptionHandling)
72*e5dd7070Spatrick     Builder.defineMacro("__wasm_exception_handling__");
73*e5dd7070Spatrick   if (HasBulkMemory)
74*e5dd7070Spatrick     Builder.defineMacro("__wasm_bulk_memory__");
75*e5dd7070Spatrick   if (HasAtomics)
76*e5dd7070Spatrick     Builder.defineMacro("__wasm_atomics__");
77*e5dd7070Spatrick   if (HasMutableGlobals)
78*e5dd7070Spatrick     Builder.defineMacro("__wasm_mutable_globals__");
79*e5dd7070Spatrick   if (HasMultivalue)
80*e5dd7070Spatrick     Builder.defineMacro("__wasm_multivalue__");
81*e5dd7070Spatrick   if (HasTailCall)
82*e5dd7070Spatrick     Builder.defineMacro("__wasm_tail_call__");
83*e5dd7070Spatrick }
84*e5dd7070Spatrick 
85*e5dd7070Spatrick void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
86*e5dd7070Spatrick                                          SIMDEnum Level) {
87*e5dd7070Spatrick   switch (Level) {
88*e5dd7070Spatrick   case UnimplementedSIMD128:
89*e5dd7070Spatrick     Features["unimplemented-simd128"] = true;
90*e5dd7070Spatrick     LLVM_FALLTHROUGH;
91*e5dd7070Spatrick   case SIMD128:
92*e5dd7070Spatrick     Features["simd128"] = true;
93*e5dd7070Spatrick     LLVM_FALLTHROUGH;
94*e5dd7070Spatrick   case NoSIMD:
95*e5dd7070Spatrick     break;
96*e5dd7070Spatrick   }
97*e5dd7070Spatrick }
98*e5dd7070Spatrick 
99*e5dd7070Spatrick bool WebAssemblyTargetInfo::initFeatureMap(
100*e5dd7070Spatrick     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
101*e5dd7070Spatrick     const std::vector<std::string> &FeaturesVec) const {
102*e5dd7070Spatrick   if (CPU == "bleeding-edge") {
103*e5dd7070Spatrick     Features["nontrapping-fptoint"] = true;
104*e5dd7070Spatrick     Features["sign-ext"] = true;
105*e5dd7070Spatrick     Features["atomics"] = true;
106*e5dd7070Spatrick     Features["mutable-globals"] = true;
107*e5dd7070Spatrick     setSIMDLevel(Features, SIMD128);
108*e5dd7070Spatrick   }
109*e5dd7070Spatrick   // Other targets do not consider user-configured features here, but while we
110*e5dd7070Spatrick   // are actively developing new features it is useful to let user-configured
111*e5dd7070Spatrick   // features control availability of builtins
112*e5dd7070Spatrick   setSIMDLevel(Features, SIMDLevel);
113*e5dd7070Spatrick   if (HasNontrappingFPToInt)
114*e5dd7070Spatrick     Features["nontrapping-fptoint"] = true;
115*e5dd7070Spatrick   if (HasSignExt)
116*e5dd7070Spatrick     Features["sign-ext"] = true;
117*e5dd7070Spatrick   if (HasExceptionHandling)
118*e5dd7070Spatrick     Features["exception-handling"] = true;
119*e5dd7070Spatrick   if (HasBulkMemory)
120*e5dd7070Spatrick     Features["bulk-memory"] = true;
121*e5dd7070Spatrick   if (HasAtomics)
122*e5dd7070Spatrick     Features["atomics"] = true;
123*e5dd7070Spatrick   if (HasMutableGlobals)
124*e5dd7070Spatrick     Features["mutable-globals"] = true;
125*e5dd7070Spatrick   if (HasMultivalue)
126*e5dd7070Spatrick     Features["multivalue"] = true;
127*e5dd7070Spatrick   if (HasTailCall)
128*e5dd7070Spatrick     Features["tail-call"] = true;
129*e5dd7070Spatrick 
130*e5dd7070Spatrick   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
131*e5dd7070Spatrick }
132*e5dd7070Spatrick 
133*e5dd7070Spatrick bool WebAssemblyTargetInfo::handleTargetFeatures(
134*e5dd7070Spatrick     std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
135*e5dd7070Spatrick   for (const auto &Feature : Features) {
136*e5dd7070Spatrick     if (Feature == "+simd128") {
137*e5dd7070Spatrick       SIMDLevel = std::max(SIMDLevel, SIMD128);
138*e5dd7070Spatrick       continue;
139*e5dd7070Spatrick     }
140*e5dd7070Spatrick     if (Feature == "-simd128") {
141*e5dd7070Spatrick       SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
142*e5dd7070Spatrick       continue;
143*e5dd7070Spatrick     }
144*e5dd7070Spatrick     if (Feature == "+unimplemented-simd128") {
145*e5dd7070Spatrick       SIMDLevel = std::max(SIMDLevel, SIMDEnum(UnimplementedSIMD128));
146*e5dd7070Spatrick       continue;
147*e5dd7070Spatrick     }
148*e5dd7070Spatrick     if (Feature == "-unimplemented-simd128") {
149*e5dd7070Spatrick       SIMDLevel = std::min(SIMDLevel, SIMDEnum(UnimplementedSIMD128 - 1));
150*e5dd7070Spatrick       continue;
151*e5dd7070Spatrick     }
152*e5dd7070Spatrick     if (Feature == "+nontrapping-fptoint") {
153*e5dd7070Spatrick       HasNontrappingFPToInt = true;
154*e5dd7070Spatrick       continue;
155*e5dd7070Spatrick     }
156*e5dd7070Spatrick     if (Feature == "-nontrapping-fptoint") {
157*e5dd7070Spatrick       HasNontrappingFPToInt = false;
158*e5dd7070Spatrick       continue;
159*e5dd7070Spatrick     }
160*e5dd7070Spatrick     if (Feature == "+sign-ext") {
161*e5dd7070Spatrick       HasSignExt = true;
162*e5dd7070Spatrick       continue;
163*e5dd7070Spatrick     }
164*e5dd7070Spatrick     if (Feature == "-sign-ext") {
165*e5dd7070Spatrick       HasSignExt = false;
166*e5dd7070Spatrick       continue;
167*e5dd7070Spatrick     }
168*e5dd7070Spatrick     if (Feature == "+exception-handling") {
169*e5dd7070Spatrick       HasExceptionHandling = true;
170*e5dd7070Spatrick       continue;
171*e5dd7070Spatrick     }
172*e5dd7070Spatrick     if (Feature == "-exception-handling") {
173*e5dd7070Spatrick       HasExceptionHandling = false;
174*e5dd7070Spatrick       continue;
175*e5dd7070Spatrick     }
176*e5dd7070Spatrick     if (Feature == "+bulk-memory") {
177*e5dd7070Spatrick       HasBulkMemory = true;
178*e5dd7070Spatrick       continue;
179*e5dd7070Spatrick     }
180*e5dd7070Spatrick     if (Feature == "-bulk-memory") {
181*e5dd7070Spatrick       HasBulkMemory = false;
182*e5dd7070Spatrick       continue;
183*e5dd7070Spatrick     }
184*e5dd7070Spatrick     if (Feature == "+atomics") {
185*e5dd7070Spatrick       HasAtomics = true;
186*e5dd7070Spatrick       continue;
187*e5dd7070Spatrick     }
188*e5dd7070Spatrick     if (Feature == "-atomics") {
189*e5dd7070Spatrick       HasAtomics = false;
190*e5dd7070Spatrick       continue;
191*e5dd7070Spatrick     }
192*e5dd7070Spatrick     if (Feature == "+mutable-globals") {
193*e5dd7070Spatrick       HasMutableGlobals = true;
194*e5dd7070Spatrick       continue;
195*e5dd7070Spatrick     }
196*e5dd7070Spatrick     if (Feature == "-mutable-globals") {
197*e5dd7070Spatrick       HasMutableGlobals = false;
198*e5dd7070Spatrick       continue;
199*e5dd7070Spatrick     }
200*e5dd7070Spatrick     if (Feature == "+multivalue") {
201*e5dd7070Spatrick       HasMultivalue = true;
202*e5dd7070Spatrick       continue;
203*e5dd7070Spatrick     }
204*e5dd7070Spatrick     if (Feature == "-multivalue") {
205*e5dd7070Spatrick       HasMultivalue = false;
206*e5dd7070Spatrick       continue;
207*e5dd7070Spatrick     }
208*e5dd7070Spatrick     if (Feature == "+tail-call") {
209*e5dd7070Spatrick       HasTailCall = true;
210*e5dd7070Spatrick       continue;
211*e5dd7070Spatrick     }
212*e5dd7070Spatrick     if (Feature == "-tail-call") {
213*e5dd7070Spatrick       HasTailCall = false;
214*e5dd7070Spatrick       continue;
215*e5dd7070Spatrick     }
216*e5dd7070Spatrick 
217*e5dd7070Spatrick     Diags.Report(diag::err_opt_not_valid_with_opt)
218*e5dd7070Spatrick         << Feature << "-target-feature";
219*e5dd7070Spatrick     return false;
220*e5dd7070Spatrick   }
221*e5dd7070Spatrick   return true;
222*e5dd7070Spatrick }
223*e5dd7070Spatrick 
224*e5dd7070Spatrick ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
225*e5dd7070Spatrick   return llvm::makeArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -
226*e5dd7070Spatrick                                              Builtin::FirstTSBuiltin);
227*e5dd7070Spatrick }
228*e5dd7070Spatrick 
229*e5dd7070Spatrick void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
230*e5dd7070Spatrick                                                MacroBuilder &Builder) const {
231*e5dd7070Spatrick   WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
232*e5dd7070Spatrick   defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
233*e5dd7070Spatrick }
234*e5dd7070Spatrick 
235*e5dd7070Spatrick void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
236*e5dd7070Spatrick                                                MacroBuilder &Builder) const {
237*e5dd7070Spatrick   WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
238*e5dd7070Spatrick   defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
239*e5dd7070Spatrick }
240