11a82d4c0SDimitry Andric //=- WebAssemblyMachineFunctionInfo.cpp - WebAssembly Machine Function Info -=//
21a82d4c0SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61a82d4c0SDimitry Andric //
71a82d4c0SDimitry Andric //===----------------------------------------------------------------------===//
81a82d4c0SDimitry Andric ///
91a82d4c0SDimitry Andric /// \file
10eb11fae6SDimitry Andric /// This file implements WebAssembly-specific per-machine-function
111a82d4c0SDimitry Andric /// information.
121a82d4c0SDimitry Andric ///
131a82d4c0SDimitry Andric //===----------------------------------------------------------------------===//
141a82d4c0SDimitry Andric
151a82d4c0SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
16344a3780SDimitry Andric #include "MCTargetDesc/WebAssemblyInstPrinter.h"
17344a3780SDimitry Andric #include "Utils/WebAssemblyTypeUtilities.h"
18b915e9e0SDimitry Andric #include "WebAssemblyISelLowering.h"
19b915e9e0SDimitry Andric #include "WebAssemblySubtarget.h"
20ac9a064cSDimitry Andric #include "WebAssemblyUtilities.h"
21b915e9e0SDimitry Andric #include "llvm/CodeGen/Analysis.h"
22344a3780SDimitry Andric #include "llvm/CodeGen/WasmEHFuncInfo.h"
23cfca06d7SDimitry Andric #include "llvm/Target/TargetMachine.h"
241a82d4c0SDimitry Andric using namespace llvm;
251a82d4c0SDimitry Andric
26e6d15924SDimitry Andric WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
27dd58ef01SDimitry Andric
clone(BumpPtrAllocator & Allocator,MachineFunction & DestMF,const DenseMap<MachineBasicBlock *,MachineBasicBlock * > & Src2DstMBB) const28145449b1SDimitry Andric MachineFunctionInfo *WebAssemblyFunctionInfo::clone(
29145449b1SDimitry Andric BumpPtrAllocator &Allocator, MachineFunction &DestMF,
30145449b1SDimitry Andric const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
31145449b1SDimitry Andric const {
32e3b55780SDimitry Andric // TODO: Implement cloning for WasmEHFuncInfo. This will have invalid block
33e3b55780SDimitry Andric // references.
34e3b55780SDimitry Andric return DestMF.cloneInfo<WebAssemblyFunctionInfo>(*this);
35145449b1SDimitry Andric }
36145449b1SDimitry Andric
initWARegs(MachineRegisterInfo & MRI)37cfca06d7SDimitry Andric void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
38dd58ef01SDimitry Andric assert(WARegs.empty());
39b1c73532SDimitry Andric unsigned Reg = WebAssembly::UnusedReg;
40cfca06d7SDimitry Andric WARegs.resize(MRI.getNumVirtRegs(), Reg);
41dd58ef01SDimitry Andric }
42b915e9e0SDimitry Andric
computeLegalValueVTs(const WebAssemblyTargetLowering & TLI,LLVMContext & Ctx,const DataLayout & DL,Type * Ty,SmallVectorImpl<MVT> & ValueVTs)43ecbca9f5SDimitry Andric void llvm::computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
44ecbca9f5SDimitry Andric LLVMContext &Ctx, const DataLayout &DL,
45ecbca9f5SDimitry Andric Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
46ecbca9f5SDimitry Andric SmallVector<EVT, 4> VTs;
47ecbca9f5SDimitry Andric ComputeValueVTs(TLI, DL, Ty, VTs);
48ecbca9f5SDimitry Andric
49ecbca9f5SDimitry Andric for (EVT VT : VTs) {
50ecbca9f5SDimitry Andric unsigned NumRegs = TLI.getNumRegisters(Ctx, VT);
51ecbca9f5SDimitry Andric MVT RegisterVT = TLI.getRegisterType(Ctx, VT);
52ecbca9f5SDimitry Andric for (unsigned I = 0; I != NumRegs; ++I)
53ecbca9f5SDimitry Andric ValueVTs.push_back(RegisterVT);
54ecbca9f5SDimitry Andric }
55ecbca9f5SDimitry Andric }
56ecbca9f5SDimitry Andric
computeLegalValueVTs(const Function & F,const TargetMachine & TM,Type * Ty,SmallVectorImpl<MVT> & ValueVTs)57e6d15924SDimitry Andric void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM,
58b915e9e0SDimitry Andric Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
59ac9a064cSDimitry Andric const DataLayout &DL(F.getDataLayout());
60b915e9e0SDimitry Andric const WebAssemblyTargetLowering &TLI =
61b915e9e0SDimitry Andric *TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
62ecbca9f5SDimitry Andric computeLegalValueVTs(TLI, F.getContext(), DL, Ty, ValueVTs);
63b915e9e0SDimitry Andric }
64b915e9e0SDimitry Andric
computeSignatureVTs(const FunctionType * Ty,const Function * TargetFunc,const Function & ContextFunc,const TargetMachine & TM,SmallVectorImpl<MVT> & Params,SmallVectorImpl<MVT> & Results)65cfca06d7SDimitry Andric void llvm::computeSignatureVTs(const FunctionType *Ty,
66cfca06d7SDimitry Andric const Function *TargetFunc,
67cfca06d7SDimitry Andric const Function &ContextFunc,
68d8e91e46SDimitry Andric const TargetMachine &TM,
69b915e9e0SDimitry Andric SmallVectorImpl<MVT> &Params,
70b915e9e0SDimitry Andric SmallVectorImpl<MVT> &Results) {
71cfca06d7SDimitry Andric computeLegalValueVTs(ContextFunc, TM, Ty->getReturnType(), Results);
72b915e9e0SDimitry Andric
73d8e91e46SDimitry Andric MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
74ac9a064cSDimitry Andric if (!WebAssembly::canLowerReturn(
75ac9a064cSDimitry Andric Results.size(),
76ac9a064cSDimitry Andric &TM.getSubtarget<WebAssemblySubtarget>(ContextFunc))) {
771d5ae102SDimitry Andric // WebAssembly can't lower returns of multiple values without demoting to
781d5ae102SDimitry Andric // sret unless multivalue is enabled (see
791d5ae102SDimitry Andric // WebAssemblyTargetLowering::CanLowerReturn). So replace multiple return
801d5ae102SDimitry Andric // values with a poitner parameter.
81b915e9e0SDimitry Andric Results.clear();
82d8e91e46SDimitry Andric Params.push_back(PtrVT);
83b915e9e0SDimitry Andric }
84b915e9e0SDimitry Andric
85d8e91e46SDimitry Andric for (auto *Param : Ty->params())
86cfca06d7SDimitry Andric computeLegalValueVTs(ContextFunc, TM, Param, Params);
87d8e91e46SDimitry Andric if (Ty->isVarArg())
88d8e91e46SDimitry Andric Params.push_back(PtrVT);
89cfca06d7SDimitry Andric
90cfca06d7SDimitry Andric // For swiftcc, emit additional swiftself and swifterror parameters
91cfca06d7SDimitry Andric // if there aren't. These additional parameters are also passed for caller.
92cfca06d7SDimitry Andric // They are necessary to match callee and caller signature for indirect
93cfca06d7SDimitry Andric // call.
94cfca06d7SDimitry Andric
95cfca06d7SDimitry Andric if (TargetFunc && TargetFunc->getCallingConv() == CallingConv::Swift) {
96cfca06d7SDimitry Andric MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
97cfca06d7SDimitry Andric bool HasSwiftErrorArg = false;
98cfca06d7SDimitry Andric bool HasSwiftSelfArg = false;
99cfca06d7SDimitry Andric for (const auto &Arg : TargetFunc->args()) {
100cfca06d7SDimitry Andric HasSwiftErrorArg |= Arg.hasAttribute(Attribute::SwiftError);
101cfca06d7SDimitry Andric HasSwiftSelfArg |= Arg.hasAttribute(Attribute::SwiftSelf);
102cfca06d7SDimitry Andric }
103cfca06d7SDimitry Andric if (!HasSwiftErrorArg)
104cfca06d7SDimitry Andric Params.push_back(PtrVT);
105cfca06d7SDimitry Andric if (!HasSwiftSelfArg)
106cfca06d7SDimitry Andric Params.push_back(PtrVT);
107cfca06d7SDimitry Andric }
108d8e91e46SDimitry Andric }
109d8e91e46SDimitry Andric
valTypesFromMVTs(ArrayRef<MVT> In,SmallVectorImpl<wasm::ValType> & Out)110ac9a064cSDimitry Andric void llvm::valTypesFromMVTs(ArrayRef<MVT> In,
111d8e91e46SDimitry Andric SmallVectorImpl<wasm::ValType> &Out) {
112d8e91e46SDimitry Andric for (MVT Ty : In)
113d8e91e46SDimitry Andric Out.push_back(WebAssembly::toValType(Ty));
114d8e91e46SDimitry Andric }
115d8e91e46SDimitry Andric
116ac9a064cSDimitry Andric wasm::WasmSignature *
signatureFromMVTs(MCContext & Ctx,const SmallVectorImpl<MVT> & Results,const SmallVectorImpl<MVT> & Params)117ac9a064cSDimitry Andric llvm::signatureFromMVTs(MCContext &Ctx, const SmallVectorImpl<MVT> &Results,
118d8e91e46SDimitry Andric const SmallVectorImpl<MVT> &Params) {
119ac9a064cSDimitry Andric auto Sig = Ctx.createWasmSignature();
120e6d15924SDimitry Andric valTypesFromMVTs(Results, Sig->Returns);
121e6d15924SDimitry Andric valTypesFromMVTs(Params, Sig->Params);
122d8e91e46SDimitry Andric return Sig;
123b915e9e0SDimitry Andric }
124e6d15924SDimitry Andric
WebAssemblyFunctionInfo(const llvm::MachineFunction & MF,const llvm::WebAssemblyFunctionInfo & MFI)125e6d15924SDimitry Andric yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
126e3b55780SDimitry Andric const llvm::MachineFunction &MF, const llvm::WebAssemblyFunctionInfo &MFI)
127344a3780SDimitry Andric : CFGStackified(MFI.isCFGStackified()) {
128344a3780SDimitry Andric for (auto VT : MFI.getParams())
129344a3780SDimitry Andric Params.push_back(EVT(VT).getEVTString());
130344a3780SDimitry Andric for (auto VT : MFI.getResults())
131344a3780SDimitry Andric Results.push_back(EVT(VT).getEVTString());
132344a3780SDimitry Andric
133344a3780SDimitry Andric // MFI.getWasmEHFuncInfo() is non-null only for functions with the
134344a3780SDimitry Andric // personality function.
135e3b55780SDimitry Andric
136e3b55780SDimitry Andric if (auto *EHInfo = MF.getWasmEHFuncInfo()) {
137344a3780SDimitry Andric // SrcToUnwindDest can contain stale mappings in case BBs are removed in
138344a3780SDimitry Andric // optimizations, in case, for example, they are unreachable. We should not
139344a3780SDimitry Andric // include their info.
140344a3780SDimitry Andric SmallPtrSet<const MachineBasicBlock *, 16> MBBs;
141344a3780SDimitry Andric for (const auto &MBB : MF)
142344a3780SDimitry Andric MBBs.insert(&MBB);
143344a3780SDimitry Andric for (auto KV : EHInfo->SrcToUnwindDest) {
144344a3780SDimitry Andric auto *SrcBB = KV.first.get<MachineBasicBlock *>();
145344a3780SDimitry Andric auto *DestBB = KV.second.get<MachineBasicBlock *>();
146344a3780SDimitry Andric if (MBBs.count(SrcBB) && MBBs.count(DestBB))
147344a3780SDimitry Andric SrcToUnwindDest[SrcBB->getNumber()] = DestBB->getNumber();
148344a3780SDimitry Andric }
149344a3780SDimitry Andric }
150344a3780SDimitry Andric }
151e6d15924SDimitry Andric
mappingImpl(yaml::IO & YamlIO)152e6d15924SDimitry Andric void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
153e6d15924SDimitry Andric MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, *this);
154e6d15924SDimitry Andric }
155e6d15924SDimitry Andric
initializeBaseYamlFields(MachineFunction & MF,const yaml::WebAssemblyFunctionInfo & YamlMFI)156e6d15924SDimitry Andric void WebAssemblyFunctionInfo::initializeBaseYamlFields(
157e3b55780SDimitry Andric MachineFunction &MF, const yaml::WebAssemblyFunctionInfo &YamlMFI) {
158e6d15924SDimitry Andric CFGStackified = YamlMFI.CFGStackified;
159344a3780SDimitry Andric for (auto VT : YamlMFI.Params)
160344a3780SDimitry Andric addParam(WebAssembly::parseMVT(VT.Value));
161344a3780SDimitry Andric for (auto VT : YamlMFI.Results)
162344a3780SDimitry Andric addResult(WebAssembly::parseMVT(VT.Value));
163e3b55780SDimitry Andric
164e3b55780SDimitry Andric // FIXME: WasmEHInfo is defined in the MachineFunction, but serialized
165e3b55780SDimitry Andric // here. Either WasmEHInfo should be moved out of MachineFunction, or the
166e3b55780SDimitry Andric // serialization handling should be moved to MachineFunction.
167e3b55780SDimitry Andric if (WasmEHFuncInfo *WasmEHInfo = MF.getWasmEHFuncInfo()) {
168344a3780SDimitry Andric for (auto KV : YamlMFI.SrcToUnwindDest)
169e3b55780SDimitry Andric WasmEHInfo->setUnwindDest(MF.getBlockNumbered(KV.first),
170e3b55780SDimitry Andric MF.getBlockNumbered(KV.second));
171344a3780SDimitry Andric }
172e6d15924SDimitry Andric }
173