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