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