1 // WebAssemblyMachineFunctionInfo.h-WebAssembly machine function info-*- C++ -*- 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file declares WebAssembly-specific per-machine-function 11 /// information. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H 16 #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H 17 18 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 19 #include "llvm/CodeGen/MIRYamlMapping.h" 20 #include "llvm/CodeGen/MachineRegisterInfo.h" 21 #include "llvm/MC/MCSymbolWasm.h" 22 23 namespace llvm { 24 class WebAssemblyTargetLowering; 25 26 struct WasmEHFuncInfo; 27 28 namespace yaml { 29 struct WebAssemblyFunctionInfo; 30 } 31 32 /// This class is derived from MachineFunctionInfo and contains private 33 /// WebAssembly-specific information for each MachineFunction. 34 class WebAssemblyFunctionInfo final : public MachineFunctionInfo { 35 std::vector<MVT> Params; 36 std::vector<MVT> Results; 37 std::vector<MVT> Locals; 38 39 /// A mapping from CodeGen vreg index to WebAssembly register number. 40 std::vector<unsigned> WARegs; 41 42 /// A mapping from CodeGen vreg index to a boolean value indicating whether 43 /// the given register is considered to be "stackified", meaning it has been 44 /// determined or made to meet the stack requirements: 45 /// - single use (per path) 46 /// - single def (per path) 47 /// - defined and used in LIFO order with other stack registers 48 BitVector VRegStackified; 49 50 // A virtual register holding the pointer to the vararg buffer for vararg 51 // functions. It is created and set in TLI::LowerFormalArguments and read by 52 // TLI::LowerVASTART 53 unsigned VarargVreg = -1U; 54 55 // A virtual register holding the base pointer for functions that have 56 // overaligned values on the user stack. 57 unsigned BasePtrVreg = -1U; 58 // A virtual register holding the frame base. This is either FP or SP 59 // after it has been replaced by a vreg 60 unsigned FrameBaseVreg = -1U; 61 // The local holding the frame base. This is either FP or SP 62 // after WebAssemblyExplicitLocals 63 unsigned FrameBaseLocal = -1U; 64 65 // Function properties. 66 bool CFGStackified = false; 67 68 public: 69 explicit WebAssemblyFunctionInfo(const Function &F, 70 const TargetSubtargetInfo *STI) {} 71 ~WebAssemblyFunctionInfo() override; 72 73 MachineFunctionInfo * 74 clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, 75 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) 76 const override; 77 78 void initializeBaseYamlFields(MachineFunction &MF, 79 const yaml::WebAssemblyFunctionInfo &YamlMFI); 80 81 void addParam(MVT VT) { Params.push_back(VT); } 82 const std::vector<MVT> &getParams() const { return Params; } 83 84 void addResult(MVT VT) { Results.push_back(VT); } 85 const std::vector<MVT> &getResults() const { return Results; } 86 87 void clearParamsAndResults() { 88 Params.clear(); 89 Results.clear(); 90 } 91 92 void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); } 93 void setLocal(size_t i, MVT VT) { Locals[i] = VT; } 94 void addLocal(MVT VT) { Locals.push_back(VT); } 95 const std::vector<MVT> &getLocals() const { return Locals; } 96 97 unsigned getVarargBufferVreg() const { 98 assert(VarargVreg != -1U && "Vararg vreg hasn't been set"); 99 return VarargVreg; 100 } 101 void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; } 102 103 unsigned getBasePointerVreg() const { 104 assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set"); 105 return BasePtrVreg; 106 } 107 void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; } 108 unsigned getFrameBaseVreg() const { 109 assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set"); 110 return FrameBaseVreg; 111 } 112 void clearFrameBaseVreg() { FrameBaseVreg = -1U; } 113 // Return true if the frame base physreg has been replaced by a virtual reg. 114 bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; } 115 void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; } 116 unsigned getFrameBaseLocal() const { 117 assert(FrameBaseLocal != -1U && "Frame base local hasn't been set"); 118 return FrameBaseLocal; 119 } 120 void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; } 121 122 void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) { 123 assert(MRI.getUniqueVRegDef(VReg)); 124 auto I = Register::virtReg2Index(VReg); 125 if (I >= VRegStackified.size()) 126 VRegStackified.resize(I + 1); 127 VRegStackified.set(I); 128 } 129 void unstackifyVReg(unsigned VReg) { 130 auto I = Register::virtReg2Index(VReg); 131 if (I < VRegStackified.size()) 132 VRegStackified.reset(I); 133 } 134 bool isVRegStackified(unsigned VReg) const { 135 auto I = Register::virtReg2Index(VReg); 136 if (I >= VRegStackified.size()) 137 return false; 138 return VRegStackified.test(I); 139 } 140 141 void initWARegs(MachineRegisterInfo &MRI); 142 void setWAReg(unsigned VReg, unsigned WAReg) { 143 assert(WAReg != WebAssembly::UnusedReg); 144 auto I = Register::virtReg2Index(VReg); 145 assert(I < WARegs.size()); 146 WARegs[I] = WAReg; 147 } 148 unsigned getWAReg(unsigned VReg) const { 149 auto I = Register::virtReg2Index(VReg); 150 assert(I < WARegs.size()); 151 return WARegs[I]; 152 } 153 154 bool isCFGStackified() const { return CFGStackified; } 155 void setCFGStackified(bool Value = true) { CFGStackified = Value; } 156 }; 157 158 void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI, 159 LLVMContext &Ctx, const DataLayout &DL, Type *Ty, 160 SmallVectorImpl<MVT> &ValueVTs); 161 162 void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, 163 SmallVectorImpl<MVT> &ValueVTs); 164 165 // Compute the signature for a given FunctionType (Ty). Note that it's not the 166 // signature for ContextFunc (ContextFunc is just used to get varous context) 167 void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, 168 const Function &ContextFunc, const TargetMachine &TM, 169 SmallVectorImpl<MVT> &Params, 170 SmallVectorImpl<MVT> &Results); 171 172 void valTypesFromMVTs(const ArrayRef<MVT> &In, 173 SmallVectorImpl<wasm::ValType> &Out); 174 175 std::unique_ptr<wasm::WasmSignature> 176 signatureFromMVTs(const SmallVectorImpl<MVT> &Results, 177 const SmallVectorImpl<MVT> &Params); 178 179 namespace yaml { 180 181 using BBNumberMap = DenseMap<int, int>; 182 183 struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo { 184 std::vector<FlowStringValue> Params; 185 std::vector<FlowStringValue> Results; 186 bool CFGStackified = false; 187 // The same as WasmEHFuncInfo's SrcToUnwindDest, but stored in the mapping of 188 // BB numbers 189 BBNumberMap SrcToUnwindDest; 190 191 WebAssemblyFunctionInfo() = default; 192 WebAssemblyFunctionInfo(const llvm::MachineFunction &MF, 193 const llvm::WebAssemblyFunctionInfo &MFI); 194 195 void mappingImpl(yaml::IO &YamlIO) override; 196 ~WebAssemblyFunctionInfo() = default; 197 }; 198 199 template <> struct MappingTraits<WebAssemblyFunctionInfo> { 200 static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) { 201 YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>()); 202 YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>()); 203 YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false); 204 YamlIO.mapOptional("wasmEHFuncInfo", MFI.SrcToUnwindDest); 205 } 206 }; 207 208 template <> struct CustomMappingTraits<BBNumberMap> { 209 static void inputOne(IO &YamlIO, StringRef Key, 210 BBNumberMap &SrcToUnwindDest) { 211 YamlIO.mapRequired(Key.str().c_str(), 212 SrcToUnwindDest[std::atoi(Key.str().c_str())]); 213 } 214 215 static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) { 216 for (auto KV : SrcToUnwindDest) 217 YamlIO.mapRequired(std::to_string(KV.first).c_str(), KV.second); 218 } 219 }; 220 221 } // end namespace yaml 222 223 } // end namespace llvm 224 225 #endif 226