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 25*fe6060f1SDimitry Andric struct WasmEHFuncInfo; 26*fe6060f1SDimitry 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*fe6060f1SDimitry Andric const MachineFunction &MF; 35*fe6060f1SDimitry 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 69*fe6060f1SDimitry Andric // Catchpad unwind destination info for wasm EH. 70*fe6060f1SDimitry Andric WasmEHFuncInfo *WasmEHInfo = nullptr; 71*fe6060f1SDimitry Andric 720b57cec5SDimitry Andric public: 73*fe6060f1SDimitry Andric explicit WebAssemblyFunctionInfo(MachineFunction &MF) 74*fe6060f1SDimitry Andric : MF(MF), WasmEHInfo(MF.getWasmEHFuncInfo()) {} 750b57cec5SDimitry Andric ~WebAssemblyFunctionInfo() override; 76*fe6060f1SDimitry Andric 77*fe6060f1SDimitry Andric const MachineFunction &getMachineFunction() const { return MF; } 78*fe6060f1SDimitry Andric 790b57cec5SDimitry Andric void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI); 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric void addParam(MVT VT) { Params.push_back(VT); } 820b57cec5SDimitry Andric const std::vector<MVT> &getParams() const { return Params; } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric void addResult(MVT VT) { Results.push_back(VT); } 850b57cec5SDimitry Andric const std::vector<MVT> &getResults() const { return Results; } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric void clearParamsAndResults() { 880b57cec5SDimitry Andric Params.clear(); 890b57cec5SDimitry Andric Results.clear(); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); } 930b57cec5SDimitry Andric void setLocal(size_t i, MVT VT) { Locals[i] = VT; } 940b57cec5SDimitry Andric void addLocal(MVT VT) { Locals.push_back(VT); } 950b57cec5SDimitry Andric const std::vector<MVT> &getLocals() const { return Locals; } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric unsigned getVarargBufferVreg() const { 980b57cec5SDimitry Andric assert(VarargVreg != -1U && "Vararg vreg hasn't been set"); 990b57cec5SDimitry Andric return VarargVreg; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric unsigned getBasePointerVreg() const { 1040b57cec5SDimitry Andric assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set"); 1050b57cec5SDimitry Andric return BasePtrVreg; 1060b57cec5SDimitry Andric } 1075ffd83dbSDimitry Andric void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; } 1085ffd83dbSDimitry Andric unsigned getFrameBaseVreg() const { 1095ffd83dbSDimitry Andric assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set"); 1105ffd83dbSDimitry Andric return FrameBaseVreg; 1115ffd83dbSDimitry Andric } 1125ffd83dbSDimitry Andric void clearFrameBaseVreg() { FrameBaseVreg = -1U; } 1135ffd83dbSDimitry Andric // Return true if the frame base physreg has been replaced by a virtual reg. 1145ffd83dbSDimitry Andric bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; } 1155ffd83dbSDimitry Andric void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; } 1165ffd83dbSDimitry Andric unsigned getFrameBaseLocal() const { 1175ffd83dbSDimitry Andric assert(FrameBaseLocal != -1U && "Frame base local hasn't been set"); 1185ffd83dbSDimitry Andric return FrameBaseLocal; 1195ffd83dbSDimitry Andric } 1200b57cec5SDimitry Andric void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric static const unsigned UnusedReg = -1u; 1230b57cec5SDimitry Andric 1245ffd83dbSDimitry Andric void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) { 1255ffd83dbSDimitry Andric assert(MRI.getUniqueVRegDef(VReg)); 1268bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1270b57cec5SDimitry Andric if (I >= VRegStackified.size()) 1280b57cec5SDimitry Andric VRegStackified.resize(I + 1); 1290b57cec5SDimitry Andric VRegStackified.set(I); 1300b57cec5SDimitry Andric } 1318bcb0991SDimitry Andric void unstackifyVReg(unsigned VReg) { 1328bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1338bcb0991SDimitry Andric if (I < VRegStackified.size()) 1348bcb0991SDimitry Andric VRegStackified.reset(I); 1358bcb0991SDimitry Andric } 1360b57cec5SDimitry Andric bool isVRegStackified(unsigned VReg) const { 1378bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1380b57cec5SDimitry Andric if (I >= VRegStackified.size()) 1390b57cec5SDimitry Andric return false; 1400b57cec5SDimitry Andric return VRegStackified.test(I); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1435ffd83dbSDimitry Andric void initWARegs(MachineRegisterInfo &MRI); 1440b57cec5SDimitry Andric void setWAReg(unsigned VReg, unsigned WAReg) { 1450b57cec5SDimitry Andric assert(WAReg != UnusedReg); 1468bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1470b57cec5SDimitry Andric assert(I < WARegs.size()); 1480b57cec5SDimitry Andric WARegs[I] = WAReg; 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric unsigned getWAReg(unsigned VReg) const { 1518bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1520b57cec5SDimitry Andric assert(I < WARegs.size()); 1530b57cec5SDimitry Andric return WARegs[I]; 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric // For a given stackified WAReg, return the id number to print with push/pop. 1570b57cec5SDimitry Andric static unsigned getWARegStackId(unsigned Reg) { 1580b57cec5SDimitry Andric assert(Reg & INT32_MIN); 1590b57cec5SDimitry Andric return Reg & INT32_MAX; 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric bool isCFGStackified() const { return CFGStackified; } 1630b57cec5SDimitry Andric void setCFGStackified(bool Value = true) { CFGStackified = Value; } 164*fe6060f1SDimitry Andric 165*fe6060f1SDimitry Andric WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; } 166*fe6060f1SDimitry Andric void setWasmEHFuncInfo(WasmEHFuncInfo *Info) { WasmEHInfo = Info; } 1670b57cec5SDimitry Andric }; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, 1700b57cec5SDimitry Andric SmallVectorImpl<MVT> &ValueVTs); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric // Compute the signature for a given FunctionType (Ty). Note that it's not the 1735ffd83dbSDimitry Andric // signature for ContextFunc (ContextFunc is just used to get varous context) 1745ffd83dbSDimitry Andric void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, 1755ffd83dbSDimitry Andric const Function &ContextFunc, const TargetMachine &TM, 1765ffd83dbSDimitry Andric SmallVectorImpl<MVT> &Params, 1770b57cec5SDimitry Andric SmallVectorImpl<MVT> &Results); 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric void valTypesFromMVTs(const ArrayRef<MVT> &In, 1800b57cec5SDimitry Andric SmallVectorImpl<wasm::ValType> &Out); 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric std::unique_ptr<wasm::WasmSignature> 1830b57cec5SDimitry Andric signatureFromMVTs(const SmallVectorImpl<MVT> &Results, 1840b57cec5SDimitry Andric const SmallVectorImpl<MVT> &Params); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric namespace yaml { 1870b57cec5SDimitry Andric 188*fe6060f1SDimitry Andric using BBNumberMap = DenseMap<int, int>; 189*fe6060f1SDimitry Andric 1900b57cec5SDimitry Andric struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo { 191*fe6060f1SDimitry Andric std::vector<FlowStringValue> Params; 192*fe6060f1SDimitry Andric std::vector<FlowStringValue> Results; 1930b57cec5SDimitry Andric bool CFGStackified = false; 194*fe6060f1SDimitry Andric // The same as WasmEHFuncInfo's SrcToUnwindDest, but stored in the mapping of 195*fe6060f1SDimitry Andric // BB numbers 196*fe6060f1SDimitry Andric BBNumberMap SrcToUnwindDest; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric WebAssemblyFunctionInfo() = default; 1990b57cec5SDimitry Andric WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI); 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric void mappingImpl(yaml::IO &YamlIO) override; 2020b57cec5SDimitry Andric ~WebAssemblyFunctionInfo() = default; 2030b57cec5SDimitry Andric }; 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric template <> struct MappingTraits<WebAssemblyFunctionInfo> { 2060b57cec5SDimitry Andric static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) { 207*fe6060f1SDimitry Andric YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>()); 208*fe6060f1SDimitry Andric YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>()); 2090b57cec5SDimitry Andric YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false); 210*fe6060f1SDimitry Andric YamlIO.mapOptional("wasmEHFuncInfo", MFI.SrcToUnwindDest); 211*fe6060f1SDimitry Andric } 212*fe6060f1SDimitry Andric }; 213*fe6060f1SDimitry Andric 214*fe6060f1SDimitry Andric template <> struct CustomMappingTraits<BBNumberMap> { 215*fe6060f1SDimitry Andric static void inputOne(IO &YamlIO, StringRef Key, 216*fe6060f1SDimitry Andric BBNumberMap &SrcToUnwindDest) { 217*fe6060f1SDimitry Andric YamlIO.mapRequired(Key.str().c_str(), 218*fe6060f1SDimitry Andric SrcToUnwindDest[std::atoi(Key.str().c_str())]); 219*fe6060f1SDimitry Andric } 220*fe6060f1SDimitry Andric 221*fe6060f1SDimitry Andric static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) { 222*fe6060f1SDimitry Andric for (auto KV : SrcToUnwindDest) 223*fe6060f1SDimitry Andric YamlIO.mapRequired(std::to_string(KV.first).c_str(), KV.second); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric }; 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric } // end namespace yaml 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric } // end namespace llvm 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric #endif 232