/src/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
Line | Count | Source (jump to first uncovered line) |
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 | 6.72k | 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 | 25.2k | void addParam(MVT VT) { Params.push_back(VT); } |
82 | 52.2k | const std::vector<MVT> &getParams() const { return Params; } |
83 | | |
84 | 3.76k | void addResult(MVT VT) { Results.push_back(VT); } |
85 | 14.2k | const std::vector<MVT> &getResults() const { return Results; } |
86 | | |
87 | 0 | void clearParamsAndResults() { |
88 | 0 | Params.clear(); |
89 | 0 | Results.clear(); |
90 | 0 | } |
91 | | |
92 | 6.72k | void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); } |
93 | 1.64k | void setLocal(size_t i, MVT VT) { Locals[i] = VT; } |
94 | 0 | void addLocal(MVT VT) { Locals.push_back(VT); } |
95 | 13.4k | const std::vector<MVT> &getLocals() const { return Locals; } |
96 | | |
97 | 0 | unsigned getVarargBufferVreg() const { |
98 | 0 | assert(VarargVreg != -1U && "Vararg vreg hasn't been set"); |
99 | 0 | return VarargVreg; |
100 | 0 | } |
101 | 0 | void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; } |
102 | | |
103 | 4 | unsigned getBasePointerVreg() const { |
104 | 4 | assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set"); |
105 | 0 | return BasePtrVreg; |
106 | 4 | } |
107 | 408 | void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; } |
108 | 26.0k | unsigned getFrameBaseVreg() const { |
109 | 26.0k | assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set"); |
110 | 0 | return FrameBaseVreg; |
111 | 26.0k | } |
112 | 245 | void clearFrameBaseVreg() { FrameBaseVreg = -1U; } |
113 | | // Return true if the frame base physreg has been replaced by a virtual reg. |
114 | 87.3k | bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; } |
115 | 155 | void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; } |
116 | 3 | unsigned getFrameBaseLocal() const { |
117 | 3 | assert(FrameBaseLocal != -1U && "Frame base local hasn't been set"); |
118 | 0 | return FrameBaseLocal; |
119 | 3 | } |
120 | 5 | void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; } |
121 | | |
122 | 102k | void stackifyVReg(MachineRegisterInfo &MRI, unsigned VReg) { |
123 | 102k | assert(MRI.getUniqueVRegDef(VReg)); |
124 | 0 | auto I = Register::virtReg2Index(VReg); |
125 | 102k | if (I >= VRegStackified.size()) |
126 | 44.2k | VRegStackified.resize(I + 1); |
127 | 102k | VRegStackified.set(I); |
128 | 102k | } |
129 | 0 | void unstackifyVReg(unsigned VReg) { |
130 | 0 | auto I = Register::virtReg2Index(VReg); |
131 | 0 | if (I < VRegStackified.size()) |
132 | 0 | VRegStackified.reset(I); |
133 | 0 | } |
134 | 853k | bool isVRegStackified(unsigned VReg) const { |
135 | 853k | auto I = Register::virtReg2Index(VReg); |
136 | 853k | if (I >= VRegStackified.size()) |
137 | 39.6k | return false; |
138 | 813k | return VRegStackified.test(I); |
139 | 853k | } |
140 | | |
141 | | void initWARegs(MachineRegisterInfo &MRI); |
142 | 67.1k | void setWAReg(unsigned VReg, unsigned WAReg) { |
143 | 67.1k | assert(WAReg != WebAssembly::UnusedReg); |
144 | 0 | auto I = Register::virtReg2Index(VReg); |
145 | 67.1k | assert(I < WARegs.size()); |
146 | 0 | WARegs[I] = WAReg; |
147 | 67.1k | } |
148 | 130k | unsigned getWAReg(unsigned VReg) const { |
149 | 130k | auto I = Register::virtReg2Index(VReg); |
150 | 130k | assert(I < WARegs.size()); |
151 | 0 | return WARegs[I]; |
152 | 130k | } |
153 | | |
154 | 74.4k | bool isCFGStackified() const { return CFGStackified; } |
155 | 6.72k | 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 | 0 | WebAssemblyFunctionInfo() = default; |
192 | | WebAssemblyFunctionInfo(const llvm::MachineFunction &MF, |
193 | | const llvm::WebAssemblyFunctionInfo &MFI); |
194 | | |
195 | | void mappingImpl(yaml::IO &YamlIO) override; |
196 | 0 | ~WebAssemblyFunctionInfo() = default; |
197 | | }; |
198 | | |
199 | | template <> struct MappingTraits<WebAssemblyFunctionInfo> { |
200 | 0 | static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) { |
201 | 0 | YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>()); |
202 | 0 | YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>()); |
203 | 0 | YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false); |
204 | 0 | YamlIO.mapOptional("wasmEHFuncInfo", MFI.SrcToUnwindDest); |
205 | 0 | } |
206 | | }; |
207 | | |
208 | | template <> struct CustomMappingTraits<BBNumberMap> { |
209 | | static void inputOne(IO &YamlIO, StringRef Key, |
210 | 0 | BBNumberMap &SrcToUnwindDest) { |
211 | 0 | YamlIO.mapRequired(Key.str().c_str(), |
212 | 0 | SrcToUnwindDest[std::atoi(Key.str().c_str())]); |
213 | 0 | } |
214 | | |
215 | 0 | static void output(IO &YamlIO, BBNumberMap &SrcToUnwindDest) { |
216 | 0 | for (auto KV : SrcToUnwindDest) |
217 | 0 | YamlIO.mapRequired(std::to_string(KV.first).c_str(), KV.second); |
218 | 0 | } |
219 | | }; |
220 | | |
221 | | } // end namespace yaml |
222 | | |
223 | | } // end namespace llvm |
224 | | |
225 | | #endif |