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