1c3890d29SNick Lewycky // WebAssemblyMachineFunctionInfo.h-WebAssembly machine function info-*- C++ -*-
210e730a2SDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
610e730a2SDan Gohman //
710e730a2SDan Gohman //===----------------------------------------------------------------------===//
810e730a2SDan Gohman ///
910e730a2SDan Gohman /// \file
105f8f34e4SAdrian Prantl /// This file declares WebAssembly-specific per-machine-function
1110e730a2SDan Gohman /// information.
1210e730a2SDan Gohman ///
1310e730a2SDan Gohman //===----------------------------------------------------------------------===//
1410e730a2SDan Gohman 
1510e730a2SDan Gohman #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
1610e730a2SDan Gohman #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
1710e730a2SDan Gohman 
189769debfSDerek Schuff #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1952221d56SHeejin Ahn #include "llvm/CodeGen/MIRYamlMapping.h"
2010e730a2SDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
2177a7a380SDerek Schuff #include "llvm/MC/MCSymbolWasm.h"
2210e730a2SDan Gohman 
2310e730a2SDan Gohman namespace llvm {
2410e730a2SDan Gohman 
250b2bc69bSHeejin Ahn struct WasmEHFuncInfo;
260b2bc69bSHeejin Ahn 
2752221d56SHeejin Ahn namespace yaml {
2852221d56SHeejin Ahn struct WebAssemblyFunctionInfo;
2952221d56SHeejin Ahn }
3052221d56SHeejin Ahn 
3110e730a2SDan Gohman /// This class is derived from MachineFunctionInfo and contains private
3210e730a2SDan Gohman /// WebAssembly-specific information for each MachineFunction.
3310e730a2SDan Gohman class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
34*cc5a1b3dSMatt Arsenault   const MachineFunction *MF;
3551fb5bf4SHeejin Ahn 
36754cd11dSDan Gohman   std::vector<MVT> Params;
372726b88cSDan Gohman   std::vector<MVT> Results;
383acb187dSDan Gohman   std::vector<MVT> Locals;
39e51c058eSDan Gohman 
40cf4748f1SDan Gohman   /// A mapping from CodeGen vreg index to WebAssembly register number.
41cf4748f1SDan Gohman   std::vector<unsigned> WARegs;
42cf4748f1SDan Gohman 
431462faadSDan Gohman   /// A mapping from CodeGen vreg index to a boolean value indicating whether
441462faadSDan Gohman   /// the given register is considered to be "stackified", meaning it has been
451462faadSDan Gohman   /// determined or made to meet the stack requirements:
461462faadSDan Gohman   ///   - single use (per path)
471462faadSDan Gohman   ///   - single def (per path)
4853d13997SDan Gohman   ///   - defined and used in LIFO order with other stack registers
491462faadSDan Gohman   BitVector VRegStackified;
501462faadSDan Gohman 
5127501e20SDerek Schuff   // A virtual register holding the pointer to the vararg buffer for vararg
5227501e20SDerek Schuff   // functions. It is created and set in TLI::LowerFormalArguments and read by
5327501e20SDerek Schuff   // TLI::LowerVASTART
5427501e20SDerek Schuff   unsigned VarargVreg = -1U;
5527501e20SDerek Schuff 
560d41b7b3SDerek Schuff   // A virtual register holding the base pointer for functions that have
570d41b7b3SDerek Schuff   // overaligned values on the user stack.
580d41b7b3SDerek Schuff   unsigned BasePtrVreg = -1U;
59ff171acfSDerek Schuff   // A virtual register holding the frame base. This is either FP or SP
60ff171acfSDerek Schuff   // after it has been replaced by a vreg
61ff171acfSDerek Schuff   unsigned FrameBaseVreg = -1U;
62ff171acfSDerek Schuff   // The local holding the frame base. This is either FP or SP
63ff171acfSDerek Schuff   // after WebAssemblyExplicitLocals
64ff171acfSDerek Schuff   unsigned FrameBaseLocal = -1U;
650d41b7b3SDerek Schuff 
661aaa481fSHeejin Ahn   // Function properties.
671aaa481fSHeejin Ahn   bool CFGStackified = false;
681aaa481fSHeejin Ahn 
6951fb5bf4SHeejin Ahn   // Catchpad unwind destination info for wasm EH.
7051fb5bf4SHeejin Ahn   WasmEHFuncInfo *WasmEHInfo = nullptr;
7151fb5bf4SHeejin Ahn 
7210e730a2SDan Gohman public:
WebAssemblyFunctionInfo(MachineFunction & MF_)73*cc5a1b3dSMatt Arsenault   explicit WebAssemblyFunctionInfo(MachineFunction &MF_)
74*cc5a1b3dSMatt Arsenault       : MF(&MF_), WasmEHInfo(MF_.getWasmEHFuncInfo()) {}
7510e730a2SDan Gohman   ~WebAssemblyFunctionInfo() override;
7651fb5bf4SHeejin Ahn 
77*cc5a1b3dSMatt Arsenault   MachineFunctionInfo *
78*cc5a1b3dSMatt Arsenault   clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
79*cc5a1b3dSMatt Arsenault         const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
80*cc5a1b3dSMatt Arsenault       const override;
81*cc5a1b3dSMatt Arsenault 
getMachineFunction()82*cc5a1b3dSMatt Arsenault   const MachineFunction &getMachineFunction() const { return *MF; }
8351fb5bf4SHeejin Ahn 
8452221d56SHeejin Ahn   void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI);
85e51c058eSDan Gohman 
addParam(MVT VT)86754cd11dSDan Gohman   void addParam(MVT VT) { Params.push_back(VT); }
getParams()87754cd11dSDan Gohman   const std::vector<MVT> &getParams() const { return Params; }
88754cd11dSDan Gohman 
addResult(MVT VT)892726b88cSDan Gohman   void addResult(MVT VT) { Results.push_back(VT); }
getResults()902726b88cSDan Gohman   const std::vector<MVT> &getResults() const { return Results; }
912726b88cSDan Gohman 
clearParamsAndResults()92f208f631SHeejin Ahn   void clearParamsAndResults() {
93f208f631SHeejin Ahn     Params.clear();
94f208f631SHeejin Ahn     Results.clear();
95f208f631SHeejin Ahn   }
96b8184827SDan Gohman 
setNumLocals(size_t NumLocals)97d934cb88SDan Gohman   void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
setLocal(size_t i,MVT VT)98d934cb88SDan Gohman   void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
addLocal(MVT VT)993acb187dSDan Gohman   void addLocal(MVT VT) { Locals.push_back(VT); }
getLocals()1003acb187dSDan Gohman   const std::vector<MVT> &getLocals() const { return Locals; }
1013acb187dSDan Gohman 
getVarargBufferVreg()10227501e20SDerek Schuff   unsigned getVarargBufferVreg() const {
10327501e20SDerek Schuff     assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
10427501e20SDerek Schuff     return VarargVreg;
10527501e20SDerek Schuff   }
setVarargBufferVreg(unsigned Reg)10627501e20SDerek Schuff   void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; }
10727501e20SDerek Schuff 
getBasePointerVreg()1080d41b7b3SDerek Schuff   unsigned getBasePointerVreg() const {
1090d41b7b3SDerek Schuff     assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set");
1100d41b7b3SDerek Schuff     return BasePtrVreg;
1110d41b7b3SDerek Schuff   }
setFrameBaseVreg(unsigned Reg)112ff171acfSDerek Schuff   void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; }
getFrameBaseVreg()113ff171acfSDerek Schuff   unsigned getFrameBaseVreg() const {
114ff171acfSDerek Schuff     assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set");
115ff171acfSDerek Schuff     return FrameBaseVreg;
116ff171acfSDerek Schuff   }
clearFrameBaseVreg()117d966bf83SDerek Schuff   void clearFrameBaseVreg() { FrameBaseVreg = -1U; }
118ff171acfSDerek Schuff   // Return true if the frame base physreg has been replaced by a virtual reg.
isFrameBaseVirtual()119ff171acfSDerek Schuff   bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; }
setFrameBaseLocal(unsigned Local)120ff171acfSDerek Schuff   void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; }
getFrameBaseLocal()121ff171acfSDerek Schuff   unsigned getFrameBaseLocal() const {
122ff171acfSDerek Schuff     assert(FrameBaseLocal != -1U && "Frame base local hasn't been set");
123ff171acfSDerek Schuff     return FrameBaseLocal;
124ff171acfSDerek Schuff   }
setBasePointerVreg(unsigned Reg)1250d41b7b3SDerek Schuff   void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; }
1260d41b7b3SDerek Schuff 
127058fce54SDan Gohman   static const unsigned UnusedReg = -1u;
128058fce54SDan Gohman 
stackifyVReg(MachineRegisterInfo & MRI,unsigned VReg)129c5d24009SMatt Arsenault   void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) {
130c5d24009SMatt Arsenault     assert(MRI.getUniqueVRegDef(VReg));
1312bea69bfSDaniel Sanders     auto I = Register::virtReg2Index(VReg);
13278c62966SWouter van Oortmerssen     if (I >= VRegStackified.size())
13378c62966SWouter van Oortmerssen       VRegStackified.resize(I + 1);
13478c62966SWouter van Oortmerssen     VRegStackified.set(I);
1351462faadSDan Gohman   }
unstackifyVReg(unsigned VReg)13661d5c76aSHeejin Ahn   void unstackifyVReg(unsigned VReg) {
13761d5c76aSHeejin Ahn     auto I = Register::virtReg2Index(VReg);
13861d5c76aSHeejin Ahn     if (I < VRegStackified.size())
13961d5c76aSHeejin Ahn       VRegStackified.reset(I);
14061d5c76aSHeejin Ahn   }
isVRegStackified(unsigned VReg)1411462faadSDan Gohman   bool isVRegStackified(unsigned VReg) const {
1422bea69bfSDaniel Sanders     auto I = Register::virtReg2Index(VReg);
14378c62966SWouter van Oortmerssen     if (I >= VRegStackified.size())
1441462faadSDan Gohman       return false;
14578c62966SWouter van Oortmerssen     return VRegStackified.test(I);
1461462faadSDan Gohman   }
1471462faadSDan Gohman 
148c5d24009SMatt Arsenault   void initWARegs(MachineRegisterInfo &MRI);
setWAReg(unsigned VReg,unsigned WAReg)149cf4748f1SDan Gohman   void setWAReg(unsigned VReg, unsigned WAReg) {
150058fce54SDan Gohman     assert(WAReg != UnusedReg);
1512bea69bfSDaniel Sanders     auto I = Register::virtReg2Index(VReg);
15278c62966SWouter van Oortmerssen     assert(I < WARegs.size());
15378c62966SWouter van Oortmerssen     WARegs[I] = WAReg;
154cf4748f1SDan Gohman   }
getWAReg(unsigned VReg)15578c62966SWouter van Oortmerssen   unsigned getWAReg(unsigned VReg) const {
1562bea69bfSDaniel Sanders     auto I = Register::virtReg2Index(VReg);
15778c62966SWouter van Oortmerssen     assert(I < WARegs.size());
15878c62966SWouter van Oortmerssen     return WARegs[I];
1599769debfSDerek Schuff   }
160b7c2400fSDan Gohman 
161b7c2400fSDan Gohman   // For a given stackified WAReg, return the id number to print with push/pop.
getWARegStackId(unsigned Reg)162b7c2400fSDan Gohman   static unsigned getWARegStackId(unsigned Reg) {
163b7c2400fSDan Gohman     assert(Reg & INT32_MIN);
164b7c2400fSDan Gohman     return Reg & INT32_MAX;
165b7c2400fSDan Gohman   }
1661aaa481fSHeejin Ahn 
isCFGStackified()1671aaa481fSHeejin Ahn   bool isCFGStackified() const { return CFGStackified; }
1681aaa481fSHeejin Ahn   void setCFGStackified(bool Value = true) { CFGStackified = Value; }
16951fb5bf4SHeejin Ahn 
getWasmEHFuncInfo()17051fb5bf4SHeejin Ahn   WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; }
setWasmEHFuncInfo(WasmEHFuncInfo * Info)17151fb5bf4SHeejin Ahn   void setWasmEHFuncInfo(WasmEHFuncInfo *Info) { WasmEHInfo = Info; }
17210e730a2SDan Gohman };
17310e730a2SDan Gohman 
174864767abSPaulo Matos void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
175864767abSPaulo Matos                           LLVMContext &Ctx, const DataLayout &DL, Type *Ty,
176864767abSPaulo Matos                           SmallVectorImpl<MVT> &ValueVTs);
177864767abSPaulo Matos 
17818c56a07SHeejin Ahn void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
179f208f631SHeejin Ahn                           SmallVectorImpl<MVT> &ValueVTs);
1802726b88cSDan Gohman 
18177a7a380SDerek Schuff // Compute the signature for a given FunctionType (Ty). Note that it's not the
18208670d43SYuta Saito // signature for ContextFunc (ContextFunc is just used to get varous context)
18308670d43SYuta Saito void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc,
18408670d43SYuta Saito                          const Function &ContextFunc, const TargetMachine &TM,
18508670d43SYuta Saito                          SmallVectorImpl<MVT> &Params,
1862726b88cSDan Gohman                          SmallVectorImpl<MVT> &Results);
1872726b88cSDan Gohman 
18818c56a07SHeejin Ahn void valTypesFromMVTs(const ArrayRef<MVT> &In,
18949482f82SWouter van Oortmerssen                       SmallVectorImpl<wasm::ValType> &Out);
19049482f82SWouter van Oortmerssen 
19177a7a380SDerek Schuff std::unique_ptr<wasm::WasmSignature>
19218c56a07SHeejin Ahn signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
19377a7a380SDerek Schuff                   const SmallVectorImpl<MVT> &Params);
19477a7a380SDerek Schuff 
19552221d56SHeejin Ahn namespace yaml {
19652221d56SHeejin Ahn 
19751fb5bf4SHeejin Ahn using BBNumberMap = DenseMap<int, int>;
19851fb5bf4SHeejin Ahn 
19952221d56SHeejin Ahn struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo {
200b3e88ccbSHeejin Ahn   std::vector<FlowStringValue> Params;
201b3e88ccbSHeejin Ahn   std::vector<FlowStringValue> Results;
2021aaa481fSHeejin Ahn   bool CFGStackified = false;
20351fb5bf4SHeejin Ahn   // The same as WasmEHFuncInfo's SrcToUnwindDest, but stored in the mapping of
20451fb5bf4SHeejin Ahn   // BB numbers
20551fb5bf4SHeejin Ahn   BBNumberMap SrcToUnwindDest;
2061aaa481fSHeejin Ahn 
20752221d56SHeejin Ahn   WebAssemblyFunctionInfo() = default;
20852221d56SHeejin Ahn   WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI);
20952221d56SHeejin Ahn 
21052221d56SHeejin Ahn   void mappingImpl(yaml::IO &YamlIO) override;
21152221d56SHeejin Ahn   ~WebAssemblyFunctionInfo() = default;
21252221d56SHeejin Ahn };
21352221d56SHeejin Ahn 
21452221d56SHeejin Ahn template <> struct MappingTraits<WebAssemblyFunctionInfo> {
2151aaa481fSHeejin Ahn   static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) {
216b3e88ccbSHeejin Ahn     YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>());
217b3e88ccbSHeejin Ahn     YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>());
2181aaa481fSHeejin Ahn     YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false);
21951fb5bf4SHeejin Ahn     YamlIO.mapOptional("wasmEHFuncInfo", MFI.SrcToUnwindDest);
22051fb5bf4SHeejin Ahn   }
22151fb5bf4SHeejin Ahn };
22251fb5bf4SHeejin Ahn 
22351fb5bf4SHeejin Ahn template <> struct CustomMappingTraits<BBNumberMap> {
22451fb5bf4SHeejin Ahn   static void inputOne(IO &YamlIO, StringRef Key,
22551fb5bf4SHeejin Ahn                        BBNumberMap &SrcToUnwindDest) {
22651fb5bf4SHeejin Ahn     YamlIO.mapRequired(Key.str().c_str(),
22751fb5bf4SHeejin Ahn                        SrcToUnwindDest[std::atoi(Key.str().c_str())]);
22851fb5bf4SHeejin Ahn   }
22951fb5bf4SHeejin Ahn 
23051fb5bf4SHeejin Ahn   static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) {
23151fb5bf4SHeejin Ahn     for (auto KV : SrcToUnwindDest)
23251fb5bf4SHeejin Ahn       YamlIO.mapRequired(std::to_string(KV.first).c_str(), KV.second);
2331aaa481fSHeejin Ahn   }
23452221d56SHeejin Ahn };
23552221d56SHeejin Ahn 
23652221d56SHeejin Ahn } // end namespace yaml
23752221d56SHeejin Ahn 
23810e730a2SDan Gohman } // end namespace llvm
23910e730a2SDan Gohman 
24010e730a2SDan Gohman #endif
241