10b57cec5SDimitry Andric //=== WebAssembly.h - Declare WebAssembly target feature support *- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file declares WebAssembly TargetInfo objects. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H 140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 170b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h" 180b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 1906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace clang { 220b57cec5SDimitry Andric namespace targets { 230b57cec5SDimitry Andric 2406c3fb27SDimitry Andric static const unsigned WebAssemblyAddrSpaceMap[] = { 2506c3fb27SDimitry Andric 0, // Default 2606c3fb27SDimitry Andric 0, // opencl_global 2706c3fb27SDimitry Andric 0, // opencl_local 2806c3fb27SDimitry Andric 0, // opencl_constant 2906c3fb27SDimitry Andric 0, // opencl_private 3006c3fb27SDimitry Andric 0, // opencl_generic 3106c3fb27SDimitry Andric 0, // opencl_global_device 3206c3fb27SDimitry Andric 0, // opencl_global_host 3306c3fb27SDimitry Andric 0, // cuda_device 3406c3fb27SDimitry Andric 0, // cuda_constant 3506c3fb27SDimitry Andric 0, // cuda_shared 3606c3fb27SDimitry Andric 0, // sycl_global 3706c3fb27SDimitry Andric 0, // sycl_global_device 3806c3fb27SDimitry Andric 0, // sycl_global_host 3906c3fb27SDimitry Andric 0, // sycl_local 4006c3fb27SDimitry Andric 0, // sycl_private 4106c3fb27SDimitry Andric 0, // ptr32_sptr 4206c3fb27SDimitry Andric 0, // ptr32_uptr 4306c3fb27SDimitry Andric 0, // ptr64 4406c3fb27SDimitry Andric 0, // hlsl_groupshared 4506c3fb27SDimitry Andric 20, // wasm_funcref 4606c3fb27SDimitry Andric }; 4706c3fb27SDimitry Andric 480b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo { 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric enum SIMDEnum { 510b57cec5SDimitry Andric NoSIMD, 520b57cec5SDimitry Andric SIMD128, 53349cc55cSDimitry Andric RelaxedSIMD, 540b57cec5SDimitry Andric } SIMDLevel = NoSIMD; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric bool HasAtomics = false; 57*0fca6ea1SDimitry Andric bool HasBulkMemory = false; 58*0fca6ea1SDimitry Andric bool HasExceptionHandling = false; 5981ad6265SDimitry Andric bool HasExtendedConst = false; 60*0fca6ea1SDimitry Andric bool HasHalfPrecision = false; 615f757f3fSDimitry Andric bool HasMultiMemory = false; 62*0fca6ea1SDimitry Andric bool HasMultivalue = false; 63*0fca6ea1SDimitry Andric bool HasMutableGlobals = false; 64*0fca6ea1SDimitry Andric bool HasNontrappingFPToInt = false; 65*0fca6ea1SDimitry Andric bool HasReferenceTypes = false; 66*0fca6ea1SDimitry Andric bool HasSignExt = false; 67*0fca6ea1SDimitry Andric bool HasTailCall = false; 685ffd83dbSDimitry Andric 695ffd83dbSDimitry Andric std::string ABI; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric public: 720b57cec5SDimitry Andric explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &) 730b57cec5SDimitry Andric : TargetInfo(T) { 7406c3fb27SDimitry Andric AddrSpaceMap = &WebAssemblyAddrSpaceMap; 750b57cec5SDimitry Andric NoAsmVariants = true; 760b57cec5SDimitry Andric SuitableAlign = 128; 770b57cec5SDimitry Andric LargeArrayMinWidth = 128; 780b57cec5SDimitry Andric LargeArrayAlign = 128; 790b57cec5SDimitry Andric SigAtomicType = SignedLong; 800b57cec5SDimitry Andric LongDoubleWidth = LongDoubleAlign = 128; 810b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEquad(); 820b57cec5SDimitry Andric MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 830b57cec5SDimitry Andric // size_t being unsigned long for both wasm32 and wasm64 makes mangled names 840b57cec5SDimitry Andric // more consistent between the two. 850b57cec5SDimitry Andric SizeType = UnsignedLong; 860b57cec5SDimitry Andric PtrDiffType = SignedLong; 870b57cec5SDimitry Andric IntPtrType = SignedLong; 88*0fca6ea1SDimitry Andric HasUnalignedAccess = true; 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 915ffd83dbSDimitry Andric StringRef getABI() const override; 925ffd83dbSDimitry Andric bool setABI(const std::string &Name) override; 93*0fca6ea1SDimitry Andric bool useFP16ConversionIntrinsics() const override { 94*0fca6ea1SDimitry Andric return !HasHalfPrecision; 95*0fca6ea1SDimitry Andric } 965ffd83dbSDimitry Andric 970b57cec5SDimitry Andric protected: 980b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 990b57cec5SDimitry Andric MacroBuilder &Builder) const override; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric private: 10275b4d546SDimitry Andric static void setSIMDLevel(llvm::StringMap<bool> &Features, SIMDEnum Level, 10375b4d546SDimitry Andric bool Enabled); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric bool 1060b57cec5SDimitry Andric initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 1070b57cec5SDimitry Andric StringRef CPU, 1080b57cec5SDimitry Andric const std::vector<std::string> &FeaturesVec) const override; 1090b57cec5SDimitry Andric bool hasFeature(StringRef Feature) const final; 1100b57cec5SDimitry Andric 11175b4d546SDimitry Andric void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, 11275b4d546SDimitry Andric bool Enabled) const final; 11375b4d546SDimitry Andric 1140b57cec5SDimitry Andric bool handleTargetFeatures(std::vector<std::string> &Features, 1150b57cec5SDimitry Andric DiagnosticsEngine &Diags) final; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric bool isValidCPUName(StringRef Name) const final; 1180b57cec5SDimitry Andric void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const final; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric bool setCPU(const std::string &Name) final { return isValidCPUName(Name); } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric ArrayRef<Builtin::Info> getTargetBuiltins() const final; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric BuiltinVaListKind getBuiltinVaListKind() const final { 1250b57cec5SDimitry Andric return VoidPtrBuiltinVaList; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 128bdd1243dSDimitry Andric ArrayRef<const char *> getGCCRegNames() const final { return std::nullopt; } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final { 131bdd1243dSDimitry Andric return std::nullopt; 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric bool validateAsmConstraint(const char *&Name, 1350b57cec5SDimitry Andric TargetInfo::ConstraintInfo &Info) const final { 1360b57cec5SDimitry Andric return false; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 13906c3fb27SDimitry Andric std::string_view getClobbers() const final { return ""; } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric bool isCLZForZeroUndef() const final { return false; } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric bool hasInt128Type() const final { return true; } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final { 1460b57cec5SDimitry Andric // WebAssembly prefers long long for explicitly 64-bit integers. 1470b57cec5SDimitry Andric return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong) 1480b57cec5SDimitry Andric : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned); 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final { 1520b57cec5SDimitry Andric // WebAssembly uses long long for int_least64_t and int_fast64_t. 1530b57cec5SDimitry Andric return BitWidth == 64 1540b57cec5SDimitry Andric ? (IsSigned ? SignedLongLong : UnsignedLongLong) 1550b57cec5SDimitry Andric : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned); 1560b57cec5SDimitry Andric } 1575ffd83dbSDimitry Andric 1585ffd83dbSDimitry Andric CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 1595ffd83dbSDimitry Andric switch (CC) { 1605ffd83dbSDimitry Andric case CC_C: 1615ffd83dbSDimitry Andric case CC_Swift: 1625ffd83dbSDimitry Andric return CCCR_OK; 163fe6060f1SDimitry Andric case CC_SwiftAsync: 164fe6060f1SDimitry Andric return CCCR_Error; 1655ffd83dbSDimitry Andric default: 1665ffd83dbSDimitry Andric return CCCR_Warning; 1675ffd83dbSDimitry Andric } 1685ffd83dbSDimitry Andric } 1695ffd83dbSDimitry Andric 1700eae32dcSDimitry Andric bool hasBitIntType() const override { return true; } 1715ffd83dbSDimitry Andric 1725ffd83dbSDimitry Andric bool hasProtectedVisibility() const override { return false; } 173fe6060f1SDimitry Andric 174fe6060f1SDimitry Andric void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override; 1750b57cec5SDimitry Andric }; 1765ffd83dbSDimitry Andric 1770b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo 1780b57cec5SDimitry Andric : public WebAssemblyTargetInfo { 1790b57cec5SDimitry Andric public: 1800b57cec5SDimitry Andric explicit WebAssembly32TargetInfo(const llvm::Triple &T, 1810b57cec5SDimitry Andric const TargetOptions &Opts) 1820b57cec5SDimitry Andric : WebAssemblyTargetInfo(T, Opts) { 183fe6060f1SDimitry Andric if (T.isOSEmscripten()) 184349cc55cSDimitry Andric resetDataLayout("e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-" 185349cc55cSDimitry Andric "S128-ni:1:10:20"); 186fe6060f1SDimitry Andric else 187349cc55cSDimitry Andric resetDataLayout( 188349cc55cSDimitry Andric "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric protected: 1920b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 1930b57cec5SDimitry Andric MacroBuilder &Builder) const override; 1940b57cec5SDimitry Andric }; 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY WebAssembly64TargetInfo 1970b57cec5SDimitry Andric : public WebAssemblyTargetInfo { 1980b57cec5SDimitry Andric public: 1990b57cec5SDimitry Andric explicit WebAssembly64TargetInfo(const llvm::Triple &T, 2000b57cec5SDimitry Andric const TargetOptions &Opts) 2010b57cec5SDimitry Andric : WebAssemblyTargetInfo(T, Opts) { 2020b57cec5SDimitry Andric LongAlign = LongWidth = 64; 2030b57cec5SDimitry Andric PointerAlign = PointerWidth = 64; 2040b57cec5SDimitry Andric SizeType = UnsignedLong; 2050b57cec5SDimitry Andric PtrDiffType = SignedLong; 2060b57cec5SDimitry Andric IntPtrType = SignedLong; 207fe6060f1SDimitry Andric if (T.isOSEmscripten()) 208349cc55cSDimitry Andric resetDataLayout("e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-" 209349cc55cSDimitry Andric "S128-ni:1:10:20"); 210fe6060f1SDimitry Andric else 211349cc55cSDimitry Andric resetDataLayout( 212349cc55cSDimitry Andric "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric protected: 2160b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 2170b57cec5SDimitry Andric MacroBuilder &Builder) const override; 2180b57cec5SDimitry Andric }; 2190b57cec5SDimitry Andric } // namespace targets 2200b57cec5SDimitry Andric } // namespace clang 2210b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H 222