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 25 struct WasmEHFuncInfo; 26 27 namespace yaml { 28 struct WebAssemblyFunctionInfo; 29 } 30 31 /// This class is derived from MachineFunctionInfo and contains private 32 /// WebAssembly-specific information for each MachineFunction. 33 class WebAssemblyFunctionInfo final : public MachineFunctionInfo { 34 const MachineFunction &MF; 35 36 std::vector<MVT> Params; 37 std::vector<MVT> Results; 38 std::vector<MVT> Locals; 39 40 /// A mapping from CodeGen vreg index to WebAssembly register number. 41 std::vector<unsigned> WARegs; 42 43 /// A mapping from CodeGen vreg index to a boolean value indicating whether 44 /// the given register is considered to be "stackified", meaning it has been 45 /// determined or made to meet the stack requirements: 46 /// - single use (per path) 47 /// - single def (per path) 48 /// - defined and used in LIFO order with other stack registers 49 BitVector VRegStackified; 50 51 // A virtual register holding the pointer to the vararg buffer for vararg 52 // functions. It is created and set in TLI::LowerFormalArguments and read by 53 // TLI::LowerVASTART 54 unsigned VarargVreg = -1U; 55 56 // A virtual register holding the base pointer for functions that have 57 // overaligned values on the user stack. 58 unsigned BasePtrVreg = -1U; 59 // A virtual register holding the frame base. This is either FP or SP 60 // after it has been replaced by a vreg 61 unsigned FrameBaseVreg = -1U; 62 // The local holding the frame base. This is either FP or SP 63 // after WebAssemblyExplicitLocals 64 unsigned FrameBaseLocal = -1U; 65 66 // Function properties. 67 bool CFGStackified = false; 68 69 // Catchpad unwind destination info for wasm EH. 70 WasmEHFuncInfo *WasmEHInfo = nullptr; 71 72 public: 73 explicit WebAssemblyFunctionInfo(MachineFunction &MF) 74 : MF(MF), WasmEHInfo(MF.getWasmEHFuncInfo()) {} 75 ~WebAssemblyFunctionInfo() override; 76 77 const MachineFunction &getMachineFunction() const { return MF; } 78 79 void initializeBaseYamlFields(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 static const unsigned UnusedReg = -1u; 123 124 void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) { 125 assert(MRI.getUniqueVRegDef(VReg)); 126 auto I = Register::virtReg2Index(VReg); 127 if (I >= VRegStackified.size()) 128 VRegStackified.resize(I + 1); 129 VRegStackified.set(I); 130 } 131 void unstackifyVReg(unsigned VReg) { 132 auto I = Register::virtReg2Index(VReg); 133 if (I < VRegStackified.size()) 134 VRegStackified.reset(I); 135 } 136 bool isVRegStackified(unsigned VReg) const { 137 auto I = Register::virtReg2Index(VReg); 138 if (I >= VRegStackified.size()) 139 return false; 140 return VRegStackified.test(I); 141 } 142 143 void initWARegs(MachineRegisterInfo &MRI); 144 void setWAReg(unsigned VReg, unsigned WAReg) { 145 assert(WAReg != UnusedReg); 146 auto I = Register::virtReg2Index(VReg); 147 assert(I < WARegs.size()); 148 WARegs[I] = WAReg; 149 } 150 unsigned getWAReg(unsigned VReg) const { 151 auto I = Register::virtReg2Index(VReg); 152 assert(I < WARegs.size()); 153 return WARegs[I]; 154 } 155 156 // For a given stackified WAReg, return the id number to print with push/pop. 157 static unsigned getWARegStackId(unsigned Reg) { 158 assert(Reg & INT32_MIN); 159 return Reg & INT32_MAX; 160 } 161 162 bool isCFGStackified() const { return CFGStackified; } 163 void setCFGStackified(bool Value = true) { CFGStackified = Value; } 164 165 WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; } 166 void setWasmEHFuncInfo(WasmEHFuncInfo *Info) { WasmEHInfo = Info; } 167 }; 168 169 void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI, 170 LLVMContext &Ctx, const DataLayout &DL, Type *Ty, 171 SmallVectorImpl<MVT> &ValueVTs); 172 173 void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, 174 SmallVectorImpl<MVT> &ValueVTs); 175 176 // Compute the signature for a given FunctionType (Ty). Note that it's not the 177 // signature for ContextFunc (ContextFunc is just used to get varous context) 178 void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, 179 const Function &ContextFunc, const TargetMachine &TM, 180 SmallVectorImpl<MVT> &Params, 181 SmallVectorImpl<MVT> &Results); 182 183 void valTypesFromMVTs(const ArrayRef<MVT> &In, 184 SmallVectorImpl<wasm::ValType> &Out); 185 186 std::unique_ptr<wasm::WasmSignature> 187 signatureFromMVTs(const SmallVectorImpl<MVT> &Results, 188 const SmallVectorImpl<MVT> &Params); 189 190 namespace yaml { 191 192 using BBNumberMap = DenseMap<int, int>; 193 194 struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo { 195 std::vector<FlowStringValue> Params; 196 std::vector<FlowStringValue> Results; 197 bool CFGStackified = false; 198 // The same as WasmEHFuncInfo's SrcToUnwindDest, but stored in the mapping of 199 // BB numbers 200 BBNumberMap SrcToUnwindDest; 201 202 WebAssemblyFunctionInfo() = default; 203 WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo &MFI); 204 205 void mappingImpl(yaml::IO &YamlIO) override; 206 ~WebAssemblyFunctionInfo() = default; 207 }; 208 209 template <> struct MappingTraits<WebAssemblyFunctionInfo> { 210 static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) { 211 YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>()); 212 YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>()); 213 YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false); 214 YamlIO.mapOptional("wasmEHFuncInfo", MFI.SrcToUnwindDest); 215 } 216 }; 217 218 template <> struct CustomMappingTraits<BBNumberMap> { 219 static void inputOne(IO &YamlIO, StringRef Key, 220 BBNumberMap &SrcToUnwindDest) { 221 YamlIO.mapRequired(Key.str().c_str(), 222 SrcToUnwindDest[std::atoi(Key.str().c_str())]); 223 } 224 225 static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) { 226 for (auto KV : SrcToUnwindDest) 227 YamlIO.mapRequired(std::to_string(KV.first).c_str(), KV.second); 228 } 229 }; 230 231 } // end namespace yaml 232 233 } // end namespace llvm 234 235 #endif 236