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/BinaryFormat/Wasm.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCSymbolWasm.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric namespace yaml { 270b57cec5SDimitry Andric struct WebAssemblyFunctionInfo; 280b57cec5SDimitry Andric } 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric /// This class is derived from MachineFunctionInfo and contains private 310b57cec5SDimitry Andric /// WebAssembly-specific information for each MachineFunction. 320b57cec5SDimitry Andric class WebAssemblyFunctionInfo final : public MachineFunctionInfo { 330b57cec5SDimitry Andric std::vector<MVT> Params; 340b57cec5SDimitry Andric std::vector<MVT> Results; 350b57cec5SDimitry Andric std::vector<MVT> Locals; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric /// A mapping from CodeGen vreg index to WebAssembly register number. 380b57cec5SDimitry Andric std::vector<unsigned> WARegs; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric /// A mapping from CodeGen vreg index to a boolean value indicating whether 410b57cec5SDimitry Andric /// the given register is considered to be "stackified", meaning it has been 420b57cec5SDimitry Andric /// determined or made to meet the stack requirements: 430b57cec5SDimitry Andric /// - single use (per path) 440b57cec5SDimitry Andric /// - single def (per path) 450b57cec5SDimitry Andric /// - defined and used in LIFO order with other stack registers 460b57cec5SDimitry Andric BitVector VRegStackified; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric // A virtual register holding the pointer to the vararg buffer for vararg 490b57cec5SDimitry Andric // functions. It is created and set in TLI::LowerFormalArguments and read by 500b57cec5SDimitry Andric // TLI::LowerVASTART 510b57cec5SDimitry Andric unsigned VarargVreg = -1U; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric // A virtual register holding the base pointer for functions that have 540b57cec5SDimitry Andric // overaligned values on the user stack. 550b57cec5SDimitry Andric unsigned BasePtrVreg = -1U; 56*5ffd83dbSDimitry Andric // A virtual register holding the frame base. This is either FP or SP 57*5ffd83dbSDimitry Andric // after it has been replaced by a vreg 58*5ffd83dbSDimitry Andric unsigned FrameBaseVreg = -1U; 59*5ffd83dbSDimitry Andric // The local holding the frame base. This is either FP or SP 60*5ffd83dbSDimitry Andric // after WebAssemblyExplicitLocals 61*5ffd83dbSDimitry Andric unsigned FrameBaseLocal = -1U; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // Function properties. 640b57cec5SDimitry Andric bool CFGStackified = false; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric public: 67*5ffd83dbSDimitry Andric explicit WebAssemblyFunctionInfo(MachineFunction &MF) {} 680b57cec5SDimitry Andric ~WebAssemblyFunctionInfo() override; 690b57cec5SDimitry Andric void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric void addParam(MVT VT) { Params.push_back(VT); } 720b57cec5SDimitry Andric const std::vector<MVT> &getParams() const { return Params; } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric void addResult(MVT VT) { Results.push_back(VT); } 750b57cec5SDimitry Andric const std::vector<MVT> &getResults() const { return Results; } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric void clearParamsAndResults() { 780b57cec5SDimitry Andric Params.clear(); 790b57cec5SDimitry Andric Results.clear(); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); } 830b57cec5SDimitry Andric void setLocal(size_t i, MVT VT) { Locals[i] = VT; } 840b57cec5SDimitry Andric void addLocal(MVT VT) { Locals.push_back(VT); } 850b57cec5SDimitry Andric const std::vector<MVT> &getLocals() const { return Locals; } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric unsigned getVarargBufferVreg() const { 880b57cec5SDimitry Andric assert(VarargVreg != -1U && "Vararg vreg hasn't been set"); 890b57cec5SDimitry Andric return VarargVreg; 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric unsigned getBasePointerVreg() const { 940b57cec5SDimitry Andric assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set"); 950b57cec5SDimitry Andric return BasePtrVreg; 960b57cec5SDimitry Andric } 97*5ffd83dbSDimitry Andric void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; } 98*5ffd83dbSDimitry Andric unsigned getFrameBaseVreg() const { 99*5ffd83dbSDimitry Andric assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set"); 100*5ffd83dbSDimitry Andric return FrameBaseVreg; 101*5ffd83dbSDimitry Andric } 102*5ffd83dbSDimitry Andric void clearFrameBaseVreg() { FrameBaseVreg = -1U; } 103*5ffd83dbSDimitry Andric // Return true if the frame base physreg has been replaced by a virtual reg. 104*5ffd83dbSDimitry Andric bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; } 105*5ffd83dbSDimitry Andric void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; } 106*5ffd83dbSDimitry Andric unsigned getFrameBaseLocal() const { 107*5ffd83dbSDimitry Andric assert(FrameBaseLocal != -1U && "Frame base local hasn't been set"); 108*5ffd83dbSDimitry Andric return FrameBaseLocal; 109*5ffd83dbSDimitry Andric } 1100b57cec5SDimitry Andric void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric static const unsigned UnusedReg = -1u; 1130b57cec5SDimitry Andric 114*5ffd83dbSDimitry Andric void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) { 115*5ffd83dbSDimitry Andric assert(MRI.getUniqueVRegDef(VReg)); 1168bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1170b57cec5SDimitry Andric if (I >= VRegStackified.size()) 1180b57cec5SDimitry Andric VRegStackified.resize(I + 1); 1190b57cec5SDimitry Andric VRegStackified.set(I); 1200b57cec5SDimitry Andric } 1218bcb0991SDimitry Andric void unstackifyVReg(unsigned VReg) { 1228bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1238bcb0991SDimitry Andric if (I < VRegStackified.size()) 1248bcb0991SDimitry Andric VRegStackified.reset(I); 1258bcb0991SDimitry Andric } 1260b57cec5SDimitry Andric bool isVRegStackified(unsigned VReg) const { 1278bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1280b57cec5SDimitry Andric if (I >= VRegStackified.size()) 1290b57cec5SDimitry Andric return false; 1300b57cec5SDimitry Andric return VRegStackified.test(I); 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric 133*5ffd83dbSDimitry Andric void initWARegs(MachineRegisterInfo &MRI); 1340b57cec5SDimitry Andric void setWAReg(unsigned VReg, unsigned WAReg) { 1350b57cec5SDimitry Andric assert(WAReg != UnusedReg); 1368bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1370b57cec5SDimitry Andric assert(I < WARegs.size()); 1380b57cec5SDimitry Andric WARegs[I] = WAReg; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric unsigned getWAReg(unsigned VReg) const { 1418bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1420b57cec5SDimitry Andric assert(I < WARegs.size()); 1430b57cec5SDimitry Andric return WARegs[I]; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric // For a given stackified WAReg, return the id number to print with push/pop. 1470b57cec5SDimitry Andric static unsigned getWARegStackId(unsigned Reg) { 1480b57cec5SDimitry Andric assert(Reg & INT32_MIN); 1490b57cec5SDimitry Andric return Reg & INT32_MAX; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric bool isCFGStackified() const { return CFGStackified; } 1530b57cec5SDimitry Andric void setCFGStackified(bool Value = true) { CFGStackified = Value; } 1540b57cec5SDimitry Andric }; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, 1570b57cec5SDimitry Andric SmallVectorImpl<MVT> &ValueVTs); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric // Compute the signature for a given FunctionType (Ty). Note that it's not the 160*5ffd83dbSDimitry Andric // signature for ContextFunc (ContextFunc is just used to get varous context) 161*5ffd83dbSDimitry Andric void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, 162*5ffd83dbSDimitry Andric const Function &ContextFunc, const TargetMachine &TM, 163*5ffd83dbSDimitry Andric SmallVectorImpl<MVT> &Params, 1640b57cec5SDimitry Andric SmallVectorImpl<MVT> &Results); 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric void valTypesFromMVTs(const ArrayRef<MVT> &In, 1670b57cec5SDimitry Andric SmallVectorImpl<wasm::ValType> &Out); 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric std::unique_ptr<wasm::WasmSignature> 1700b57cec5SDimitry Andric signatureFromMVTs(const SmallVectorImpl<MVT> &Results, 1710b57cec5SDimitry Andric const SmallVectorImpl<MVT> &Params); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric namespace yaml { 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo { 1760b57cec5SDimitry Andric bool CFGStackified = false; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric WebAssemblyFunctionInfo() = default; 1790b57cec5SDimitry Andric WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI); 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric void mappingImpl(yaml::IO &YamlIO) override; 1820b57cec5SDimitry Andric ~WebAssemblyFunctionInfo() = default; 1830b57cec5SDimitry Andric }; 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric template <> struct MappingTraits<WebAssemblyFunctionInfo> { 1860b57cec5SDimitry Andric static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) { 1870b57cec5SDimitry Andric YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric }; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric } // end namespace yaml 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric } // end namespace llvm 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric #endif 196