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 HasNontrappingFPToInt = false;
57   bool HasSignExt = false;
58   bool HasExceptionHandling = false;
59   bool HasBulkMemory = false;
60   bool HasAtomics = false;
61   bool HasMutableGlobals = false;
62   bool HasMultivalue = false;
63   bool HasTailCall = false;
64   bool HasReferenceTypes = false;
65   bool HasExtendedConst = false;
66 
67   std::string ABI;
68 
69 public:
70   explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
71       : TargetInfo(T) {
72     AddrSpaceMap = &WebAssemblyAddrSpaceMap;
73     NoAsmVariants = true;
74     SuitableAlign = 128;
75     LargeArrayMinWidth = 128;
76     LargeArrayAlign = 128;
77     SigAtomicType = SignedLong;
78     LongDoubleWidth = LongDoubleAlign = 128;
79     LongDoubleFormat = &llvm::APFloat::IEEEquad();
80     MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
81     // size_t being unsigned long for both wasm32 and wasm64 makes mangled names
82     // more consistent between the two.
83     SizeType = UnsignedLong;
84     PtrDiffType = SignedLong;
85     IntPtrType = SignedLong;
86   }
87 
88   StringRef getABI() const override;
89   bool setABI(const std::string &Name) override;
90 
91 protected:
92   void getTargetDefines(const LangOptions &Opts,
93                         MacroBuilder &Builder) const override;
94 
95 private:
96   static void setSIMDLevel(llvm::StringMap<bool> &Features, SIMDEnum Level,
97                            bool Enabled);
98 
99   bool
100   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
101                  StringRef CPU,
102                  const std::vector<std::string> &FeaturesVec) const override;
103   bool hasFeature(StringRef Feature) const final;
104 
105   void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
106                          bool Enabled) const final;
107 
108   bool handleTargetFeatures(std::vector<std::string> &Features,
109                             DiagnosticsEngine &Diags) final;
110 
111   bool isValidCPUName(StringRef Name) const final;
112   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const final;
113 
114   bool setCPU(const std::string &Name) final { return isValidCPUName(Name); }
115 
116   ArrayRef<Builtin::Info> getTargetBuiltins() const final;
117 
118   BuiltinVaListKind getBuiltinVaListKind() const final {
119     return VoidPtrBuiltinVaList;
120   }
121 
122   ArrayRef<const char *> getGCCRegNames() const final { return std::nullopt; }
123 
124   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final {
125     return std::nullopt;
126   }
127 
128   bool validateAsmConstraint(const char *&Name,
129                              TargetInfo::ConstraintInfo &Info) const final {
130     return false;
131   }
132 
133   std::string_view getClobbers() const final { return ""; }
134 
135   bool isCLZForZeroUndef() const final { return false; }
136 
137   bool hasInt128Type() const final { return true; }
138 
139   IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
140     // WebAssembly prefers long long for explicitly 64-bit integers.
141     return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong)
142                           : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
143   }
144 
145   IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
146     // WebAssembly uses long long for int_least64_t and int_fast64_t.
147     return BitWidth == 64
148                ? (IsSigned ? SignedLongLong : UnsignedLongLong)
149                : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
150   }
151 
152   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
153     switch (CC) {
154     case CC_C:
155     case CC_Swift:
156       return CCCR_OK;
157     case CC_SwiftAsync:
158       return CCCR_Error;
159     default:
160       return CCCR_Warning;
161     }
162   }
163 
164   bool hasBitIntType() const override { return true; }
165 
166   bool hasProtectedVisibility() const override { return false; }
167 
168   void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
169 };
170 
171 class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo
172     : public WebAssemblyTargetInfo {
173 public:
174   explicit WebAssembly32TargetInfo(const llvm::Triple &T,
175                                    const TargetOptions &Opts)
176       : WebAssemblyTargetInfo(T, Opts) {
177     if (T.isOSEmscripten())
178       resetDataLayout("e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-"
179                       "S128-ni:1:10:20");
180     else
181       resetDataLayout(
182           "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20");
183   }
184 
185 protected:
186   void getTargetDefines(const LangOptions &Opts,
187                         MacroBuilder &Builder) const override;
188 };
189 
190 class LLVM_LIBRARY_VISIBILITY WebAssembly64TargetInfo
191     : public WebAssemblyTargetInfo {
192 public:
193   explicit WebAssembly64TargetInfo(const llvm::Triple &T,
194                                    const TargetOptions &Opts)
195       : WebAssemblyTargetInfo(T, Opts) {
196     LongAlign = LongWidth = 64;
197     PointerAlign = PointerWidth = 64;
198     SizeType = UnsignedLong;
199     PtrDiffType = SignedLong;
200     IntPtrType = SignedLong;
201     if (T.isOSEmscripten())
202       resetDataLayout("e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-"
203                       "S128-ni:1:10:20");
204     else
205       resetDataLayout(
206           "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20");
207   }
208 
209 protected:
210   void getTargetDefines(const LangOptions &Opts,
211                         MacroBuilder &Builder) const override;
212 };
213 } // namespace targets
214 } // namespace clang
215 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
216