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