brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.2 KiB · 5bbb7af Raw
419 lines · cpp
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-exception6//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 20using namespace clang;21using namespace clang::targets;22 23static constexpr int NumBuiltins =24    clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin;25 26static constexpr llvm::StringTable BuiltinStrings =27    CLANG_BUILTIN_STR_TABLE_START28#define BUILTIN CLANG_BUILTIN_STR_TABLE29#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE30#include "clang/Basic/BuiltinsWebAssembly.def"31    ;32 33static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({34#define BUILTIN CLANG_BUILTIN_ENTRY35#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY36#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY37#include "clang/Basic/BuiltinsWebAssembly.def"38});39 40static constexpr llvm::StringLiteral ValidCPUNames[] = {41    {"mvp"}, {"bleeding-edge"}, {"generic"}, {"lime1"}};42 43StringRef WebAssemblyTargetInfo::getABI() const { return ABI; }44 45bool WebAssemblyTargetInfo::setABI(const std::string &Name) {46  if (Name != "mvp" && Name != "experimental-mv")47    return false;48 49  ABI = Name;50  return true;51}52 53bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {54  return llvm::StringSwitch<bool>(Feature)55      .Case("atomics", HasAtomics)56      .Case("bulk-memory", HasBulkMemory)57      .Case("bulk-memory-opt", HasBulkMemoryOpt)58      .Case("call-indirect-overlong", HasCallIndirectOverlong)59      .Case("exception-handling", HasExceptionHandling)60      .Case("extended-const", HasExtendedConst)61      .Case("fp16", HasFP16)62      .Case("gc", HasGC)63      .Case("multimemory", HasMultiMemory)64      .Case("multivalue", HasMultivalue)65      .Case("mutable-globals", HasMutableGlobals)66      .Case("nontrapping-fptoint", HasNontrappingFPToInt)67      .Case("reference-types", HasReferenceTypes)68      .Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)69      .Case("sign-ext", HasSignExt)70      .Case("simd128", SIMDLevel >= SIMD128)71      .Case("tail-call", HasTailCall)72      .Case("wide-arithmetic", HasWideArithmetic)73      .Default(false);74}75 76bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {77  return llvm::is_contained(ValidCPUNames, Name);78}79 80void WebAssemblyTargetInfo::fillValidCPUList(81    SmallVectorImpl<StringRef> &Values) const {82  Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));83}84 85void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,86                                             MacroBuilder &Builder) const {87  defineCPUMacros(Builder, "wasm", /*Tuning=*/false);88  if (HasAtomics)89    Builder.defineMacro("__wasm_atomics__");90  if (HasBulkMemory)91    Builder.defineMacro("__wasm_bulk_memory__");92  if (HasBulkMemoryOpt)93    Builder.defineMacro("__wasm_bulk_memory_opt__");94  if (HasExceptionHandling)95    Builder.defineMacro("__wasm_exception_handling__");96  if (HasExtendedConst)97    Builder.defineMacro("__wasm_extended_const__");98  if (HasMultiMemory)99    Builder.defineMacro("__wasm_multimemory__");100  if (HasFP16)101    Builder.defineMacro("__wasm_fp16__");102  if (HasGC)103    Builder.defineMacro("__wasm_gc__");104  if (HasMultivalue)105    Builder.defineMacro("__wasm_multivalue__");106  if (HasMutableGlobals)107    Builder.defineMacro("__wasm_mutable_globals__");108  if (HasNontrappingFPToInt)109    Builder.defineMacro("__wasm_nontrapping_fptoint__");110  if (HasReferenceTypes)111    Builder.defineMacro("__wasm_reference_types__");112  if (SIMDLevel >= RelaxedSIMD)113    Builder.defineMacro("__wasm_relaxed_simd__");114  if (HasSignExt)115    Builder.defineMacro("__wasm_sign_ext__");116  if (SIMDLevel >= SIMD128)117    Builder.defineMacro("__wasm_simd128__");118  if (HasTailCall)119    Builder.defineMacro("__wasm_tail_call__");120  if (HasWideArithmetic)121    Builder.defineMacro("__wasm_wide_arithmetic__");122 123  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");124  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");125  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");126  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");127}128 129void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,130                                         SIMDEnum Level, bool Enabled) {131  if (Enabled) {132    switch (Level) {133    case RelaxedSIMD:134      Features["relaxed-simd"] = true;135      [[fallthrough]];136    case SIMD128:137      Features["simd128"] = true;138      [[fallthrough]];139    case NoSIMD:140      break;141    }142    return;143  }144 145  switch (Level) {146  case NoSIMD:147  case SIMD128:148    Features["simd128"] = false;149    [[fallthrough]];150  case RelaxedSIMD:151    Features["relaxed-simd"] = false;152    break;153  }154}155 156void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,157                                              StringRef Name,158                                              bool Enabled) const {159  if (Name == "simd128")160    setSIMDLevel(Features, SIMD128, Enabled);161  else if (Name == "relaxed-simd")162    setSIMDLevel(Features, RelaxedSIMD, Enabled);163  else164    Features[Name] = Enabled;165}166 167bool WebAssemblyTargetInfo::initFeatureMap(168    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,169    const std::vector<std::string> &FeaturesVec) const {170  auto addGenericFeatures = [&]() {171    Features["bulk-memory"] = true;172    Features["bulk-memory-opt"] = true;173    Features["call-indirect-overlong"] = true;174    Features["multivalue"] = true;175    Features["mutable-globals"] = true;176    Features["nontrapping-fptoint"] = true;177    Features["reference-types"] = true;178    Features["sign-ext"] = true;179  };180  auto addLime1Features = [&]() {181    // Lime1:182    // <https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#lime1>183    Features["bulk-memory-opt"] = true;184    Features["call-indirect-overlong"] = true;185    Features["extended-const"] = true;186    Features["multivalue"] = true;187    Features["mutable-globals"] = true;188    Features["nontrapping-fptoint"] = true;189    Features["sign-ext"] = true;190  };191  auto addBleedingEdgeFeatures = [&]() {192    addGenericFeatures();193    Features["atomics"] = true;194    Features["exception-handling"] = true;195    Features["extended-const"] = true;196    Features["fp16"] = true;197    Features["gc"] = true;198    Features["multimemory"] = true;199    Features["tail-call"] = true;200    Features["wide-arithmetic"] = true;201    setSIMDLevel(Features, RelaxedSIMD, true);202  };203  if (CPU == "generic") {204    addGenericFeatures();205  } else if (CPU == "lime1") {206    addLime1Features();207  } else if (CPU == "bleeding-edge") {208    addBleedingEdgeFeatures();209  }210 211  return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);212}213 214bool WebAssemblyTargetInfo::handleTargetFeatures(215    std::vector<std::string> &Features, DiagnosticsEngine &Diags) {216  HasMustTail = false;217  for (const auto &Feature : Features) {218    if (Feature == "+atomics") {219      HasAtomics = true;220      continue;221    }222    if (Feature == "-atomics") {223      HasAtomics = false;224      continue;225    }226    if (Feature == "+bulk-memory") {227      HasBulkMemory = true;228      continue;229    }230    if (Feature == "-bulk-memory") {231      HasBulkMemory = false;232      continue;233    }234    if (Feature == "+bulk-memory-opt") {235      HasBulkMemoryOpt = true;236      continue;237    }238    if (Feature == "-bulk-memory-opt") {239      HasBulkMemoryOpt = false;240      continue;241    }242    if (Feature == "+call-indirect-overlong") {243      HasCallIndirectOverlong = true;244      continue;245    }246    if (Feature == "-call-indirect-overlong") {247      HasCallIndirectOverlong = false;248      continue;249    }250    if (Feature == "+exception-handling") {251      HasExceptionHandling = true;252      continue;253    }254    if (Feature == "-exception-handling") {255      HasExceptionHandling = false;256      continue;257    }258    if (Feature == "+extended-const") {259      HasExtendedConst = true;260      continue;261    }262    if (Feature == "-extended-const") {263      HasExtendedConst = false;264      continue;265    }266    if (Feature == "+fp16") {267      SIMDLevel = std::max(SIMDLevel, SIMD128);268      HasFP16 = true;269      continue;270    }271    if (Feature == "-fp16") {272      HasFP16 = false;273      continue;274    }275    if (Feature == "+gc") {276      HasGC = true;277      continue;278    }279    if (Feature == "-gc") {280      HasGC = false;281      continue;282    }283    if (Feature == "+multimemory") {284      HasMultiMemory = true;285      continue;286    }287    if (Feature == "-multimemory") {288      HasMultiMemory = false;289      continue;290    }291    if (Feature == "+multivalue") {292      HasMultivalue = true;293      continue;294    }295    if (Feature == "-multivalue") {296      HasMultivalue = false;297      continue;298    }299    if (Feature == "+mutable-globals") {300      HasMutableGlobals = true;301      continue;302    }303    if (Feature == "-mutable-globals") {304      HasMutableGlobals = false;305      continue;306    }307    if (Feature == "+nontrapping-fptoint") {308      HasNontrappingFPToInt = true;309      continue;310    }311    if (Feature == "-nontrapping-fptoint") {312      HasNontrappingFPToInt = false;313      continue;314    }315    if (Feature == "+reference-types") {316      HasReferenceTypes = true;317      continue;318    }319    if (Feature == "-reference-types") {320      HasReferenceTypes = false;321      continue;322    }323    if (Feature == "+relaxed-simd") {324      SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);325      continue;326    }327    if (Feature == "-relaxed-simd") {328      SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));329      continue;330    }331    if (Feature == "+sign-ext") {332      HasSignExt = true;333      continue;334    }335    if (Feature == "-sign-ext") {336      HasSignExt = false;337      continue;338    }339    if (Feature == "+simd128") {340      SIMDLevel = std::max(SIMDLevel, SIMD128);341      continue;342    }343    if (Feature == "-simd128") {344      SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));345      continue;346    }347    if (Feature == "+tail-call") {348      HasTailCall = true;349      HasMustTail = true;350      continue;351    }352    if (Feature == "-tail-call") {353      HasTailCall = false;354      HasMustTail = false;355      continue;356    }357    if (Feature == "+wide-arithmetic") {358      HasWideArithmetic = true;359      continue;360    }361    if (Feature == "-wide-arithmetic") {362      HasWideArithmetic = false;363      continue;364    }365 366    Diags.Report(diag::err_opt_not_valid_with_opt)367        << Feature << "-target-feature";368    return false;369  }370 371  // gc implies reference-types372  if (HasGC) {373    HasReferenceTypes = true;374  }375 376  // bulk-memory-opt is a subset of bulk-memory.377  if (HasBulkMemory) {378    HasBulkMemoryOpt = true;379  }380 381  // The reference-types feature included the change to `call_indirect`382  // encodings to support overlong immediates.383  if (HasReferenceTypes) {384    HasCallIndirectOverlong = true;385  }386 387  return true;388}389 390llvm::SmallVector<Builtin::InfosShard>391WebAssemblyTargetInfo::getTargetBuiltins() const {392  return {{&BuiltinStrings, BuiltinInfos}};393}394 395void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts,396                                   const TargetInfo *Aux) {397  TargetInfo::adjust(Diags, Opts, Aux);398  // Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT399  // or __STDCPP_THREADS__ if we will eventually end up stripping atomics400  // because they are unsupported.401  if (!HasAtomics || !HasBulkMemory) {402    Opts.POSIXThreads = false;403    Opts.setThreadModel(LangOptions::ThreadModelKind::Single);404    Opts.ThreadsafeStatics = false;405  }406}407 408void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,409                                               MacroBuilder &Builder) const {410  WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);411  defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);412}413 414void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,415                                               MacroBuilder &Builder) const {416  WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);417  defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);418}419