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 MachineFunction &MF; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric std::vector<MVT> Params; 360b57cec5SDimitry Andric std::vector<MVT> Results; 370b57cec5SDimitry Andric std::vector<MVT> Locals; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric /// A mapping from CodeGen vreg index to WebAssembly register number. 400b57cec5SDimitry Andric std::vector<unsigned> WARegs; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric /// A mapping from CodeGen vreg index to a boolean value indicating whether 430b57cec5SDimitry Andric /// the given register is considered to be "stackified", meaning it has been 440b57cec5SDimitry Andric /// determined or made to meet the stack requirements: 450b57cec5SDimitry Andric /// - single use (per path) 460b57cec5SDimitry Andric /// - single def (per path) 470b57cec5SDimitry Andric /// - defined and used in LIFO order with other stack registers 480b57cec5SDimitry Andric BitVector VRegStackified; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // A virtual register holding the pointer to the vararg buffer for vararg 510b57cec5SDimitry Andric // functions. It is created and set in TLI::LowerFormalArguments and read by 520b57cec5SDimitry Andric // TLI::LowerVASTART 530b57cec5SDimitry Andric unsigned VarargVreg = -1U; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric // A virtual register holding the base pointer for functions that have 560b57cec5SDimitry Andric // overaligned values on the user stack. 570b57cec5SDimitry Andric unsigned BasePtrVreg = -1U; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Function properties. 600b57cec5SDimitry Andric bool CFGStackified = false; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric public: 630b57cec5SDimitry Andric explicit WebAssemblyFunctionInfo(MachineFunction &MF) : MF(MF) {} 640b57cec5SDimitry Andric ~WebAssemblyFunctionInfo() override; 650b57cec5SDimitry Andric void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric void addParam(MVT VT) { Params.push_back(VT); } 680b57cec5SDimitry Andric const std::vector<MVT> &getParams() const { return Params; } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric void addResult(MVT VT) { Results.push_back(VT); } 710b57cec5SDimitry Andric const std::vector<MVT> &getResults() const { return Results; } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric void clearParamsAndResults() { 740b57cec5SDimitry Andric Params.clear(); 750b57cec5SDimitry Andric Results.clear(); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); } 790b57cec5SDimitry Andric void setLocal(size_t i, MVT VT) { Locals[i] = VT; } 800b57cec5SDimitry Andric void addLocal(MVT VT) { Locals.push_back(VT); } 810b57cec5SDimitry Andric const std::vector<MVT> &getLocals() const { return Locals; } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric unsigned getVarargBufferVreg() const { 840b57cec5SDimitry Andric assert(VarargVreg != -1U && "Vararg vreg hasn't been set"); 850b57cec5SDimitry Andric return VarargVreg; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric unsigned getBasePointerVreg() const { 900b57cec5SDimitry Andric assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set"); 910b57cec5SDimitry Andric return BasePtrVreg; 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric static const unsigned UnusedReg = -1u; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric void stackifyVReg(unsigned VReg) { 980b57cec5SDimitry Andric assert(MF.getRegInfo().getUniqueVRegDef(VReg)); 99*8bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1000b57cec5SDimitry Andric if (I >= VRegStackified.size()) 1010b57cec5SDimitry Andric VRegStackified.resize(I + 1); 1020b57cec5SDimitry Andric VRegStackified.set(I); 1030b57cec5SDimitry Andric } 104*8bcb0991SDimitry Andric void unstackifyVReg(unsigned VReg) { 105*8bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 106*8bcb0991SDimitry Andric if (I < VRegStackified.size()) 107*8bcb0991SDimitry Andric VRegStackified.reset(I); 108*8bcb0991SDimitry Andric } 1090b57cec5SDimitry Andric bool isVRegStackified(unsigned VReg) const { 110*8bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1110b57cec5SDimitry Andric if (I >= VRegStackified.size()) 1120b57cec5SDimitry Andric return false; 1130b57cec5SDimitry Andric return VRegStackified.test(I); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric void initWARegs(); 1170b57cec5SDimitry Andric void setWAReg(unsigned VReg, unsigned WAReg) { 1180b57cec5SDimitry Andric assert(WAReg != UnusedReg); 119*8bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1200b57cec5SDimitry Andric assert(I < WARegs.size()); 1210b57cec5SDimitry Andric WARegs[I] = WAReg; 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric unsigned getWAReg(unsigned VReg) const { 124*8bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1250b57cec5SDimitry Andric assert(I < WARegs.size()); 1260b57cec5SDimitry Andric return WARegs[I]; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric // For a given stackified WAReg, return the id number to print with push/pop. 1300b57cec5SDimitry Andric static unsigned getWARegStackId(unsigned Reg) { 1310b57cec5SDimitry Andric assert(Reg & INT32_MIN); 1320b57cec5SDimitry Andric return Reg & INT32_MAX; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric bool isCFGStackified() const { return CFGStackified; } 1360b57cec5SDimitry Andric void setCFGStackified(bool Value = true) { CFGStackified = Value; } 1370b57cec5SDimitry Andric }; 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, 1400b57cec5SDimitry Andric SmallVectorImpl<MVT> &ValueVTs); 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // Compute the signature for a given FunctionType (Ty). Note that it's not the 1430b57cec5SDimitry Andric // signature for F (F is just used to get varous context) 1440b57cec5SDimitry Andric void computeSignatureVTs(const FunctionType *Ty, const Function &F, 1450b57cec5SDimitry Andric const TargetMachine &TM, SmallVectorImpl<MVT> &Params, 1460b57cec5SDimitry Andric SmallVectorImpl<MVT> &Results); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric void valTypesFromMVTs(const ArrayRef<MVT> &In, 1490b57cec5SDimitry Andric SmallVectorImpl<wasm::ValType> &Out); 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric std::unique_ptr<wasm::WasmSignature> 1520b57cec5SDimitry Andric signatureFromMVTs(const SmallVectorImpl<MVT> &Results, 1530b57cec5SDimitry Andric const SmallVectorImpl<MVT> &Params); 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric namespace yaml { 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo { 1580b57cec5SDimitry Andric bool CFGStackified = false; 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric WebAssemblyFunctionInfo() = default; 1610b57cec5SDimitry Andric WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI); 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric void mappingImpl(yaml::IO &YamlIO) override; 1640b57cec5SDimitry Andric ~WebAssemblyFunctionInfo() = default; 1650b57cec5SDimitry Andric }; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric template <> struct MappingTraits<WebAssemblyFunctionInfo> { 1680b57cec5SDimitry Andric static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) { 1690b57cec5SDimitry Andric YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric }; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric } // end namespace yaml 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric } // end namespace llvm 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric #endif 178