1296417Sdim// WebAssemblyMachineFunctionInfo.h-WebAssembly machine function info-*- C++ -*-
2285163Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6285163Sdim//
7285163Sdim//===----------------------------------------------------------------------===//
8285163Sdim///
9285163Sdim/// \file
10341825Sdim/// This file declares WebAssembly-specific per-machine-function
11285163Sdim/// information.
12285163Sdim///
13285163Sdim//===----------------------------------------------------------------------===//
14285163Sdim
15285163Sdim#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
16285163Sdim#define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
17285163Sdim
18296417Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
19344779Sdim#include "llvm/BinaryFormat/Wasm.h"
20353358Sdim#include "llvm/CodeGen/MIRYamlMapping.h"
21285163Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
22344779Sdim#include "llvm/MC/MCSymbolWasm.h"
23285163Sdim
24285163Sdimnamespace llvm {
25285163Sdim
26353358Sdimnamespace yaml {
27353358Sdimstruct WebAssemblyFunctionInfo;
28353358Sdim}
29353358Sdim
30285163Sdim/// This class is derived from MachineFunctionInfo and contains private
31285163Sdim/// WebAssembly-specific information for each MachineFunction.
32285163Sdimclass WebAssemblyFunctionInfo final : public MachineFunctionInfo {
33285163Sdim  MachineFunction &MF;
34285163Sdim
35296417Sdim  std::vector<MVT> Params;
36314564Sdim  std::vector<MVT> Results;
37314564Sdim  std::vector<MVT> Locals;
38296417Sdim
39296417Sdim  /// A mapping from CodeGen vreg index to WebAssembly register number.
40296417Sdim  std::vector<unsigned> WARegs;
41296417Sdim
42296417Sdim  /// A mapping from CodeGen vreg index to a boolean value indicating whether
43296417Sdim  /// the given register is considered to be "stackified", meaning it has been
44296417Sdim  /// determined or made to meet the stack requirements:
45296417Sdim  ///   - single use (per path)
46296417Sdim  ///   - single def (per path)
47296417Sdim  ///   - defined and used in LIFO order with other stack registers
48296417Sdim  BitVector VRegStackified;
49296417Sdim
50309124Sdim  // A virtual register holding the pointer to the vararg buffer for vararg
51309124Sdim  // functions. It is created and set in TLI::LowerFormalArguments and read by
52309124Sdim  // TLI::LowerVASTART
53309124Sdim  unsigned VarargVreg = -1U;
54296417Sdim
55314564Sdim  // A virtual register holding the base pointer for functions that have
56314564Sdim  // overaligned values on the user stack.
57314564Sdim  unsigned BasePtrVreg = -1U;
58314564Sdim
59353358Sdim  // Function properties.
60353358Sdim  bool CFGStackified = false;
61353358Sdim
62344779Sdimpublic:
63309124Sdim  explicit WebAssemblyFunctionInfo(MachineFunction &MF) : MF(MF) {}
64285163Sdim  ~WebAssemblyFunctionInfo() override;
65353358Sdim  void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI);
66296417Sdim
67296417Sdim  void addParam(MVT VT) { Params.push_back(VT); }
68296417Sdim  const std::vector<MVT> &getParams() const { return Params; }
69296417Sdim
70314564Sdim  void addResult(MVT VT) { Results.push_back(VT); }
71314564Sdim  const std::vector<MVT> &getResults() const { return Results; }
72314564Sdim
73344779Sdim  void clearParamsAndResults() {
74344779Sdim    Params.clear();
75344779Sdim    Results.clear();
76344779Sdim  }
77341825Sdim
78321369Sdim  void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
79321369Sdim  void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
80314564Sdim  void addLocal(MVT VT) { Locals.push_back(VT); }
81314564Sdim  const std::vector<MVT> &getLocals() const { return Locals; }
82314564Sdim
83309124Sdim  unsigned getVarargBufferVreg() const {
84309124Sdim    assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
85309124Sdim    return VarargVreg;
86309124Sdim  }
87309124Sdim  void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; }
88309124Sdim
89314564Sdim  unsigned getBasePointerVreg() const {
90314564Sdim    assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set");
91314564Sdim    return BasePtrVreg;
92314564Sdim  }
93314564Sdim  void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; }
94314564Sdim
95296417Sdim  static const unsigned UnusedReg = -1u;
96296417Sdim
97296417Sdim  void stackifyVReg(unsigned VReg) {
98314564Sdim    assert(MF.getRegInfo().getUniqueVRegDef(VReg));
99360784Sdim    auto I = Register::virtReg2Index(VReg);
100341825Sdim    if (I >= VRegStackified.size())
101341825Sdim      VRegStackified.resize(I + 1);
102341825Sdim    VRegStackified.set(I);
103296417Sdim  }
104360784Sdim  void unstackifyVReg(unsigned VReg) {
105360784Sdim    auto I = Register::virtReg2Index(VReg);
106360784Sdim    if (I < VRegStackified.size())
107360784Sdim      VRegStackified.reset(I);
108360784Sdim  }
109296417Sdim  bool isVRegStackified(unsigned VReg) const {
110360784Sdim    auto I = Register::virtReg2Index(VReg);
111341825Sdim    if (I >= VRegStackified.size())
112296417Sdim      return false;
113341825Sdim    return VRegStackified.test(I);
114296417Sdim  }
115296417Sdim
116296417Sdim  void initWARegs();
117296417Sdim  void setWAReg(unsigned VReg, unsigned WAReg) {
118296417Sdim    assert(WAReg != UnusedReg);
119360784Sdim    auto I = Register::virtReg2Index(VReg);
120341825Sdim    assert(I < WARegs.size());
121341825Sdim    WARegs[I] = WAReg;
122296417Sdim  }
123341825Sdim  unsigned getWAReg(unsigned VReg) const {
124360784Sdim    auto I = Register::virtReg2Index(VReg);
125341825Sdim    assert(I < WARegs.size());
126341825Sdim    return WARegs[I];
127296417Sdim  }
128296417Sdim
129309124Sdim  // For a given stackified WAReg, return the id number to print with push/pop.
130309124Sdim  static unsigned getWARegStackId(unsigned Reg) {
131309124Sdim    assert(Reg & INT32_MIN);
132309124Sdim    return Reg & INT32_MAX;
133296417Sdim  }
134353358Sdim
135353358Sdim  bool isCFGStackified() const { return CFGStackified; }
136353358Sdim  void setCFGStackified(bool Value = true) { CFGStackified = Value; }
137285163Sdim};
138285163Sdim
139353358Sdimvoid computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
140344779Sdim                          SmallVectorImpl<MVT> &ValueVTs);
141314564Sdim
142344779Sdim// Compute the signature for a given FunctionType (Ty). Note that it's not the
143344779Sdim// signature for F (F is just used to get varous context)
144353358Sdimvoid computeSignatureVTs(const FunctionType *Ty, const Function &F,
145344779Sdim                         const TargetMachine &TM, SmallVectorImpl<MVT> &Params,
146314564Sdim                         SmallVectorImpl<MVT> &Results);
147314564Sdim
148353358Sdimvoid valTypesFromMVTs(const ArrayRef<MVT> &In,
149344779Sdim                      SmallVectorImpl<wasm::ValType> &Out);
150344779Sdim
151344779Sdimstd::unique_ptr<wasm::WasmSignature>
152353358SdimsignatureFromMVTs(const SmallVectorImpl<MVT> &Results,
153344779Sdim                  const SmallVectorImpl<MVT> &Params);
154344779Sdim
155353358Sdimnamespace yaml {
156353358Sdim
157353358Sdimstruct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo {
158353358Sdim  bool CFGStackified = false;
159353358Sdim
160353358Sdim  WebAssemblyFunctionInfo() = default;
161353358Sdim  WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI);
162353358Sdim
163353358Sdim  void mappingImpl(yaml::IO &YamlIO) override;
164353358Sdim  ~WebAssemblyFunctionInfo() = default;
165353358Sdim};
166353358Sdim
167353358Sdimtemplate <> struct MappingTraits<WebAssemblyFunctionInfo> {
168353358Sdim  static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) {
169353358Sdim    YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false);
170353358Sdim  }
171353358Sdim};
172353358Sdim
173353358Sdim} // end namespace yaml
174353358Sdim
175285163Sdim} // end namespace llvm
176285163Sdim
177285163Sdim#endif
178