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
21namespace clang {
22namespace targets {
23
24static 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 0, // hlsl_constant
46 0, // hlsl_private
47 0, // hlsl_device
48 0, // hlsl_input
49 0, // hlsl_output
50 0, // hlsl_push_constant
51 20, // wasm_funcref
52};
53
54class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
55
56 enum SIMDEnum {
57 NoSIMD,
58 SIMD128,
59 RelaxedSIMD,
60 } SIMDLevel = NoSIMD;
61
62 bool HasAtomics = false;
63 bool HasBulkMemory = false;
64 bool HasBulkMemoryOpt = false;
65 bool HasCallIndirectOverlong = false;
66 bool HasCooperativeThreading = false;
67 bool HasCompactImports = false;
68 bool HasExceptionHandling = false;
69 bool HasExtendedConst = false;
70 bool HasFP16 = false;
71 bool HasGC = false;
72 bool HasLibcallThreadContext = false;
73 bool HasMultiMemory = false;
74 bool HasMultivalue = false;
75 bool HasMutableGlobals = false;
76 bool HasNontrappingFPToInt = false;
77 bool HasReferenceTypes = false;
78 bool HasRelaxedAtomics = false;
79 bool HasSignExt = false;
80 bool HasTailCall = false;
81 bool HasWideArithmetic = false;
82
83 std::string ABI;
84
85public:
86 explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
87 : TargetInfo(T) {
88 AddrSpaceMap = &WebAssemblyAddrSpaceMap;
89 UseAddrSpaceMapMangling = true;
90 NoAsmVariants = true;
91 SuitableAlign = 128;
92 LargeArrayMinWidth = 128;
93 LargeArrayAlign = 128;
94 SigAtomicType = SignedLong;
95 LongDoubleWidth = LongDoubleAlign = 128;
96 LongDoubleFormat = &llvm::APFloat::IEEEquad();
97 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
98 HasUnalignedAccess = true;
99 if (T.isWALI()) {
100 // The WALI ABI is documented here:
101 // https://doc.rust-lang.org/rustc/platform-support/wasm32-wali-linux.html
102 // Currently, this ABI only applies to wasm32 targets and notably requires
103 // 64-bit longs
104 LongAlign = LongWidth = 64;
105 SizeType = UnsignedInt;
106 PtrDiffType = SignedInt;
107 IntPtrType = SignedInt;
108 } else {
109 // size_t being unsigned long for both wasm32 and wasm64 makes mangled
110 // names more consistent between the two.
111 SizeType = UnsignedLong;
112 PtrDiffType = SignedLong;
113 IntPtrType = SignedLong;
114 }
115 if (T.getOS() == llvm::Triple::WASIp3) {
116 HasLibcallThreadContext = true;
117 HasCooperativeThreading = true;
118 }
119 }
120
121 StringRef getABI() const override;
122 bool setABI(const std::string &Name) override;
123 bool useFP16ConversionIntrinsics() const override { return !HasFP16; }
124
125protected:
126 void getTargetDefines(const LangOptions &Opts,
127 MacroBuilder &Builder) const override;
128
129private:
130 static void setSIMDLevel(llvm::StringMap<bool> &Features, SIMDEnum Level,
131 bool Enabled);
132
133 bool
134 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
135 StringRef CPU,
136 const std::vector<std::string> &FeaturesVec) const override;
137 bool hasFeature(StringRef Feature) const final;
138
139 void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
140 bool Enabled) const final;
141
142 bool handleTargetFeatures(std::vector<std::string> &Features,
143 DiagnosticsEngine &Diags) final;
144
145 bool isValidCPUName(StringRef Name) const final;
146 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const final;
147
148 bool setCPU(StringRef Name) final { return isValidCPUName(Name); }
149
150 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const final;
151
152 BuiltinVaListKind getBuiltinVaListKind() const final {
153 return VoidPtrBuiltinVaList;
154 }
155
156 ArrayRef<const char *> getGCCRegNames() const final { return {}; }
157
158 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final {
159 return {};
160 }
161
162 bool validateAsmConstraint(const char *&Name,
163 TargetInfo::ConstraintInfo &Info) const final {
164 return false;
165 }
166
167 std::string_view getClobbers() const final { return ""; }
168
169 bool isCLZForZeroUndef() const final { return false; }
170
171 bool hasInt128Type() const final { return true; }
172
173 IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
174 // WebAssembly prefers long long for explicitly 64-bit integers.
175 return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong)
176 : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
177 }
178
179 IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
180 // WebAssembly uses long long for int_least64_t and int_fast64_t.
181 return BitWidth == 64
182 ? (IsSigned ? SignedLongLong : UnsignedLongLong)
183 : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
184 }
185
186 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
187 switch (CC) {
188 case CC_C:
189 case CC_Swift:
190 return CCCR_OK;
191 case CC_SwiftAsync:
192 return HasTailCall ? CCCR_OK : CCCR_Error;
193 default:
194 return CCCR_Warning;
195 }
196 }
197
198 bool hasBitIntType() const override { return true; }
199
200 bool hasProtectedVisibility() const override { return false; }
201
202 void adjust(DiagnosticsEngine &Diags, LangOptions &Opts,
203 const TargetInfo *Aux) override;
204};
205
206class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo
207 : public WebAssemblyTargetInfo {
208public:
209 explicit WebAssembly32TargetInfo(const llvm::Triple &T,
210 const TargetOptions &Opts)
211 : WebAssemblyTargetInfo(T, Opts) {
212 resetDataLayout();
213 }
214
215protected:
216 void getTargetDefines(const LangOptions &Opts,
217 MacroBuilder &Builder) const override;
218};
219
220class LLVM_LIBRARY_VISIBILITY WebAssembly64TargetInfo
221 : public WebAssemblyTargetInfo {
222public:
223 explicit WebAssembly64TargetInfo(const llvm::Triple &T,
224 const TargetOptions &Opts)
225 : WebAssemblyTargetInfo(T, Opts) {
226 LongAlign = LongWidth = 64;
227 PointerAlign = PointerWidth = 64;
228 SizeType = UnsignedLong;
229 PtrDiffType = SignedLong;
230 IntPtrType = SignedLong;
231 resetDataLayout();
232 }
233
234protected:
235 void getTargetDefines(const LangOptions &Opts,
236 MacroBuilder &Builder) const override;
237};
238} // namespace targets
239} // namespace clang
240#endif // LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
241