1 // WebAssemblyMachineFunctionInfo.h-WebAssembly machine function info-*- 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 /// \file
10 /// This file declares WebAssembly-specific per-machine-function
11 /// information.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
16 #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
17 
18 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
19 #include "llvm/CodeGen/MIRYamlMapping.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/MC/MCSymbolWasm.h"
22 
23 namespace llvm {
24 
25 struct WasmEHFuncInfo;
26 
27 namespace yaml {
28 struct WebAssemblyFunctionInfo;
29 }
30 
31 /// This class is derived from MachineFunctionInfo and contains private
32 /// WebAssembly-specific information for each MachineFunction.
33 class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
34   const MachineFunction *MF;
35 
36   std::vector<MVT> Params;
37   std::vector<MVT> Results;
38   std::vector<MVT> Locals;
39 
40   /// A mapping from CodeGen vreg index to WebAssembly register number.
41   std::vector<unsigned> WARegs;
42 
43   /// A mapping from CodeGen vreg index to a boolean value indicating whether
44   /// the given register is considered to be "stackified", meaning it has been
45   /// determined or made to meet the stack requirements:
46   ///   - single use (per path)
47   ///   - single def (per path)
48   ///   - defined and used in LIFO order with other stack registers
49   BitVector VRegStackified;
50 
51   // A virtual register holding the pointer to the vararg buffer for vararg
52   // functions. It is created and set in TLI::LowerFormalArguments and read by
53   // TLI::LowerVASTART
54   unsigned VarargVreg = -1U;
55 
56   // A virtual register holding the base pointer for functions that have
57   // overaligned values on the user stack.
58   unsigned BasePtrVreg = -1U;
59   // A virtual register holding the frame base. This is either FP or SP
60   // after it has been replaced by a vreg
61   unsigned FrameBaseVreg = -1U;
62   // The local holding the frame base. This is either FP or SP
63   // after WebAssemblyExplicitLocals
64   unsigned FrameBaseLocal = -1U;
65 
66   // Function properties.
67   bool CFGStackified = false;
68 
69   // Catchpad unwind destination info for wasm EH.
70   WasmEHFuncInfo *WasmEHInfo = nullptr;
71 
72 public:
73   explicit WebAssemblyFunctionInfo(MachineFunction &MF_)
74       : MF(&MF_), WasmEHInfo(MF_.getWasmEHFuncInfo()) {}
75   ~WebAssemblyFunctionInfo() override;
76 
77   MachineFunctionInfo *
78   clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
79         const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
80       const override;
81 
82   const MachineFunction &getMachineFunction() const { return *MF; }
83 
84   void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI);
85 
86   void addParam(MVT VT) { Params.push_back(VT); }
87   const std::vector<MVT> &getParams() const { return Params; }
88 
89   void addResult(MVT VT) { Results.push_back(VT); }
90   const std::vector<MVT> &getResults() const { return Results; }
91 
92   void clearParamsAndResults() {
93     Params.clear();
94     Results.clear();
95   }
96 
97   void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
98   void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
99   void addLocal(MVT VT) { Locals.push_back(VT); }
100   const std::vector<MVT> &getLocals() const { return Locals; }
101 
102   unsigned getVarargBufferVreg() const {
103     assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
104     return VarargVreg;
105   }
106   void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; }
107 
108   unsigned getBasePointerVreg() const {
109     assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set");
110     return BasePtrVreg;
111   }
112   void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; }
113   unsigned getFrameBaseVreg() const {
114     assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set");
115     return FrameBaseVreg;
116   }
117   void clearFrameBaseVreg() { FrameBaseVreg = -1U; }
118   // Return true if the frame base physreg has been replaced by a virtual reg.
119   bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; }
120   void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; }
121   unsigned getFrameBaseLocal() const {
122     assert(FrameBaseLocal != -1U && "Frame base local hasn't been set");
123     return FrameBaseLocal;
124   }
125   void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; }
126 
127   static const unsigned UnusedReg = -1u;
128 
129   void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) {
130     assert(MRI.getUniqueVRegDef(VReg));
131     auto I = Register::virtReg2Index(VReg);
132     if (I >= VRegStackified.size())
133       VRegStackified.resize(I + 1);
134     VRegStackified.set(I);
135   }
136   void unstackifyVReg(unsigned VReg) {
137     auto I = Register::virtReg2Index(VReg);
138     if (I < VRegStackified.size())
139       VRegStackified.reset(I);
140   }
141   bool isVRegStackified(unsigned VReg) const {
142     auto I = Register::virtReg2Index(VReg);
143     if (I >= VRegStackified.size())
144       return false;
145     return VRegStackified.test(I);
146   }
147 
148   void initWARegs(MachineRegisterInfo &MRI);
149   void setWAReg(unsigned VReg, unsigned WAReg) {
150     assert(WAReg != UnusedReg);
151     auto I = Register::virtReg2Index(VReg);
152     assert(I < WARegs.size());
153     WARegs[I] = WAReg;
154   }
155   unsigned getWAReg(unsigned VReg) const {
156     auto I = Register::virtReg2Index(VReg);
157     assert(I < WARegs.size());
158     return WARegs[I];
159   }
160 
161   // For a given stackified WAReg, return the id number to print with push/pop.
162   static unsigned getWARegStackId(unsigned Reg) {
163     assert(Reg & INT32_MIN);
164     return Reg & INT32_MAX;
165   }
166 
167   bool isCFGStackified() const { return CFGStackified; }
168   void setCFGStackified(bool Value = true) { CFGStackified = Value; }
169 
170   WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; }
171   void setWasmEHFuncInfo(WasmEHFuncInfo *Info) { WasmEHInfo = Info; }
172 };
173 
174 void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
175                           LLVMContext &Ctx, const DataLayout &DL, Type *Ty,
176                           SmallVectorImpl<MVT> &ValueVTs);
177 
178 void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
179                           SmallVectorImpl<MVT> &ValueVTs);
180 
181 // Compute the signature for a given FunctionType (Ty). Note that it's not the
182 // signature for ContextFunc (ContextFunc is just used to get varous context)
183 void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc,
184                          const Function &ContextFunc, const TargetMachine &TM,
185                          SmallVectorImpl<MVT> &Params,
186                          SmallVectorImpl<MVT> &Results);
187 
188 void valTypesFromMVTs(const ArrayRef<MVT> &In,
189                       SmallVectorImpl<wasm::ValType> &Out);
190 
191 std::unique_ptr<wasm::WasmSignature>
192 signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
193                   const SmallVectorImpl<MVT> &Params);
194 
195 namespace yaml {
196 
197 using BBNumberMap = DenseMap<int, int>;
198 
199 struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo {
200   std::vector<FlowStringValue> Params;
201   std::vector<FlowStringValue> Results;
202   bool CFGStackified = false;
203   // The same as WasmEHFuncInfo's SrcToUnwindDest, but stored in the mapping of
204   // BB numbers
205   BBNumberMap SrcToUnwindDest;
206 
207   WebAssemblyFunctionInfo() = default;
208   WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI);
209 
210   void mappingImpl(yaml::IO &YamlIO) override;
211   ~WebAssemblyFunctionInfo() = default;
212 };
213 
214 template <> struct MappingTraits<WebAssemblyFunctionInfo> {
215   static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) {
216     YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>());
217     YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>());
218     YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false);
219     YamlIO.mapOptional("wasmEHFuncInfo", MFI.SrcToUnwindDest);
220   }
221 };
222 
223 template <> struct CustomMappingTraits<BBNumberMap> {
224   static void inputOne(IO &YamlIO, StringRef Key,
225                        BBNumberMap &SrcToUnwindDest) {
226     YamlIO.mapRequired(Key.str().c_str(),
227                        SrcToUnwindDest[std::atoi(Key.str().c_str())]);
228   }
229 
230   static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) {
231     for (auto KV : SrcToUnwindDest)
232       YamlIO.mapRequired(std::to_string(KV.first).c_str(), KV.second);
233   }
234 };
235 
236 } // end namespace yaml
237 
238 } // end namespace llvm
239 
240 #endif
241