| 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(x: VT); } |
| 82 | const std::vector<MVT> &getParams() const { return Params; } |
| 83 | |
| 84 | void addResult(MVT VT) { Results.push_back(x: 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(new_size: NumLocals, x: MVT::i32); } |
| 93 | void setLocal(size_t i, MVT VT) { Locals[i] = VT; } |
| 94 | void addLocal(MVT VT) { Locals.push_back(x: 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, Register VReg) { |
| 123 | assert(MRI.getUniqueVRegDef(VReg)); |
| 124 | auto I = VReg.virtRegIndex(); |
| 125 | if (I >= VRegStackified.size()) |
| 126 | VRegStackified.resize(N: I + 1); |
| 127 | VRegStackified.set(I); |
| 128 | } |
| 129 | void unstackifyVReg(Register VReg) { |
| 130 | auto I = VReg.virtRegIndex(); |
| 131 | if (I < VRegStackified.size()) |
| 132 | VRegStackified.reset(Idx: I); |
| 133 | } |
| 134 | bool isVRegStackified(Register VReg) const { |
| 135 | auto I = VReg.virtRegIndex(); |
| 136 | if (I >= VRegStackified.size()) |
| 137 | return false; |
| 138 | return VRegStackified.test(Idx: I); |
| 139 | } |
| 140 | |
| 141 | void initWARegs(MachineRegisterInfo &MRI); |
| 142 | void setWAReg(Register VReg, unsigned WAReg) { |
| 143 | assert(WAReg != WebAssembly::UnusedReg); |
| 144 | auto I = VReg.virtRegIndex(); |
| 145 | assert(I < WARegs.size()); |
| 146 | WARegs[I] = WAReg; |
| 147 | } |
| 148 | unsigned getWAReg(Register VReg) const { |
| 149 | auto I = VReg.virtRegIndex(); |
| 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(ArrayRef<MVT> In, SmallVectorImpl<wasm::ValType> &Out); |
| 173 | |
| 174 | wasm::WasmSignature *signatureFromMVTs(MCContext &Ctx, |
| 175 | const SmallVectorImpl<MVT> &Results, |
| 176 | const SmallVectorImpl<MVT> &Params); |
| 177 | |
| 178 | namespace yaml { |
| 179 | |
| 180 | using BBNumberMap = DenseMap<int, int>; |
| 181 | |
| 182 | struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo { |
| 183 | std::vector<FlowStringValue> Params; |
| 184 | std::vector<FlowStringValue> Results; |
| 185 | bool CFGStackified = false; |
| 186 | // The same as WasmEHFuncInfo's SrcToUnwindDest, but stored in the mapping of |
| 187 | // BB numbers |
| 188 | BBNumberMap SrcToUnwindDest; |
| 189 | |
| 190 | WebAssemblyFunctionInfo() = default; |
| 191 | WebAssemblyFunctionInfo(const llvm::MachineFunction &MF, |
| 192 | const llvm::WebAssemblyFunctionInfo &MFI); |
| 193 | |
| 194 | void mappingImpl(yaml::IO &YamlIO) override; |
| 195 | ~WebAssemblyFunctionInfo() = default; |
| 196 | }; |
| 197 | |
| 198 | template <> struct MappingTraits<WebAssemblyFunctionInfo> { |
| 199 | static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) { |
| 200 | YamlIO.mapOptional(Key: "params" , Val&: MFI.Params, Default: std::vector<FlowStringValue>()); |
| 201 | YamlIO.mapOptional(Key: "results" , Val&: MFI.Results, Default: std::vector<FlowStringValue>()); |
| 202 | YamlIO.mapOptional(Key: "isCFGStackified" , Val&: MFI.CFGStackified, Default: false); |
| 203 | YamlIO.mapOptional(Key: "wasmEHFuncInfo" , Val&: MFI.SrcToUnwindDest); |
| 204 | } |
| 205 | }; |
| 206 | |
| 207 | template <> struct CustomMappingTraits<BBNumberMap> { |
| 208 | static void inputOne(IO &YamlIO, StringRef Key, |
| 209 | BBNumberMap &SrcToUnwindDest) { |
| 210 | YamlIO.mapRequired(Key: Key.str().c_str(), |
| 211 | Val&: SrcToUnwindDest[std::atoi(nptr: Key.str().c_str())]); |
| 212 | } |
| 213 | |
| 214 | static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) { |
| 215 | for (auto KV : SrcToUnwindDest) |
| 216 | YamlIO.mapRequired(Key: std::to_string(val: KV.first).c_str(), Val&: KV.second); |
| 217 | } |
| 218 | }; |
| 219 | |
| 220 | } // end namespace yaml |
| 221 | |
| 222 | } // end namespace llvm |
| 223 | |
| 224 | #endif |
| 225 | |