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