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