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