xref: /freebsd/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric // WebAssemblyMachineFunctionInfo.h-WebAssembly machine function info-*- C++ -*-
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file declares WebAssembly-specific per-machine-function
110b57cec5SDimitry Andric /// information.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
160b57cec5SDimitry Andric #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCSymbolWasm.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric namespace llvm {
240b57cec5SDimitry Andric 
25fe6060f1SDimitry Andric struct WasmEHFuncInfo;
26fe6060f1SDimitry Andric 
270b57cec5SDimitry Andric namespace yaml {
280b57cec5SDimitry Andric struct WebAssemblyFunctionInfo;
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric /// This class is derived from MachineFunctionInfo and contains private
320b57cec5SDimitry Andric /// WebAssembly-specific information for each MachineFunction.
330b57cec5SDimitry Andric class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
34*81ad6265SDimitry Andric   const MachineFunction *MF;
35fe6060f1SDimitry Andric 
360b57cec5SDimitry Andric   std::vector<MVT> Params;
370b57cec5SDimitry Andric   std::vector<MVT> Results;
380b57cec5SDimitry Andric   std::vector<MVT> Locals;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   /// A mapping from CodeGen vreg index to WebAssembly register number.
410b57cec5SDimitry Andric   std::vector<unsigned> WARegs;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   /// A mapping from CodeGen vreg index to a boolean value indicating whether
440b57cec5SDimitry Andric   /// the given register is considered to be "stackified", meaning it has been
450b57cec5SDimitry Andric   /// determined or made to meet the stack requirements:
460b57cec5SDimitry Andric   ///   - single use (per path)
470b57cec5SDimitry Andric   ///   - single def (per path)
480b57cec5SDimitry Andric   ///   - defined and used in LIFO order with other stack registers
490b57cec5SDimitry Andric   BitVector VRegStackified;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   // A virtual register holding the pointer to the vararg buffer for vararg
520b57cec5SDimitry Andric   // functions. It is created and set in TLI::LowerFormalArguments and read by
530b57cec5SDimitry Andric   // TLI::LowerVASTART
540b57cec5SDimitry Andric   unsigned VarargVreg = -1U;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   // A virtual register holding the base pointer for functions that have
570b57cec5SDimitry Andric   // overaligned values on the user stack.
580b57cec5SDimitry Andric   unsigned BasePtrVreg = -1U;
595ffd83dbSDimitry Andric   // A virtual register holding the frame base. This is either FP or SP
605ffd83dbSDimitry Andric   // after it has been replaced by a vreg
615ffd83dbSDimitry Andric   unsigned FrameBaseVreg = -1U;
625ffd83dbSDimitry Andric   // The local holding the frame base. This is either FP or SP
635ffd83dbSDimitry Andric   // after WebAssemblyExplicitLocals
645ffd83dbSDimitry Andric   unsigned FrameBaseLocal = -1U;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   // Function properties.
670b57cec5SDimitry Andric   bool CFGStackified = false;
680b57cec5SDimitry Andric 
69fe6060f1SDimitry Andric   // Catchpad unwind destination info for wasm EH.
70fe6060f1SDimitry Andric   WasmEHFuncInfo *WasmEHInfo = nullptr;
71fe6060f1SDimitry Andric 
720b57cec5SDimitry Andric public:
73*81ad6265SDimitry Andric   explicit WebAssemblyFunctionInfo(MachineFunction &MF_)
74*81ad6265SDimitry Andric       : MF(&MF_), WasmEHInfo(MF_.getWasmEHFuncInfo()) {}
750b57cec5SDimitry Andric   ~WebAssemblyFunctionInfo() override;
76fe6060f1SDimitry Andric 
77*81ad6265SDimitry Andric   MachineFunctionInfo *
78*81ad6265SDimitry Andric   clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
79*81ad6265SDimitry Andric         const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
80*81ad6265SDimitry Andric       const override;
81*81ad6265SDimitry Andric 
82*81ad6265SDimitry Andric   const MachineFunction &getMachineFunction() const { return *MF; }
83fe6060f1SDimitry Andric 
840b57cec5SDimitry Andric   void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI);
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   void addParam(MVT VT) { Params.push_back(VT); }
870b57cec5SDimitry Andric   const std::vector<MVT> &getParams() const { return Params; }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   void addResult(MVT VT) { Results.push_back(VT); }
900b57cec5SDimitry Andric   const std::vector<MVT> &getResults() const { return Results; }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   void clearParamsAndResults() {
930b57cec5SDimitry Andric     Params.clear();
940b57cec5SDimitry Andric     Results.clear();
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
980b57cec5SDimitry Andric   void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
990b57cec5SDimitry Andric   void addLocal(MVT VT) { Locals.push_back(VT); }
1000b57cec5SDimitry Andric   const std::vector<MVT> &getLocals() const { return Locals; }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   unsigned getVarargBufferVreg() const {
1030b57cec5SDimitry Andric     assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
1040b57cec5SDimitry Andric     return VarargVreg;
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric   void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   unsigned getBasePointerVreg() const {
1090b57cec5SDimitry Andric     assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set");
1100b57cec5SDimitry Andric     return BasePtrVreg;
1110b57cec5SDimitry Andric   }
1125ffd83dbSDimitry Andric   void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; }
1135ffd83dbSDimitry Andric   unsigned getFrameBaseVreg() const {
1145ffd83dbSDimitry Andric     assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set");
1155ffd83dbSDimitry Andric     return FrameBaseVreg;
1165ffd83dbSDimitry Andric   }
1175ffd83dbSDimitry Andric   void clearFrameBaseVreg() { FrameBaseVreg = -1U; }
1185ffd83dbSDimitry Andric   // Return true if the frame base physreg has been replaced by a virtual reg.
1195ffd83dbSDimitry Andric   bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; }
1205ffd83dbSDimitry Andric   void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; }
1215ffd83dbSDimitry Andric   unsigned getFrameBaseLocal() const {
1225ffd83dbSDimitry Andric     assert(FrameBaseLocal != -1U && "Frame base local hasn't been set");
1235ffd83dbSDimitry Andric     return FrameBaseLocal;
1245ffd83dbSDimitry Andric   }
1250b57cec5SDimitry Andric   void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   static const unsigned UnusedReg = -1u;
1280b57cec5SDimitry Andric 
1295ffd83dbSDimitry Andric   void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) {
1305ffd83dbSDimitry Andric     assert(MRI.getUniqueVRegDef(VReg));
1318bcb0991SDimitry Andric     auto I = Register::virtReg2Index(VReg);
1320b57cec5SDimitry Andric     if (I >= VRegStackified.size())
1330b57cec5SDimitry Andric       VRegStackified.resize(I + 1);
1340b57cec5SDimitry Andric     VRegStackified.set(I);
1350b57cec5SDimitry Andric   }
1368bcb0991SDimitry Andric   void unstackifyVReg(unsigned VReg) {
1378bcb0991SDimitry Andric     auto I = Register::virtReg2Index(VReg);
1388bcb0991SDimitry Andric     if (I < VRegStackified.size())
1398bcb0991SDimitry Andric       VRegStackified.reset(I);
1408bcb0991SDimitry Andric   }
1410b57cec5SDimitry Andric   bool isVRegStackified(unsigned VReg) const {
1428bcb0991SDimitry Andric     auto I = Register::virtReg2Index(VReg);
1430b57cec5SDimitry Andric     if (I >= VRegStackified.size())
1440b57cec5SDimitry Andric       return false;
1450b57cec5SDimitry Andric     return VRegStackified.test(I);
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric 
1485ffd83dbSDimitry Andric   void initWARegs(MachineRegisterInfo &MRI);
1490b57cec5SDimitry Andric   void setWAReg(unsigned VReg, unsigned WAReg) {
1500b57cec5SDimitry Andric     assert(WAReg != UnusedReg);
1518bcb0991SDimitry Andric     auto I = Register::virtReg2Index(VReg);
1520b57cec5SDimitry Andric     assert(I < WARegs.size());
1530b57cec5SDimitry Andric     WARegs[I] = WAReg;
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric   unsigned getWAReg(unsigned VReg) const {
1568bcb0991SDimitry Andric     auto I = Register::virtReg2Index(VReg);
1570b57cec5SDimitry Andric     assert(I < WARegs.size());
1580b57cec5SDimitry Andric     return WARegs[I];
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   // For a given stackified WAReg, return the id number to print with push/pop.
1620b57cec5SDimitry Andric   static unsigned getWARegStackId(unsigned Reg) {
1630b57cec5SDimitry Andric     assert(Reg & INT32_MIN);
1640b57cec5SDimitry Andric     return Reg & INT32_MAX;
1650b57cec5SDimitry Andric   }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   bool isCFGStackified() const { return CFGStackified; }
1680b57cec5SDimitry Andric   void setCFGStackified(bool Value = true) { CFGStackified = Value; }
169fe6060f1SDimitry Andric 
170fe6060f1SDimitry Andric   WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; }
171fe6060f1SDimitry Andric   void setWasmEHFuncInfo(WasmEHFuncInfo *Info) { WasmEHInfo = Info; }
1720b57cec5SDimitry Andric };
1730b57cec5SDimitry Andric 
1741fd87a68SDimitry Andric void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
1751fd87a68SDimitry Andric                           LLVMContext &Ctx, const DataLayout &DL, Type *Ty,
1761fd87a68SDimitry Andric                           SmallVectorImpl<MVT> &ValueVTs);
1771fd87a68SDimitry Andric 
1780b57cec5SDimitry Andric void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
1790b57cec5SDimitry Andric                           SmallVectorImpl<MVT> &ValueVTs);
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric // Compute the signature for a given FunctionType (Ty). Note that it's not the
1825ffd83dbSDimitry Andric // signature for ContextFunc (ContextFunc is just used to get varous context)
1835ffd83dbSDimitry Andric void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc,
1845ffd83dbSDimitry Andric                          const Function &ContextFunc, const TargetMachine &TM,
1855ffd83dbSDimitry Andric                          SmallVectorImpl<MVT> &Params,
1860b57cec5SDimitry Andric                          SmallVectorImpl<MVT> &Results);
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric void valTypesFromMVTs(const ArrayRef<MVT> &In,
1890b57cec5SDimitry Andric                       SmallVectorImpl<wasm::ValType> &Out);
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric std::unique_ptr<wasm::WasmSignature>
1920b57cec5SDimitry Andric signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
1930b57cec5SDimitry Andric                   const SmallVectorImpl<MVT> &Params);
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric namespace yaml {
1960b57cec5SDimitry Andric 
197fe6060f1SDimitry Andric using BBNumberMap = DenseMap<int, int>;
198fe6060f1SDimitry Andric 
1990b57cec5SDimitry Andric struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo {
200fe6060f1SDimitry Andric   std::vector<FlowStringValue> Params;
201fe6060f1SDimitry Andric   std::vector<FlowStringValue> Results;
2020b57cec5SDimitry Andric   bool CFGStackified = false;
203fe6060f1SDimitry Andric   // The same as WasmEHFuncInfo's SrcToUnwindDest, but stored in the mapping of
204fe6060f1SDimitry Andric   // BB numbers
205fe6060f1SDimitry Andric   BBNumberMap SrcToUnwindDest;
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   WebAssemblyFunctionInfo() = default;
2080b57cec5SDimitry Andric   WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI);
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   void mappingImpl(yaml::IO &YamlIO) override;
2110b57cec5SDimitry Andric   ~WebAssemblyFunctionInfo() = default;
2120b57cec5SDimitry Andric };
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric template <> struct MappingTraits<WebAssemblyFunctionInfo> {
2150b57cec5SDimitry Andric   static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) {
216fe6060f1SDimitry Andric     YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>());
217fe6060f1SDimitry Andric     YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>());
2180b57cec5SDimitry Andric     YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false);
219fe6060f1SDimitry Andric     YamlIO.mapOptional("wasmEHFuncInfo", MFI.SrcToUnwindDest);
220fe6060f1SDimitry Andric   }
221fe6060f1SDimitry Andric };
222fe6060f1SDimitry Andric 
223fe6060f1SDimitry Andric template <> struct CustomMappingTraits<BBNumberMap> {
224fe6060f1SDimitry Andric   static void inputOne(IO &YamlIO, StringRef Key,
225fe6060f1SDimitry Andric                        BBNumberMap &SrcToUnwindDest) {
226fe6060f1SDimitry Andric     YamlIO.mapRequired(Key.str().c_str(),
227fe6060f1SDimitry Andric                        SrcToUnwindDest[std::atoi(Key.str().c_str())]);
228fe6060f1SDimitry Andric   }
229fe6060f1SDimitry Andric 
230fe6060f1SDimitry Andric   static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) {
231fe6060f1SDimitry Andric     for (auto KV : SrcToUnwindDest)
232fe6060f1SDimitry Andric       YamlIO.mapRequired(std::to_string(KV.first).c_str(), KV.second);
2330b57cec5SDimitry Andric   }
2340b57cec5SDimitry Andric };
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric } // end namespace yaml
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric } // end namespace llvm
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric #endif
241