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