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