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