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
24namespace llvm {
25
26namespace yaml {
27struct WebAssemblyFunctionInfo;
28}
29
30/// This class is derived from MachineFunctionInfo and contains private
31/// WebAssembly-specific information for each MachineFunction.
32class 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
66public:
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
156void 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)
161void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc,
162                         const Function &ContextFunc, const TargetMachine &TM,
163                         SmallVectorImpl<MVT> &Params,
164                         SmallVectorImpl<MVT> &Results);
165
166void valTypesFromMVTs(const ArrayRef<MVT> &In,
167                      SmallVectorImpl<wasm::ValType> &Out);
168
169std::unique_ptr<wasm::WasmSignature>
170signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
171                  const SmallVectorImpl<MVT> &Params);
172
173namespace yaml {
174
175struct 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
185template <> 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