Path: blob/main/contrib/llvm-project/clang/lib/Basic/Targets/WebAssembly.cpp
213799 views
//===--- WebAssembly.cpp - Implement WebAssembly target feature support ---===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements WebAssembly TargetInfo objects.9//10//===----------------------------------------------------------------------===//1112#include "WebAssembly.h"13#include "Targets.h"14#include "clang/Basic/Builtins.h"15#include "clang/Basic/Diagnostic.h"16#include "clang/Basic/TargetBuiltins.h"17#include "llvm/ADT/StringSwitch.h"1819using namespace clang;20using namespace clang::targets;2122static constexpr int NumBuiltins =23clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin;2425static constexpr llvm::StringTable BuiltinStrings =26CLANG_BUILTIN_STR_TABLE_START27#define BUILTIN CLANG_BUILTIN_STR_TABLE28#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE29#include "clang/Basic/BuiltinsWebAssembly.def"30;3132static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({33#define BUILTIN CLANG_BUILTIN_ENTRY34#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY35#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY36#include "clang/Basic/BuiltinsWebAssembly.def"37});3839static constexpr llvm::StringLiteral ValidCPUNames[] = {40{"mvp"}, {"bleeding-edge"}, {"generic"}, {"lime1"}};4142StringRef WebAssemblyTargetInfo::getABI() const { return ABI; }4344bool WebAssemblyTargetInfo::setABI(const std::string &Name) {45if (Name != "mvp" && Name != "experimental-mv")46return false;4748ABI = Name;49return true;50}5152bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {53return llvm::StringSwitch<bool>(Feature)54.Case("atomics", HasAtomics)55.Case("bulk-memory", HasBulkMemory)56.Case("bulk-memory-opt", HasBulkMemoryOpt)57.Case("call-indirect-overlong", HasCallIndirectOverlong)58.Case("exception-handling", HasExceptionHandling)59.Case("extended-const", HasExtendedConst)60.Case("fp16", HasFP16)61.Case("multimemory", HasMultiMemory)62.Case("multivalue", HasMultivalue)63.Case("mutable-globals", HasMutableGlobals)64.Case("nontrapping-fptoint", HasNontrappingFPToInt)65.Case("reference-types", HasReferenceTypes)66.Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)67.Case("sign-ext", HasSignExt)68.Case("simd128", SIMDLevel >= SIMD128)69.Case("tail-call", HasTailCall)70.Case("wide-arithmetic", HasWideArithmetic)71.Default(false);72}7374bool WebAssemblyTargetInfo::isValidCPUName(StringRef Name) const {75return llvm::is_contained(ValidCPUNames, Name);76}7778void WebAssemblyTargetInfo::fillValidCPUList(79SmallVectorImpl<StringRef> &Values) const {80Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));81}8283void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,84MacroBuilder &Builder) const {85defineCPUMacros(Builder, "wasm", /*Tuning=*/false);86if (HasAtomics)87Builder.defineMacro("__wasm_atomics__");88if (HasBulkMemory)89Builder.defineMacro("__wasm_bulk_memory__");90if (HasBulkMemoryOpt)91Builder.defineMacro("__wasm_bulk_memory_opt__");92if (HasExceptionHandling)93Builder.defineMacro("__wasm_exception_handling__");94if (HasExtendedConst)95Builder.defineMacro("__wasm_extended_const__");96if (HasMultiMemory)97Builder.defineMacro("__wasm_multimemory__");98if (HasFP16)99Builder.defineMacro("__wasm_fp16__");100if (HasMultivalue)101Builder.defineMacro("__wasm_multivalue__");102if (HasMutableGlobals)103Builder.defineMacro("__wasm_mutable_globals__");104if (HasNontrappingFPToInt)105Builder.defineMacro("__wasm_nontrapping_fptoint__");106if (HasReferenceTypes)107Builder.defineMacro("__wasm_reference_types__");108if (SIMDLevel >= RelaxedSIMD)109Builder.defineMacro("__wasm_relaxed_simd__");110if (HasSignExt)111Builder.defineMacro("__wasm_sign_ext__");112if (SIMDLevel >= SIMD128)113Builder.defineMacro("__wasm_simd128__");114if (HasTailCall)115Builder.defineMacro("__wasm_tail_call__");116if (HasWideArithmetic)117Builder.defineMacro("__wasm_wide_arithmetic__");118119Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");120Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");121Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");122Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");123}124125void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap<bool> &Features,126SIMDEnum Level, bool Enabled) {127if (Enabled) {128switch (Level) {129case RelaxedSIMD:130Features["relaxed-simd"] = true;131[[fallthrough]];132case SIMD128:133Features["simd128"] = true;134[[fallthrough]];135case NoSIMD:136break;137}138return;139}140141switch (Level) {142case NoSIMD:143case SIMD128:144Features["simd128"] = false;145[[fallthrough]];146case RelaxedSIMD:147Features["relaxed-simd"] = false;148break;149}150}151152void WebAssemblyTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,153StringRef Name,154bool Enabled) const {155if (Name == "simd128")156setSIMDLevel(Features, SIMD128, Enabled);157else if (Name == "relaxed-simd")158setSIMDLevel(Features, RelaxedSIMD, Enabled);159else160Features[Name] = Enabled;161}162163bool WebAssemblyTargetInfo::initFeatureMap(164llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,165const std::vector<std::string> &FeaturesVec) const {166auto addGenericFeatures = [&]() {167Features["bulk-memory"] = true;168Features["bulk-memory-opt"] = true;169Features["call-indirect-overlong"] = true;170Features["multivalue"] = true;171Features["mutable-globals"] = true;172Features["nontrapping-fptoint"] = true;173Features["reference-types"] = true;174Features["sign-ext"] = true;175};176auto addLime1Features = [&]() {177// Lime1:178// <https://github.com/WebAssembly/tool-conventions/blob/main/Lime.md#lime1>179Features["bulk-memory-opt"] = true;180Features["call-indirect-overlong"] = true;181Features["extended-const"] = true;182Features["multivalue"] = true;183Features["mutable-globals"] = true;184Features["nontrapping-fptoint"] = true;185Features["sign-ext"] = true;186};187auto addBleedingEdgeFeatures = [&]() {188addGenericFeatures();189Features["atomics"] = true;190Features["exception-handling"] = true;191Features["extended-const"] = true;192Features["fp16"] = true;193Features["multimemory"] = true;194Features["tail-call"] = true;195Features["wide-arithmetic"] = true;196setSIMDLevel(Features, RelaxedSIMD, true);197};198if (CPU == "generic") {199addGenericFeatures();200} else if (CPU == "lime1") {201addLime1Features();202} else if (CPU == "bleeding-edge") {203addBleedingEdgeFeatures();204}205206return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);207}208209bool WebAssemblyTargetInfo::handleTargetFeatures(210std::vector<std::string> &Features, DiagnosticsEngine &Diags) {211for (const auto &Feature : Features) {212if (Feature == "+atomics") {213HasAtomics = true;214continue;215}216if (Feature == "-atomics") {217HasAtomics = false;218continue;219}220if (Feature == "+bulk-memory") {221HasBulkMemory = true;222continue;223}224if (Feature == "-bulk-memory") {225HasBulkMemory = false;226continue;227}228if (Feature == "+bulk-memory-opt") {229HasBulkMemoryOpt = true;230continue;231}232if (Feature == "-bulk-memory-opt") {233HasBulkMemoryOpt = false;234continue;235}236if (Feature == "+call-indirect-overlong") {237HasCallIndirectOverlong = true;238continue;239}240if (Feature == "-call-indirect-overlong") {241HasCallIndirectOverlong = false;242continue;243}244if (Feature == "+exception-handling") {245HasExceptionHandling = true;246continue;247}248if (Feature == "-exception-handling") {249HasExceptionHandling = false;250continue;251}252if (Feature == "+extended-const") {253HasExtendedConst = true;254continue;255}256if (Feature == "-extended-const") {257HasExtendedConst = false;258continue;259}260if (Feature == "+fp16") {261SIMDLevel = std::max(SIMDLevel, SIMD128);262HasFP16 = true;263continue;264}265if (Feature == "-fp16") {266HasFP16 = false;267continue;268}269if (Feature == "+multimemory") {270HasMultiMemory = true;271continue;272}273if (Feature == "-multimemory") {274HasMultiMemory = false;275continue;276}277if (Feature == "+multivalue") {278HasMultivalue = true;279continue;280}281if (Feature == "-multivalue") {282HasMultivalue = false;283continue;284}285if (Feature == "+mutable-globals") {286HasMutableGlobals = true;287continue;288}289if (Feature == "-mutable-globals") {290HasMutableGlobals = false;291continue;292}293if (Feature == "+nontrapping-fptoint") {294HasNontrappingFPToInt = true;295continue;296}297if (Feature == "-nontrapping-fptoint") {298HasNontrappingFPToInt = false;299continue;300}301if (Feature == "+reference-types") {302HasReferenceTypes = true;303continue;304}305if (Feature == "-reference-types") {306HasReferenceTypes = false;307continue;308}309if (Feature == "+relaxed-simd") {310SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);311continue;312}313if (Feature == "-relaxed-simd") {314SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));315continue;316}317if (Feature == "+sign-ext") {318HasSignExt = true;319continue;320}321if (Feature == "-sign-ext") {322HasSignExt = false;323continue;324}325if (Feature == "+simd128") {326SIMDLevel = std::max(SIMDLevel, SIMD128);327continue;328}329if (Feature == "-simd128") {330SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));331continue;332}333if (Feature == "+tail-call") {334HasTailCall = true;335continue;336}337if (Feature == "-tail-call") {338HasTailCall = false;339continue;340}341if (Feature == "+wide-arithmetic") {342HasWideArithmetic = true;343continue;344}345if (Feature == "-wide-arithmetic") {346HasWideArithmetic = false;347continue;348}349350Diags.Report(diag::err_opt_not_valid_with_opt)351<< Feature << "-target-feature";352return false;353}354355// bulk-memory-opt is a subset of bulk-memory.356if (HasBulkMemory) {357HasBulkMemoryOpt = true;358}359360// The reference-types feature included the change to `call_indirect`361// encodings to support overlong immediates.362if (HasReferenceTypes) {363HasCallIndirectOverlong = true;364}365366return true;367}368369llvm::SmallVector<Builtin::InfosShard>370WebAssemblyTargetInfo::getTargetBuiltins() const {371return {{&BuiltinStrings, BuiltinInfos}};372}373374void WebAssemblyTargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts,375const TargetInfo *Aux) {376TargetInfo::adjust(Diags, Opts, Aux);377// Turn off POSIXThreads and ThreadModel so that we don't predefine _REENTRANT378// or __STDCPP_THREADS__ if we will eventually end up stripping atomics379// because they are unsupported.380if (!HasAtomics || !HasBulkMemory) {381Opts.POSIXThreads = false;382Opts.setThreadModel(LangOptions::ThreadModelKind::Single);383Opts.ThreadsafeStatics = false;384}385}386387void WebAssembly32TargetInfo::getTargetDefines(const LangOptions &Opts,388MacroBuilder &Builder) const {389WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);390defineCPUMacros(Builder, "wasm32", /*Tuning=*/false);391}392393void WebAssembly64TargetInfo::getTargetDefines(const LangOptions &Opts,394MacroBuilder &Builder) const {395WebAssemblyTargetInfo::getTargetDefines(Opts, Builder);396defineCPUMacros(Builder, "wasm64", /*Tuning=*/false);397}398399400