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/BinaryFormat/Wasm.h"
20 #include "llvm/CodeGen/MIRYamlMapping.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/MC/MCSymbolWasm.h"
23 
24 namespace llvm {
25 
26 namespace yaml {
27 struct WebAssemblyFunctionInfo;
28 }
29 
30 /// This class is derived from MachineFunctionInfo and contains private
31 /// WebAssembly-specific information for each MachineFunction.
32 class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
33   std::vector<MVT> Params;
34   std::vector<MVT> Results;
35   std::vector<MVT> Locals;
36 
37   /// A mapping from CodeGen vreg index to WebAssembly register number.
38   std::vector<unsigned> WARegs;
39 
40   /// A mapping from CodeGen vreg index to a boolean value indicating whether
41   /// the given register is considered to be "stackified", meaning it has been
42   /// determined or made to meet the stack requirements:
43   ///   - single use (per path)
44   ///   - single def (per path)
45   ///   - defined and used in LIFO order with other stack registers
46   BitVector VRegStackified;
47 
48   // A virtual register holding the pointer to the vararg buffer for vararg
49   // functions. It is created and set in TLI::LowerFormalArguments and read by
50   // TLI::LowerVASTART
51   unsigned VarargVreg = -1U;
52 
53   // A virtual register holding the base pointer for functions that have
54   // overaligned values on the user stack.
55   unsigned BasePtrVreg = -1U;
56   // A virtual register holding the frame base. This is either FP or SP
57   // after it has been replaced by a vreg
58   unsigned FrameBaseVreg = -1U;
59   // The local holding the frame base. This is either FP or SP
60   // after WebAssemblyExplicitLocals
61   unsigned FrameBaseLocal = -1U;
62 
63   // Function properties.
64   bool CFGStackified = false;
65 
66 public:
67   explicit WebAssemblyFunctionInfo(MachineFunction &MF) {}
68   ~WebAssemblyFunctionInfo() override;
69   void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI);
70 
71   void addParam(MVT VT) { Params.push_back(VT); }
72   const std::vector<MVT> &getParams() const { return Params; }
73 
74   void addResult(MVT VT) { Results.push_back(VT); }
75   const std::vector<MVT> &getResults() const { return Results; }
76 
77   void clearParamsAndResults() {
78     Params.clear();
79     Results.clear();
80   }
81 
82   void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
83   void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
84   void addLocal(MVT VT) { Locals.push_back(VT); }
85   const std::vector<MVT> &getLocals() const { return Locals; }
86 
87   unsigned getVarargBufferVreg() const {
88     assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
89     return VarargVreg;
90   }
91   void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; }
92 
93   unsigned getBasePointerVreg() const {
94     assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set");
95     return BasePtrVreg;
96   }
97   void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; }
98   unsigned getFrameBaseVreg() const {
99     assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set");
100     return FrameBaseVreg;
101   }
102   void clearFrameBaseVreg() { FrameBaseVreg = -1U; }
103   // Return true if the frame base physreg has been replaced by a virtual reg.
104   bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; }
105   void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; }
106   unsigned getFrameBaseLocal() const {
107     assert(FrameBaseLocal != -1U && "Frame base local hasn't been set");
108     return FrameBaseLocal;
109   }
110   void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; }
111 
112   static const unsigned UnusedReg = -1u;
113 
114   void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) {
115     assert(MRI.getUniqueVRegDef(VReg));
116     auto I = Register::virtReg2Index(VReg);
117     if (I >= VRegStackified.size())
118       VRegStackified.resize(I + 1);
119     VRegStackified.set(I);
120   }
121   void unstackifyVReg(unsigned VReg) {
122     auto I = Register::virtReg2Index(VReg);
123     if (I < VRegStackified.size())
124       VRegStackified.reset(I);
125   }
126   bool isVRegStackified(unsigned VReg) const {
127     auto I = Register::virtReg2Index(VReg);
128     if (I >= VRegStackified.size())
129       return false;
130     return VRegStackified.test(I);
131   }
132 
133   void initWARegs(MachineRegisterInfo &MRI);
134   void setWAReg(unsigned VReg, unsigned WAReg) {
135     assert(WAReg != UnusedReg);
136     auto I = Register::virtReg2Index(VReg);
137     assert(I < WARegs.size());
138     WARegs[I] = WAReg;
139   }
140   unsigned getWAReg(unsigned VReg) const {
141     auto I = Register::virtReg2Index(VReg);
142     assert(I < WARegs.size());
143     return WARegs[I];
144   }
145 
146   // For a given stackified WAReg, return the id number to print with push/pop.
147   static unsigned getWARegStackId(unsigned Reg) {
148     assert(Reg & INT32_MIN);
149     return Reg & INT32_MAX;
150   }
151 
152   bool isCFGStackified() const { return CFGStackified; }
153   void setCFGStackified(bool Value = true) { CFGStackified = Value; }
154 };
155 
156 void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
157                           SmallVectorImpl<MVT> &ValueVTs);
158 
159 // Compute the signature for a given FunctionType (Ty). Note that it's not the
160 // signature for ContextFunc (ContextFunc is just used to get varous context)
161 void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc,
162                          const Function &ContextFunc, const TargetMachine &TM,
163                          SmallVectorImpl<MVT> &Params,
164                          SmallVectorImpl<MVT> &Results);
165 
166 void valTypesFromMVTs(const ArrayRef<MVT> &In,
167                       SmallVectorImpl<wasm::ValType> &Out);
168 
169 std::unique_ptr<wasm::WasmSignature>
170 signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
171                   const SmallVectorImpl<MVT> &Params);
172 
173 namespace yaml {
174 
175 struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo {
176   bool CFGStackified = false;
177 
178   WebAssemblyFunctionInfo() = default;
179   WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI);
180 
181   void mappingImpl(yaml::IO &YamlIO) override;
182   ~WebAssemblyFunctionInfo() = default;
183 };
184 
185 template <> struct MappingTraits<WebAssemblyFunctionInfo> {
186   static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) {
187     YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false);
188   }
189 };
190 
191 } // end namespace yaml
192 
193 } // end namespace llvm
194 
195 #endif
196