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