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/ADT/Triple.h"
19 #include "llvm/Support/Compiler.h"
20 
21 namespace clang {
22 namespace targets {
23 
24 class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
25 
26   enum SIMDEnum {
27     NoSIMD,
28     SIMD128,
29     RelaxedSIMD,
30   } SIMDLevel = NoSIMD;
31 
32   bool HasNontrappingFPToInt = false;
33   bool HasSignExt = false;
34   bool HasExceptionHandling = false;
35   bool HasBulkMemory = false;
36   bool HasAtomics = false;
37   bool HasMutableGlobals = false;
38   bool HasMultivalue = false;
39   bool HasTailCall = false;
40   bool HasReferenceTypes = false;
41   bool HasExtendedConst = false;
42 
43   std::string ABI;
44 
45 public:
46   explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
47       : TargetInfo(T) {
48     NoAsmVariants = true;
49     SuitableAlign = 128;
50     LargeArrayMinWidth = 128;
51     LargeArrayAlign = 128;
52     SimdDefaultAlign = 128;
53     SigAtomicType = SignedLong;
54     LongDoubleWidth = LongDoubleAlign = 128;
55     LongDoubleFormat = &llvm::APFloat::IEEEquad();
56     MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
57     // size_t being unsigned long for both wasm32 and wasm64 makes mangled names
58     // more consistent between the two.
59     SizeType = UnsignedLong;
60     PtrDiffType = SignedLong;
61     IntPtrType = SignedLong;
62   }
63 
64   StringRef getABI() const override;
65   bool setABI(const std::string &Name) override;
66 
67 protected:
68   void getTargetDefines(const LangOptions &Opts,
69                         MacroBuilder &Builder) const override;
70 
71 private:
72   static void setSIMDLevel(llvm::StringMap<bool> &Features, SIMDEnum Level,
73                            bool Enabled);
74 
75   bool
76   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
77                  StringRef CPU,
78                  const std::vector<std::string> &FeaturesVec) const override;
79   bool hasFeature(StringRef Feature) const final;
80 
81   void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
82                          bool Enabled) const final;
83 
84   bool handleTargetFeatures(std::vector<std::string> &Features,
85                             DiagnosticsEngine &Diags) final;
86 
87   bool isValidCPUName(StringRef Name) const final;
88   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const final;
89 
90   bool setCPU(const std::string &Name) final { return isValidCPUName(Name); }
91 
92   ArrayRef<Builtin::Info> getTargetBuiltins() const final;
93 
94   BuiltinVaListKind getBuiltinVaListKind() const final {
95     return VoidPtrBuiltinVaList;
96   }
97 
98   ArrayRef<const char *> getGCCRegNames() const final { return std::nullopt; }
99 
100   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final {
101     return std::nullopt;
102   }
103 
104   bool validateAsmConstraint(const char *&Name,
105                              TargetInfo::ConstraintInfo &Info) const final {
106     return false;
107   }
108 
109   const char *getClobbers() const final { return ""; }
110 
111   bool isCLZForZeroUndef() const final { return false; }
112 
113   bool hasInt128Type() const final { return true; }
114 
115   IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
116     // WebAssembly prefers long long for explicitly 64-bit integers.
117     return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong)
118                           : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
119   }
120 
121   IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
122     // WebAssembly uses long long for int_least64_t and int_fast64_t.
123     return BitWidth == 64
124                ? (IsSigned ? SignedLongLong : UnsignedLongLong)
125                : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
126   }
127 
128   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
129     switch (CC) {
130     case CC_C:
131     case CC_Swift:
132       return CCCR_OK;
133     case CC_SwiftAsync:
134       return CCCR_Error;
135     default:
136       return CCCR_Warning;
137     }
138   }
139 
140   bool hasBitIntType() const override { return true; }
141 
142   bool hasProtectedVisibility() const override { return false; }
143 
144   void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override;
145 };
146 
147 class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo
148     : public WebAssemblyTargetInfo {
149 public:
150   explicit WebAssembly32TargetInfo(const llvm::Triple &T,
151                                    const TargetOptions &Opts)
152       : WebAssemblyTargetInfo(T, Opts) {
153     if (T.isOSEmscripten())
154       resetDataLayout("e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-"
155                       "S128-ni:1:10:20");
156     else
157       resetDataLayout(
158           "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20");
159   }
160 
161 protected:
162   void getTargetDefines(const LangOptions &Opts,
163                         MacroBuilder &Builder) const override;
164 };
165 
166 class LLVM_LIBRARY_VISIBILITY WebAssembly64TargetInfo
167     : public WebAssemblyTargetInfo {
168 public:
169   explicit WebAssembly64TargetInfo(const llvm::Triple &T,
170                                    const TargetOptions &Opts)
171       : WebAssemblyTargetInfo(T, Opts) {
172     LongAlign = LongWidth = 64;
173     PointerAlign = PointerWidth = 64;
174     SizeType = UnsignedLong;
175     PtrDiffType = SignedLong;
176     IntPtrType = SignedLong;
177     if (T.isOSEmscripten())
178       resetDataLayout("e-m:e-p:64:64-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:64:64-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 } // namespace targets
190 } // namespace clang
191 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
192