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
23namespace llvm {
24
25struct WasmEHFuncInfo;
26
27namespace yaml {
28struct WebAssemblyFunctionInfo;
29}
30
31/// This class is derived from MachineFunctionInfo and contains private
32/// WebAssembly-specific information for each MachineFunction.
33class 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
67public:
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
80  void addParam(MVT VT) { Params.push_back(VT); }
81  const std::vector<MVT> &getParams() const { return Params; }
82
83  void addResult(MVT VT) { Results.push_back(VT); }
84  const std::vector<MVT> &getResults() const { return Results; }
85
86  void clearParamsAndResults() {
87    Params.clear();
88    Results.clear();
89  }
90
91  void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
92  void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
93  void addLocal(MVT VT) { Locals.push_back(VT); }
94  const std::vector<MVT> &getLocals() const { return Locals; }
95
96  unsigned getVarargBufferVreg() const {
97    assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
98    return VarargVreg;
99  }
100  void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; }
101
102  unsigned getBasePointerVreg() const {
103    assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set");
104    return BasePtrVreg;
105  }
106  void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; }
107  unsigned getFrameBaseVreg() const {
108    assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set");
109    return FrameBaseVreg;
110  }
111  void clearFrameBaseVreg() { FrameBaseVreg = -1U; }
112  // Return true if the frame base physreg has been replaced by a virtual reg.
113  bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; }
114  void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; }
115  unsigned getFrameBaseLocal() const {
116    assert(FrameBaseLocal != -1U && "Frame base local hasn't been set");
117    return FrameBaseLocal;
118  }
119  void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; }
120
121  static const unsigned UnusedReg = -1u;
122
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  }
130  void unstackifyVReg(unsigned VReg) {
131    auto I = Register::virtReg2Index(VReg);
132    if (I < VRegStackified.size())
133      VRegStackified.reset(I);
134  }
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);
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  }
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.
156  static unsigned getWARegStackId(unsigned Reg) {
157    assert(Reg & INT32_MIN);
158    return Reg & INT32_MAX;
159  }
160
161  bool isCFGStackified() const { return CFGStackified; }
162  void setCFGStackified(bool Value = true) { CFGStackified = Value; }
163};
164
165void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
166                          LLVMContext &Ctx, const DataLayout &DL, Type *Ty,
167                          SmallVectorImpl<MVT> &ValueVTs);
168
169void 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)
174void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc,
175                         const Function &ContextFunc, const TargetMachine &TM,
176                         SmallVectorImpl<MVT> &Params,
177                         SmallVectorImpl<MVT> &Results);
178
179void valTypesFromMVTs(const ArrayRef<MVT> &In,
180                      SmallVectorImpl<wasm::ValType> &Out);
181
182std::unique_ptr<wasm::WasmSignature>
183signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
184                  const SmallVectorImpl<MVT> &Params);
185
186namespace yaml {
187
188using BBNumberMap = DenseMap<int, int>;
189
190struct 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
206template <> 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
215template <> 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