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