1 | //=- WebAssemblyMachineFunctionInfo.cpp - WebAssembly Machine Function Info -=// |
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 implements WebAssembly-specific per-machine-function |
11 | /// information. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "WebAssemblyMachineFunctionInfo.h" |
16 | #include "Utils/WebAssemblyTypeUtilities.h" |
17 | #include "WebAssemblyISelLowering.h" |
18 | #include "WebAssemblySubtarget.h" |
19 | #include "WebAssemblyUtilities.h" |
20 | #include "llvm/CodeGen/Analysis.h" |
21 | #include "llvm/CodeGen/WasmEHFuncInfo.h" |
22 | #include "llvm/Target/TargetMachine.h" |
23 | using namespace llvm; |
24 | |
25 | WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor. |
26 | |
27 | MachineFunctionInfo *WebAssemblyFunctionInfo::clone( |
28 | BumpPtrAllocator &Allocator, MachineFunction &DestMF, |
29 | const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) |
30 | const { |
31 | // TODO: Implement cloning for WasmEHFuncInfo. This will have invalid block |
32 | // references. |
33 | return DestMF.cloneInfo<WebAssemblyFunctionInfo>(Old: *this); |
34 | } |
35 | |
36 | void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) { |
37 | assert(WARegs.empty()); |
38 | unsigned Reg = WebAssembly::UnusedReg; |
39 | WARegs.resize(new_size: MRI.getNumVirtRegs(), x: Reg); |
40 | } |
41 | |
42 | void llvm::computeLegalValueVTs(const WebAssemblyTargetLowering &TLI, |
43 | LLVMContext &Ctx, const DataLayout &DL, |
44 | Type *Ty, SmallVectorImpl<MVT> &ValueVTs) { |
45 | SmallVector<EVT, 4> VTs; |
46 | ComputeValueVTs(TLI, DL, Ty, ValueVTs&: VTs); |
47 | |
48 | for (EVT VT : VTs) { |
49 | unsigned NumRegs = TLI.getNumRegisters(Context&: Ctx, VT); |
50 | MVT RegisterVT = TLI.getRegisterType(Context&: Ctx, VT); |
51 | for (unsigned I = 0; I != NumRegs; ++I) |
52 | ValueVTs.push_back(Elt: RegisterVT); |
53 | } |
54 | } |
55 | |
56 | void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM, |
57 | Type *Ty, SmallVectorImpl<MVT> &ValueVTs) { |
58 | const DataLayout &DL(F.getDataLayout()); |
59 | const WebAssemblyTargetLowering &TLI = |
60 | *TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering(); |
61 | computeLegalValueVTs(TLI, Ctx&: F.getContext(), DL, Ty, ValueVTs); |
62 | } |
63 | |
64 | void llvm::computeSignatureVTs(const FunctionType *Ty, |
65 | const Function *TargetFunc, |
66 | const Function &ContextFunc, |
67 | const TargetMachine &TM, |
68 | SmallVectorImpl<MVT> &Params, |
69 | SmallVectorImpl<MVT> &Results) { |
70 | computeLegalValueVTs(F: ContextFunc, TM, Ty: Ty->getReturnType(), ValueVTs&: Results); |
71 | |
72 | MVT PtrVT = MVT::getIntegerVT(BitWidth: TM.createDataLayout().getPointerSizeInBits()); |
73 | if (!WebAssembly::canLowerReturn( |
74 | ResultSize: Results.size(), |
75 | Subtarget: &TM.getSubtarget<WebAssemblySubtarget>(F: ContextFunc))) { |
76 | // WebAssembly can't lower returns of multiple values without demoting to |
77 | // sret unless multivalue is enabled (see |
78 | // WebAssemblyTargetLowering::CanLowerReturn). So replace multiple return |
79 | // values with a poitner parameter. |
80 | Results.clear(); |
81 | Params.push_back(Elt: PtrVT); |
82 | } |
83 | |
84 | for (auto *Param : Ty->params()) |
85 | computeLegalValueVTs(F: ContextFunc, TM, Ty: Param, ValueVTs&: Params); |
86 | if (Ty->isVarArg()) |
87 | Params.push_back(Elt: PtrVT); |
88 | |
89 | // For swiftcc, emit additional swiftself and swifterror parameters |
90 | // if there aren't. These additional parameters are also passed for caller. |
91 | // They are necessary to match callee and caller signature for indirect |
92 | // call. |
93 | |
94 | if (TargetFunc && TargetFunc->getCallingConv() == CallingConv::Swift) { |
95 | MVT PtrVT = MVT::getIntegerVT(BitWidth: TM.createDataLayout().getPointerSizeInBits()); |
96 | bool HasSwiftErrorArg = false; |
97 | bool HasSwiftSelfArg = false; |
98 | for (const auto &Arg : TargetFunc->args()) { |
99 | HasSwiftErrorArg |= Arg.hasAttribute(Kind: Attribute::SwiftError); |
100 | HasSwiftSelfArg |= Arg.hasAttribute(Kind: Attribute::SwiftSelf); |
101 | } |
102 | if (!HasSwiftErrorArg) |
103 | Params.push_back(Elt: PtrVT); |
104 | if (!HasSwiftSelfArg) |
105 | Params.push_back(Elt: PtrVT); |
106 | } |
107 | } |
108 | |
109 | void llvm::valTypesFromMVTs(ArrayRef<MVT> In, |
110 | SmallVectorImpl<wasm::ValType> &Out) { |
111 | for (MVT Ty : In) |
112 | Out.push_back(Elt: WebAssembly::toValType(Type: Ty)); |
113 | } |
114 | |
115 | wasm::WasmSignature * |
116 | llvm::signatureFromMVTs(MCContext &Ctx, const SmallVectorImpl<MVT> &Results, |
117 | const SmallVectorImpl<MVT> &Params) { |
118 | auto Sig = Ctx.createWasmSignature(); |
119 | valTypesFromMVTs(In: Results, Out&: Sig->Returns); |
120 | valTypesFromMVTs(In: Params, Out&: Sig->Params); |
121 | return Sig; |
122 | } |
123 | |
124 | yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo( |
125 | const llvm::MachineFunction &MF, const llvm::WebAssemblyFunctionInfo &MFI) |
126 | : CFGStackified(MFI.isCFGStackified()) { |
127 | for (auto VT : MFI.getParams()) |
128 | Params.push_back(x: EVT(VT).getEVTString()); |
129 | for (auto VT : MFI.getResults()) |
130 | Results.push_back(x: EVT(VT).getEVTString()); |
131 | |
132 | // MFI.getWasmEHFuncInfo() is non-null only for functions with the |
133 | // personality function. |
134 | |
135 | if (auto *EHInfo = MF.getWasmEHFuncInfo()) { |
136 | // SrcToUnwindDest can contain stale mappings in case BBs are removed in |
137 | // optimizations, in case, for example, they are unreachable. We should not |
138 | // include their info. |
139 | SmallPtrSet<const MachineBasicBlock *, 16> MBBs; |
140 | for (const auto &MBB : MF) |
141 | MBBs.insert(Ptr: &MBB); |
142 | for (auto KV : EHInfo->SrcToUnwindDest) { |
143 | auto *SrcBB = cast<MachineBasicBlock *>(Val&: KV.first); |
144 | auto *DestBB = cast<MachineBasicBlock *>(Val&: KV.second); |
145 | if (MBBs.count(Ptr: SrcBB) && MBBs.count(Ptr: DestBB)) |
146 | SrcToUnwindDest[SrcBB->getNumber()] = DestBB->getNumber(); |
147 | } |
148 | } |
149 | } |
150 | |
151 | void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) { |
152 | MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, MFI&: *this); |
153 | } |
154 | |
155 | void WebAssemblyFunctionInfo::initializeBaseYamlFields( |
156 | MachineFunction &MF, const yaml::WebAssemblyFunctionInfo &YamlMFI) { |
157 | CFGStackified = YamlMFI.CFGStackified; |
158 | for (auto VT : YamlMFI.Params) |
159 | addParam(VT: WebAssembly::parseMVT(Type: VT.Value)); |
160 | for (auto VT : YamlMFI.Results) |
161 | addResult(VT: WebAssembly::parseMVT(Type: VT.Value)); |
162 | |
163 | // FIXME: WasmEHInfo is defined in the MachineFunction, but serialized |
164 | // here. Either WasmEHInfo should be moved out of MachineFunction, or the |
165 | // serialization handling should be moved to MachineFunction. |
166 | if (WasmEHFuncInfo *WasmEHInfo = MF.getWasmEHFuncInfo()) { |
167 | for (auto KV : YamlMFI.SrcToUnwindDest) |
168 | WasmEHInfo->setUnwindDest(MBB: MF.getBlockNumbered(N: KV.first), |
169 | Dest: MF.getBlockNumbered(N: KV.second)); |
170 | } |
171 | } |
172 | |