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