1 //=== WebAssembly.h - Declare WebAssembly target feature support *- C++ -*-===// 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 declares WebAssembly TargetInfo objects. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H 14 #define LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H 15 16 #include "clang/Basic/TargetInfo.h" 17 #include "clang/Basic/TargetOptions.h" 18 #include "llvm/Support/Compiler.h" 19 #include "llvm/TargetParser/Triple.h" 20 21 namespace clang { 22 namespace targets { 23 24 static const unsigned WebAssemblyAddrSpaceMap[] = { 25 0, // Default 26 0, // opencl_global 27 0, // opencl_local 28 0, // opencl_constant 29 0, // opencl_private 30 0, // opencl_generic 31 0, // opencl_global_device 32 0, // opencl_global_host 33 0, // cuda_device 34 0, // cuda_constant 35 0, // cuda_shared 36 0, // sycl_global 37 0, // sycl_global_device 38 0, // sycl_global_host 39 0, // sycl_local 40 0, // sycl_private 41 0, // ptr32_sptr 42 0, // ptr32_uptr 43 0, // ptr64 44 0, // hlsl_groupshared 45 20, // wasm_funcref 46 }; 47 48 class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo { 49 50 enum SIMDEnum { 51 NoSIMD, 52 SIMD128, 53 RelaxedSIMD, 54 } SIMDLevel = NoSIMD; 55 56 bool HasAtomics = false; 57 bool HasBulkMemory = false; 58 bool HasExceptionHandling = false; 59 bool HasExtendedConst = false; 60 bool HasHalfPrecision = false; 61 bool HasMultiMemory = false; 62 bool HasMultivalue = false; 63 bool HasMutableGlobals = false; 64 bool HasNontrappingFPToInt = false; 65 bool HasReferenceTypes = false; 66 bool HasSignExt = false; 67 bool HasTailCall = false; 68 69 std::string ABI; 70 71 public: WebAssemblyTargetInfo(const llvm::Triple & T,const TargetOptions &)72 explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &) 73 : TargetInfo(T) { 74 AddrSpaceMap = &WebAssemblyAddrSpaceMap; 75 NoAsmVariants = true; 76 SuitableAlign = 128; 77 LargeArrayMinWidth = 128; 78 LargeArrayAlign = 128; 79 SigAtomicType = SignedLong; 80 LongDoubleWidth = LongDoubleAlign = 128; 81 LongDoubleFormat = &llvm::APFloat::IEEEquad(); 82 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 83 // size_t being unsigned long for both wasm32 and wasm64 makes mangled names 84 // more consistent between the two. 85 SizeType = UnsignedLong; 86 PtrDiffType = SignedLong; 87 IntPtrType = SignedLong; 88 HasUnalignedAccess = true; 89 } 90 91 StringRef getABI() const override; 92 bool setABI(const std::string &Name) override; useFP16ConversionIntrinsics()93 bool useFP16ConversionIntrinsics() const override { 94 return !HasHalfPrecision; 95 } 96 97 protected: 98 void getTargetDefines(const LangOptions &Opts, 99 MacroBuilder &Builder) const override; 100 101 private: 102 static void setSIMDLevel(llvm::StringMap<bool> &Features, SIMDEnum Level, 103 bool Enabled); 104 105 bool 106 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 107 StringRef CPU, 108 const std::vector<std::string> &FeaturesVec) const override; 109 bool hasFeature(StringRef Feature) const final; 110 111 void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, 112 bool Enabled) const final; 113 114 bool handleTargetFeatures(std::vector<std::string> &Features, 115 DiagnosticsEngine &Diags) final; 116 117 bool isValidCPUName(StringRef Name) const final; 118 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const final; 119 setCPU(const std::string & Name)120 bool setCPU(const std::string &Name) final { return isValidCPUName(Name); } 121 122 ArrayRef<Builtin::Info> getTargetBuiltins() const final; 123 getBuiltinVaListKind()124 BuiltinVaListKind getBuiltinVaListKind() const final { 125 return VoidPtrBuiltinVaList; 126 } 127 getGCCRegNames()128 ArrayRef<const char *> getGCCRegNames() const final { return std::nullopt; } 129 getGCCRegAliases()130 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final { 131 return std::nullopt; 132 } 133 validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info)134 bool validateAsmConstraint(const char *&Name, 135 TargetInfo::ConstraintInfo &Info) const final { 136 return false; 137 } 138 getClobbers()139 std::string_view getClobbers() const final { return ""; } 140 isCLZForZeroUndef()141 bool isCLZForZeroUndef() const final { return false; } 142 hasInt128Type()143 bool hasInt128Type() const final { return true; } 144 getIntTypeByWidth(unsigned BitWidth,bool IsSigned)145 IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final { 146 // WebAssembly prefers long long for explicitly 64-bit integers. 147 return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong) 148 : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned); 149 } 150 getLeastIntTypeByWidth(unsigned BitWidth,bool IsSigned)151 IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final { 152 // WebAssembly uses long long for int_least64_t and int_fast64_t. 153 return BitWidth == 64 154 ? (IsSigned ? SignedLongLong : UnsignedLongLong) 155 : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned); 156 } 157 checkCallingConvention(CallingConv CC)158 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 159 switch (CC) { 160 case CC_C: 161 case CC_Swift: 162 return CCCR_OK; 163 case CC_SwiftAsync: 164 return CCCR_Error; 165 default: 166 return CCCR_Warning; 167 } 168 } 169 hasBitIntType()170 bool hasBitIntType() const override { return true; } 171 hasProtectedVisibility()172 bool hasProtectedVisibility() const override { return false; } 173 174 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override; 175 }; 176 177 class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo 178 : public WebAssemblyTargetInfo { 179 public: WebAssembly32TargetInfo(const llvm::Triple & T,const TargetOptions & Opts)180 explicit WebAssembly32TargetInfo(const llvm::Triple &T, 181 const TargetOptions &Opts) 182 : WebAssemblyTargetInfo(T, Opts) { 183 if (T.isOSEmscripten()) 184 resetDataLayout("e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-" 185 "S128-ni:1:10:20"); 186 else 187 resetDataLayout( 188 "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"); 189 } 190 191 protected: 192 void getTargetDefines(const LangOptions &Opts, 193 MacroBuilder &Builder) const override; 194 }; 195 196 class LLVM_LIBRARY_VISIBILITY WebAssembly64TargetInfo 197 : public WebAssemblyTargetInfo { 198 public: WebAssembly64TargetInfo(const llvm::Triple & T,const TargetOptions & Opts)199 explicit WebAssembly64TargetInfo(const llvm::Triple &T, 200 const TargetOptions &Opts) 201 : WebAssemblyTargetInfo(T, Opts) { 202 LongAlign = LongWidth = 64; 203 PointerAlign = PointerWidth = 64; 204 SizeType = UnsignedLong; 205 PtrDiffType = SignedLong; 206 IntPtrType = SignedLong; 207 if (T.isOSEmscripten()) 208 resetDataLayout("e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-" 209 "S128-ni:1:10:20"); 210 else 211 resetDataLayout( 212 "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"); 213 } 214 215 protected: 216 void getTargetDefines(const LangOptions &Opts, 217 MacroBuilder &Builder) const override; 218 }; 219 } // namespace targets 220 } // namespace clang 221 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H 222