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