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     UnimplementedSIMD128,
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 
43 public:
44   explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
45       : TargetInfo(T) {
46     NoAsmVariants = true;
47     SuitableAlign = 128;
48     LargeArrayMinWidth = 128;
49     LargeArrayAlign = 128;
50     SimdDefaultAlign = 128;
51     SigAtomicType = SignedLong;
52     LongDoubleWidth = LongDoubleAlign = 128;
53     LongDoubleFormat = &llvm::APFloat::IEEEquad();
54     MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
55     // size_t being unsigned long for both wasm32 and wasm64 makes mangled names
56     // more consistent between the two.
57     SizeType = UnsignedLong;
58     PtrDiffType = SignedLong;
59     IntPtrType = SignedLong;
60   }
61 
62 protected:
63   void getTargetDefines(const LangOptions &Opts,
64                         MacroBuilder &Builder) const override;
65 
66 private:
67   static void setSIMDLevel(llvm::StringMap<bool> &Features, SIMDEnum Level);
68 
69   bool
70   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
71                  StringRef CPU,
72                  const std::vector<std::string> &FeaturesVec) const override;
73   bool hasFeature(StringRef Feature) const final;
74 
75   bool handleTargetFeatures(std::vector<std::string> &Features,
76                             DiagnosticsEngine &Diags) final;
77 
78   bool isValidCPUName(StringRef Name) const final;
79   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const final;
80 
81   bool setCPU(const std::string &Name) final { return isValidCPUName(Name); }
82 
83   ArrayRef<Builtin::Info> getTargetBuiltins() const final;
84 
85   BuiltinVaListKind getBuiltinVaListKind() const final {
86     return VoidPtrBuiltinVaList;
87   }
88 
89   ArrayRef<const char *> getGCCRegNames() const final { return None; }
90 
91   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const final {
92     return None;
93   }
94 
95   bool validateAsmConstraint(const char *&Name,
96                              TargetInfo::ConstraintInfo &Info) const final {
97     return false;
98   }
99 
100   const char *getClobbers() const final { return ""; }
101 
102   bool isCLZForZeroUndef() const final { return false; }
103 
104   bool hasInt128Type() const final { return true; }
105 
106   IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
107     // WebAssembly prefers long long for explicitly 64-bit integers.
108     return BitWidth == 64 ? (IsSigned ? SignedLongLong : UnsignedLongLong)
109                           : TargetInfo::getIntTypeByWidth(BitWidth, IsSigned);
110   }
111 
112   IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const final {
113     // WebAssembly uses long long for int_least64_t and int_fast64_t.
114     return BitWidth == 64
115                ? (IsSigned ? SignedLongLong : UnsignedLongLong)
116                : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
117   }
118 
119   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
120     switch (CC) {
121     case CC_C:
122     case CC_Swift:
123       return CCCR_OK;
124     default:
125       return CCCR_Warning;
126     }
127   }
128 };
129 class LLVM_LIBRARY_VISIBILITY WebAssembly32TargetInfo
130     : public WebAssemblyTargetInfo {
131 public:
132   explicit WebAssembly32TargetInfo(const llvm::Triple &T,
133                                    const TargetOptions &Opts)
134       : WebAssemblyTargetInfo(T, Opts) {
135     resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128");
136   }
137 
138 protected:
139   void getTargetDefines(const LangOptions &Opts,
140                         MacroBuilder &Builder) const override;
141 };
142 
143 class LLVM_LIBRARY_VISIBILITY WebAssembly64TargetInfo
144     : public WebAssemblyTargetInfo {
145 public:
146   explicit WebAssembly64TargetInfo(const llvm::Triple &T,
147                                    const TargetOptions &Opts)
148       : WebAssemblyTargetInfo(T, Opts) {
149     LongAlign = LongWidth = 64;
150     PointerAlign = PointerWidth = 64;
151     SizeType = UnsignedLong;
152     PtrDiffType = SignedLong;
153     IntPtrType = SignedLong;
154     resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
155   }
156 
157 protected:
158   void getTargetDefines(const LangOptions &Opts,
159                         MacroBuilder &Builder) const override;
160 };
161 } // namespace targets
162 } // namespace clang
163 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_WEBASSEMBLY_H
164