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