xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/WebAssembly.cpp (revision 75b4d546cd9d9f62a5a3466e6df5629262aef7b1)
10b57cec5SDimitry Andric //===--- WebAssembly.cpp - Implement WebAssembly target feature support ---===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements WebAssembly TargetInfo objects.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "WebAssembly.h"
140b57cec5SDimitry Andric #include "Targets.h"
150b57cec5SDimitry Andric #include "clang/Basic/Builtins.h"
160b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
170b57cec5SDimitry Andric #include "clang/Basic/TargetBuiltins.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace clang;
210b57cec5SDimitry Andric using namespace clang::targets;
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric const Builtin::Info WebAssemblyTargetInfo::BuiltinInfo[] = {
240b57cec5SDimitry Andric #define BUILTIN(ID, TYPE, ATTRS)                                               \
250b57cec5SDimitry Andric   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
260b57cec5SDimitry Andric #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
270b57cec5SDimitry Andric   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
280b57cec5SDimitry Andric #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
290b57cec5SDimitry Andric   {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
300b57cec5SDimitry Andric #include "clang/Basic/BuiltinsWebAssembly.def"
310b57cec5SDimitry Andric };
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric static constexpr llvm::StringLiteral ValidCPUNames[] = {
340b57cec5SDimitry Andric     {"mvp"}, {"bleeding-edge"}, {"generic"}};
350b57cec5SDimitry Andric 
365ffd83dbSDimitry Andric StringRef WebAssemblyTargetInfo::getABI() const { return ABI; }
375ffd83dbSDimitry Andric 
385ffd83dbSDimitry Andric bool WebAssemblyTargetInfo::setABI(const std::string &Name) {
395ffd83dbSDimitry Andric   if (Name != "mvp" && Name != "experimental-mv")
405ffd83dbSDimitry Andric     return false;
415ffd83dbSDimitry Andric 
425ffd83dbSDimitry Andric   ABI = Name;
435ffd83dbSDimitry Andric   return true;
445ffd83dbSDimitry Andric }
455ffd83dbSDimitry Andric 
460b57cec5SDimitry Andric bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
470b57cec5SDimitry Andric   return llvm::StringSwitch<bool>(Feature)
480b57cec5SDimitry Andric       .Case("simd128", SIMDLevel >= SIMD128)
490b57cec5SDimitry Andric       .Case("unimplemented-simd128", SIMDLevel >= UnimplementedSIMD128)
500b57cec5SDimitry Andric       .Case("nontrapping-fptoint", HasNontrappingFPToInt)
510b57cec5SDimitry Andric       .Case("sign-ext", HasSignExt)
520b57cec5SDimitry Andric       .Case("exception-handling", HasExceptionHandling)
530b57cec5SDimitry Andric       .Case("bulk-memory", HasBulkMemory)
540b57cec5SDimitry Andric       .Case("atomics", HasAtomics)
550b57cec5SDimitry Andric       .Case("mutable-globals", HasMutableGlobals)
560b57cec5SDimitry Andric       .Case("multivalue", HasMultivalue)
570b57cec5SDimitry Andric       .Case("tail-call", HasTailCall)
585ffd83dbSDimitry Andric       .Case("reference-types", HasReferenceTypes)
590b57cec5SDimitry Andric       .Default(false);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {
630b57cec5SDimitry Andric   return llvm::find(ValidCPUNames, Name) != std::end(ValidCPUNames);
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric void WebAssemblyTargetInfo::fillValidCPUList(
670b57cec5SDimitry Andric     SmallVectorImpl<StringRef> &Values) const {
680b57cec5SDimitry Andric   Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
720b57cec5SDimitry Andric                                              MacroBuilder &Builder) const {
730b57cec5SDimitry Andric   defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
740b57cec5SDimitry Andric   if (SIMDLevel >= SIMD128)
750b57cec5SDimitry Andric     Builder.defineMacro("__wasm_simd128__");
760b57cec5SDimitry Andric   if (SIMDLevel >= UnimplementedSIMD128)
770b57cec5SDimitry Andric     Builder.defineMacro("__wasm_unimplemented_simd128__");
780b57cec5SDimitry Andric   if (HasNontrappingFPToInt)
790b57cec5SDimitry Andric     Builder.defineMacro("__wasm_nontrapping_fptoint__");
800b57cec5SDimitry Andric   if (HasSignExt)
810b57cec5SDimitry Andric     Builder.defineMacro("__wasm_sign_ext__");
820b57cec5SDimitry Andric   if (HasExceptionHandling)
830b57cec5SDimitry Andric     Builder.defineMacro("__wasm_exception_handling__");
840b57cec5SDimitry Andric   if (HasBulkMemory)
850b57cec5SDimitry Andric     Builder.defineMacro("__wasm_bulk_memory__");
860b57cec5SDimitry Andric   if (HasAtomics)
870b57cec5SDimitry Andric     Builder.defineMacro("__wasm_atomics__");
880b57cec5SDimitry Andric   if (HasMutableGlobals)
890b57cec5SDimitry Andric     Builder.defineMacro("__wasm_mutable_globals__");
900b57cec5SDimitry Andric   if (HasMultivalue)
910b57cec5SDimitry Andric     Builder.defineMacro("__wasm_multivalue__");
920b57cec5SDimitry Andric   if (HasTailCall)
930b57cec5SDimitry Andric     Builder.defineMacro("__wasm_tail_call__");
945ffd83dbSDimitry Andric   if (HasReferenceTypes)
955ffd83dbSDimitry Andric     Builder.defineMacro("__wasm_reference_types__");
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,
99*75b4d546SDimitry Andric                                          SIMDEnum Level, bool Enabled) {
100*75b4d546SDimitry Andric   if (Enabled) {
1010b57cec5SDimitry Andric     switch (Level) {
1020b57cec5SDimitry Andric     case UnimplementedSIMD128:
1030b57cec5SDimitry Andric       Features["unimplemented-simd128"] = true;
1040b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
1050b57cec5SDimitry Andric     case SIMD128:
1060b57cec5SDimitry Andric       Features["simd128"] = true;
1070b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
1080b57cec5SDimitry Andric     case NoSIMD:
1090b57cec5SDimitry Andric       break;
1100b57cec5SDimitry Andric     }
111*75b4d546SDimitry Andric     return;
112*75b4d546SDimitry Andric   }
113*75b4d546SDimitry Andric 
114*75b4d546SDimitry Andric   switch (Level) {
115*75b4d546SDimitry Andric   case NoSIMD:
116*75b4d546SDimitry Andric   case SIMD128:
117*75b4d546SDimitry Andric     Features["simd128"] = false;
118*75b4d546SDimitry Andric     LLVM_FALLTHROUGH;
119*75b4d546SDimitry Andric   case UnimplementedSIMD128:
120*75b4d546SDimitry Andric     Features["unimplemented-simd128"] = false;
121*75b4d546SDimitry Andric     break;
122*75b4d546SDimitry Andric   }
123*75b4d546SDimitry Andric }
124*75b4d546SDimitry Andric 
125*75b4d546SDimitry Andric void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
126*75b4d546SDimitry Andric                                               StringRef Name,
127*75b4d546SDimitry Andric                                               bool Enabled) const {
128*75b4d546SDimitry Andric   if (Name == "simd128")
129*75b4d546SDimitry Andric     setSIMDLevel(Features, SIMD128, Enabled);
130*75b4d546SDimitry Andric   else if (Name == "unimplemented-simd128")
131*75b4d546SDimitry Andric     setSIMDLevel(Features, UnimplementedSIMD128, Enabled);
132*75b4d546SDimitry Andric   else
133*75b4d546SDimitry Andric     Features[Name] = Enabled;
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric bool WebAssemblyTargetInfo::initFeatureMap(
1370b57cec5SDimitry Andric     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
1380b57cec5SDimitry Andric     const std::vector<std::string> &FeaturesVec) const {
1390b57cec5SDimitry Andric   if (CPU == "bleeding-edge") {
1400b57cec5SDimitry Andric     Features["nontrapping-fptoint"] = true;
1410b57cec5SDimitry Andric     Features["sign-ext"] = true;
1425ffd83dbSDimitry Andric     Features["bulk-memory"] = true;
1430b57cec5SDimitry Andric     Features["atomics"] = true;
1440b57cec5SDimitry Andric     Features["mutable-globals"] = true;
1455ffd83dbSDimitry Andric     Features["tail-call"] = true;
146*75b4d546SDimitry Andric     setSIMDLevel(Features, SIMD128, true);
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric bool WebAssemblyTargetInfo::handleTargetFeatures(
1530b57cec5SDimitry Andric     std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
1540b57cec5SDimitry Andric   for (const auto &Feature : Features) {
1550b57cec5SDimitry Andric     if (Feature == "+simd128") {
1560b57cec5SDimitry Andric       SIMDLevel = std::max(SIMDLevel, SIMD128);
1570b57cec5SDimitry Andric       continue;
1580b57cec5SDimitry Andric     }
1590b57cec5SDimitry Andric     if (Feature == "-simd128") {
1600b57cec5SDimitry Andric       SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
1610b57cec5SDimitry Andric       continue;
1620b57cec5SDimitry Andric     }
1630b57cec5SDimitry Andric     if (Feature == "+unimplemented-simd128") {
1640b57cec5SDimitry Andric       SIMDLevel = std::max(SIMDLevel, SIMDEnum(UnimplementedSIMD128));
1650b57cec5SDimitry Andric       continue;
1660b57cec5SDimitry Andric     }
1670b57cec5SDimitry Andric     if (Feature == "-unimplemented-simd128") {
1680b57cec5SDimitry Andric       SIMDLevel = std::min(SIMDLevel, SIMDEnum(UnimplementedSIMD128 - 1));
1690b57cec5SDimitry Andric       continue;
1700b57cec5SDimitry Andric     }
1710b57cec5SDimitry Andric     if (Feature == "+nontrapping-fptoint") {
1720b57cec5SDimitry Andric       HasNontrappingFPToInt = true;
1730b57cec5SDimitry Andric       continue;
1740b57cec5SDimitry Andric     }
1750b57cec5SDimitry Andric     if (Feature == "-nontrapping-fptoint") {
1760b57cec5SDimitry Andric       HasNontrappingFPToInt = false;
1770b57cec5SDimitry Andric       continue;
1780b57cec5SDimitry Andric     }
1790b57cec5SDimitry Andric     if (Feature == "+sign-ext") {
1800b57cec5SDimitry Andric       HasSignExt = true;
1810b57cec5SDimitry Andric       continue;
1820b57cec5SDimitry Andric     }
1830b57cec5SDimitry Andric     if (Feature == "-sign-ext") {
1840b57cec5SDimitry Andric       HasSignExt = false;
1850b57cec5SDimitry Andric       continue;
1860b57cec5SDimitry Andric     }
1870b57cec5SDimitry Andric     if (Feature == "+exception-handling") {
1880b57cec5SDimitry Andric       HasExceptionHandling = true;
1890b57cec5SDimitry Andric       continue;
1900b57cec5SDimitry Andric     }
1910b57cec5SDimitry Andric     if (Feature == "-exception-handling") {
1920b57cec5SDimitry Andric       HasExceptionHandling = false;
1930b57cec5SDimitry Andric       continue;
1940b57cec5SDimitry Andric     }
1950b57cec5SDimitry Andric     if (Feature == "+bulk-memory") {
1960b57cec5SDimitry Andric       HasBulkMemory = true;
1970b57cec5SDimitry Andric       continue;
1980b57cec5SDimitry Andric     }
1990b57cec5SDimitry Andric     if (Feature == "-bulk-memory") {
2000b57cec5SDimitry Andric       HasBulkMemory = false;
2010b57cec5SDimitry Andric       continue;
2020b57cec5SDimitry Andric     }
2030b57cec5SDimitry Andric     if (Feature == "+atomics") {
2040b57cec5SDimitry Andric       HasAtomics = true;
2050b57cec5SDimitry Andric       continue;
2060b57cec5SDimitry Andric     }
2070b57cec5SDimitry Andric     if (Feature == "-atomics") {
2080b57cec5SDimitry Andric       HasAtomics = false;
2090b57cec5SDimitry Andric       continue;
2100b57cec5SDimitry Andric     }
2110b57cec5SDimitry Andric     if (Feature == "+mutable-globals") {
2120b57cec5SDimitry Andric       HasMutableGlobals = true;
2130b57cec5SDimitry Andric       continue;
2140b57cec5SDimitry Andric     }
2150b57cec5SDimitry Andric     if (Feature == "-mutable-globals") {
2160b57cec5SDimitry Andric       HasMutableGlobals = false;
2170b57cec5SDimitry Andric       continue;
2180b57cec5SDimitry Andric     }
2190b57cec5SDimitry Andric     if (Feature == "+multivalue") {
2200b57cec5SDimitry Andric       HasMultivalue = true;
2210b57cec5SDimitry Andric       continue;
2220b57cec5SDimitry Andric     }
2230b57cec5SDimitry Andric     if (Feature == "-multivalue") {
2240b57cec5SDimitry Andric       HasMultivalue = false;
2250b57cec5SDimitry Andric       continue;
2260b57cec5SDimitry Andric     }
2270b57cec5SDimitry Andric     if (Feature == "+tail-call") {
2280b57cec5SDimitry Andric       HasTailCall = true;
2290b57cec5SDimitry Andric       continue;
2300b57cec5SDimitry Andric     }
2310b57cec5SDimitry Andric     if (Feature == "-tail-call") {
2320b57cec5SDimitry Andric       HasTailCall = false;
2330b57cec5SDimitry Andric       continue;
2340b57cec5SDimitry Andric     }
2355ffd83dbSDimitry Andric     if (Feature == "+reference-types") {
2365ffd83dbSDimitry Andric       HasReferenceTypes = true;
2375ffd83dbSDimitry Andric       continue;
2385ffd83dbSDimitry Andric     }
2395ffd83dbSDimitry Andric     if (Feature == "-reference-types") {
2405ffd83dbSDimitry Andric       HasReferenceTypes = false;
2415ffd83dbSDimitry Andric       continue;
2425ffd83dbSDimitry Andric     }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric     Diags.Report(diag::err_opt_not_valid_with_opt)
2450b57cec5SDimitry Andric         << Feature << "-target-feature";
2460b57cec5SDimitry Andric     return false;
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric   return true;
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric ArrayRef<Builtin::Info> WebAssemblyTargetInfo::getTargetBuiltins() const {
2520b57cec5SDimitry Andric   return llvm::makeArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin -
2530b57cec5SDimitry Andric                                              Builtin::FirstTSBuiltin);
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,
2570b57cec5SDimitry Andric                                                MacroBuilder &Builder) const {
2580b57cec5SDimitry Andric   WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
2590b57cec5SDimitry Andric   defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,
2630b57cec5SDimitry Andric                                                MacroBuilder &Builder) const {
2640b57cec5SDimitry Andric   WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);
2650b57cec5SDimitry Andric   defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);
2660b57cec5SDimitry Andric }
267