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 { 245f757f3fSDimitry Andric class WebAssemblyTargetLowering; 250b57cec5SDimitry Andric 26fe6060f1SDimitry Andric struct WasmEHFuncInfo; 27fe6060f1SDimitry Andric 280b57cec5SDimitry Andric namespace yaml { 290b57cec5SDimitry Andric struct WebAssemblyFunctionInfo; 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric /// This class is derived from MachineFunctionInfo and contains private 330b57cec5SDimitry Andric /// WebAssembly-specific information for each MachineFunction. 340b57cec5SDimitry Andric class WebAssemblyFunctionInfo final : public MachineFunctionInfo { 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; 585ffd83dbSDimitry Andric // A virtual register holding the frame base. This is either FP or SP 595ffd83dbSDimitry Andric // after it has been replaced by a vreg 605ffd83dbSDimitry Andric unsigned FrameBaseVreg = -1U; 615ffd83dbSDimitry Andric // The local holding the frame base. This is either FP or SP 625ffd83dbSDimitry Andric // after WebAssemblyExplicitLocals 635ffd83dbSDimitry Andric unsigned FrameBaseLocal = -1U; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // Function properties. 660b57cec5SDimitry Andric bool CFGStackified = false; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric public: 69bdd1243dSDimitry Andric explicit WebAssemblyFunctionInfo(const Function &F, 70bdd1243dSDimitry Andric const TargetSubtargetInfo *STI) {} 710b57cec5SDimitry Andric ~WebAssemblyFunctionInfo() override; 72fe6060f1SDimitry Andric 7381ad6265SDimitry Andric MachineFunctionInfo * 7481ad6265SDimitry Andric clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, 7581ad6265SDimitry Andric const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) 7681ad6265SDimitry Andric const override; 7781ad6265SDimitry Andric 78bdd1243dSDimitry Andric void initializeBaseYamlFields(MachineFunction &MF, 79bdd1243dSDimitry Andric 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 1225ffd83dbSDimitry Andric void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) { 1235ffd83dbSDimitry Andric assert(MRI.getUniqueVRegDef(VReg)); 1248bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1250b57cec5SDimitry Andric if (I >= VRegStackified.size()) 1260b57cec5SDimitry Andric VRegStackified.resize(I + 1); 1270b57cec5SDimitry Andric VRegStackified.set(I); 1280b57cec5SDimitry Andric } 1298bcb0991SDimitry Andric void unstackifyVReg(unsigned VReg) { 1308bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1318bcb0991SDimitry Andric if (I < VRegStackified.size()) 1328bcb0991SDimitry Andric VRegStackified.reset(I); 1338bcb0991SDimitry Andric } 1340b57cec5SDimitry Andric bool isVRegStackified(unsigned VReg) const { 1358bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1360b57cec5SDimitry Andric if (I >= VRegStackified.size()) 1370b57cec5SDimitry Andric return false; 1380b57cec5SDimitry Andric return VRegStackified.test(I); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1415ffd83dbSDimitry Andric void initWARegs(MachineRegisterInfo &MRI); 1420b57cec5SDimitry Andric void setWAReg(unsigned VReg, unsigned WAReg) { 1435f757f3fSDimitry Andric assert(WAReg != WebAssembly::UnusedReg); 1448bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1450b57cec5SDimitry Andric assert(I < WARegs.size()); 1460b57cec5SDimitry Andric WARegs[I] = WAReg; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric unsigned getWAReg(unsigned VReg) const { 1498bcb0991SDimitry Andric auto I = Register::virtReg2Index(VReg); 1500b57cec5SDimitry Andric assert(I < WARegs.size()); 1510b57cec5SDimitry Andric return WARegs[I]; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric bool isCFGStackified() const { return CFGStackified; } 1550b57cec5SDimitry Andric void setCFGStackified(bool Value = true) { CFGStackified = Value; } 1560b57cec5SDimitry Andric }; 1570b57cec5SDimitry Andric 1581fd87a68SDimitry Andric void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI, 1591fd87a68SDimitry Andric LLVMContext &Ctx, const DataLayout &DL, Type *Ty, 1601fd87a68SDimitry Andric SmallVectorImpl<MVT> &ValueVTs); 1611fd87a68SDimitry Andric 1620b57cec5SDimitry Andric void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, 1630b57cec5SDimitry Andric SmallVectorImpl<MVT> &ValueVTs); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // Compute the signature for a given FunctionType (Ty). Note that it's not the 1665ffd83dbSDimitry Andric // signature for ContextFunc (ContextFunc is just used to get varous context) 1675ffd83dbSDimitry Andric void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, 1685ffd83dbSDimitry Andric const Function &ContextFunc, const TargetMachine &TM, 1695ffd83dbSDimitry Andric SmallVectorImpl<MVT> &Params, 1700b57cec5SDimitry Andric SmallVectorImpl<MVT> &Results); 1710b57cec5SDimitry Andric 172*0fca6ea1SDimitry Andric void valTypesFromMVTs(ArrayRef<MVT> In, SmallVectorImpl<wasm::ValType> &Out); 1730b57cec5SDimitry Andric 174*0fca6ea1SDimitry Andric wasm::WasmSignature *signatureFromMVTs(MCContext &Ctx, 175*0fca6ea1SDimitry Andric const SmallVectorImpl<MVT> &Results, 1760b57cec5SDimitry Andric const SmallVectorImpl<MVT> &Params); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric namespace yaml { 1790b57cec5SDimitry Andric 180fe6060f1SDimitry Andric using BBNumberMap = DenseMap<int, int>; 181fe6060f1SDimitry Andric 1820b57cec5SDimitry Andric struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo { 183fe6060f1SDimitry Andric std::vector<FlowStringValue> Params; 184fe6060f1SDimitry Andric std::vector<FlowStringValue> Results; 1850b57cec5SDimitry Andric bool CFGStackified = false; 186fe6060f1SDimitry Andric // The same as WasmEHFuncInfo's SrcToUnwindDest, but stored in the mapping of 187fe6060f1SDimitry Andric // BB numbers 188fe6060f1SDimitry Andric BBNumberMap SrcToUnwindDest; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric WebAssemblyFunctionInfo() = default; 191bdd1243dSDimitry Andric WebAssemblyFunctionInfo(const llvm::MachineFunction &MF, 192bdd1243dSDimitry Andric const llvm::WebAssemblyFunctionInfo &MFI); 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric void mappingImpl(yaml::IO &YamlIO) override; 1950b57cec5SDimitry Andric ~WebAssemblyFunctionInfo() = default; 1960b57cec5SDimitry Andric }; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric template <> struct MappingTraits<WebAssemblyFunctionInfo> { 1990b57cec5SDimitry Andric static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) { 200fe6060f1SDimitry Andric YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>()); 201fe6060f1SDimitry Andric YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>()); 2020b57cec5SDimitry Andric YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false); 203fe6060f1SDimitry Andric YamlIO.mapOptional("wasmEHFuncInfo", MFI.SrcToUnwindDest); 204fe6060f1SDimitry Andric } 205fe6060f1SDimitry Andric }; 206fe6060f1SDimitry Andric 207fe6060f1SDimitry Andric template <> struct CustomMappingTraits<BBNumberMap> { 208fe6060f1SDimitry Andric static void inputOne(IO &YamlIO, StringRef Key, 209fe6060f1SDimitry Andric BBNumberMap &SrcToUnwindDest) { 210fe6060f1SDimitry Andric YamlIO.mapRequired(Key.str().c_str(), 211fe6060f1SDimitry Andric SrcToUnwindDest[std::atoi(Key.str().c_str())]); 212fe6060f1SDimitry Andric } 213fe6060f1SDimitry Andric 214fe6060f1SDimitry Andric static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) { 215fe6060f1SDimitry Andric for (auto KV : SrcToUnwindDest) 216fe6060f1SDimitry Andric YamlIO.mapRequired(std::to_string(KV.first).c_str(), KV.second); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric }; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric } // end namespace yaml 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric } // end namespace llvm 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric #endif 225