110e730a2SDan Gohman //=- WebAssemblyMachineFunctionInfo.cpp - WebAssembly Machine Function Info -=//
210e730a2SDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
610e730a2SDan Gohman //
710e730a2SDan Gohman //===----------------------------------------------------------------------===//
810e730a2SDan Gohman ///
910e730a2SDan Gohman /// \file
105f8f34e4SAdrian Prantl /// This file implements WebAssembly-specific per-machine-function
1110e730a2SDan Gohman /// information.
1210e730a2SDan Gohman ///
1310e730a2SDan Gohman //===----------------------------------------------------------------------===//
1410e730a2SDan Gohman 
1510e730a2SDan Gohman #include "WebAssemblyMachineFunctionInfo.h"
16b3e88ccbSHeejin Ahn #include "MCTargetDesc/WebAssemblyInstPrinter.h"
170b2bc69bSHeejin Ahn #include "Utils/WebAssemblyTypeUtilities.h"
182726b88cSDan Gohman #include "WebAssemblyISelLowering.h"
192726b88cSDan Gohman #include "WebAssemblySubtarget.h"
202726b88cSDan Gohman #include "llvm/CodeGen/Analysis.h"
210b2bc69bSHeejin Ahn #include "llvm/CodeGen/WasmEHFuncInfo.h"
22fe0006c8SSimon Pilgrim #include "llvm/Target/TargetMachine.h"
2310e730a2SDan Gohman using namespace llvm;
2410e730a2SDan Gohman 
2518c56a07SHeejin Ahn WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
26058fce54SDan Gohman 
clone(BumpPtrAllocator & Allocator,MachineFunction & DestMF,const DenseMap<MachineBasicBlock *,MachineBasicBlock * > & Src2DstMBB) const27*cc5a1b3dSMatt Arsenault MachineFunctionInfo *WebAssemblyFunctionInfo::clone(
28*cc5a1b3dSMatt Arsenault     BumpPtrAllocator &Allocator, MachineFunction &DestMF,
29*cc5a1b3dSMatt Arsenault     const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
30*cc5a1b3dSMatt Arsenault     const {
31*cc5a1b3dSMatt Arsenault   WebAssemblyFunctionInfo *Clone =
32*cc5a1b3dSMatt Arsenault       DestMF.cloneInfo<WebAssemblyFunctionInfo>(*this);
33*cc5a1b3dSMatt Arsenault   Clone->MF = &DestMF;
34*cc5a1b3dSMatt Arsenault   return Clone;
35*cc5a1b3dSMatt Arsenault }
36*cc5a1b3dSMatt Arsenault 
initWARegs(MachineRegisterInfo & MRI)37c5d24009SMatt Arsenault void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
38058fce54SDan Gohman   assert(WARegs.empty());
39058fce54SDan Gohman   unsigned Reg = UnusedReg;
40c5d24009SMatt Arsenault   WARegs.resize(MRI.getNumVirtRegs(), Reg);
41058fce54SDan Gohman }
422726b88cSDan Gohman 
computeLegalValueVTs(const WebAssemblyTargetLowering & TLI,LLVMContext & Ctx,const DataLayout & DL,Type * Ty,SmallVectorImpl<MVT> & ValueVTs)43864767abSPaulo Matos void llvm::computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
44864767abSPaulo Matos                                 LLVMContext &Ctx, const DataLayout &DL,
45864767abSPaulo Matos                                 Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
46864767abSPaulo Matos   SmallVector<EVT, 4> VTs;
47864767abSPaulo Matos   ComputeValueVTs(TLI, DL, Ty, VTs);
48864767abSPaulo Matos 
49864767abSPaulo Matos   for (EVT VT : VTs) {
50864767abSPaulo Matos     unsigned NumRegs = TLI.getNumRegisters(Ctx, VT);
51864767abSPaulo Matos     MVT RegisterVT = TLI.getRegisterType(Ctx, VT);
52864767abSPaulo Matos     for (unsigned I = 0; I != NumRegs; ++I)
53864767abSPaulo Matos       ValueVTs.push_back(RegisterVT);
54864767abSPaulo Matos   }
55864767abSPaulo Matos }
56864767abSPaulo Matos 
computeLegalValueVTs(const Function & F,const TargetMachine & TM,Type * Ty,SmallVectorImpl<MVT> & ValueVTs)5718c56a07SHeejin Ahn void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM,
582726b88cSDan Gohman                                 Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
592726b88cSDan Gohman   const DataLayout &DL(F.getParent()->getDataLayout());
602726b88cSDan Gohman   const WebAssemblyTargetLowering &TLI =
612726b88cSDan Gohman       *TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
62864767abSPaulo Matos   computeLegalValueVTs(TLI, F.getContext(), DL, Ty, ValueVTs);
632726b88cSDan Gohman }
642726b88cSDan Gohman 
computeSignatureVTs(const FunctionType * Ty,const Function * TargetFunc,const Function & ContextFunc,const TargetMachine & TM,SmallVectorImpl<MVT> & Params,SmallVectorImpl<MVT> & Results)6508670d43SYuta Saito void llvm::computeSignatureVTs(const FunctionType *Ty,
6608670d43SYuta Saito                                const Function *TargetFunc,
6708670d43SYuta Saito                                const Function &ContextFunc,
6877a7a380SDerek Schuff                                const TargetMachine &TM,
692726b88cSDan Gohman                                SmallVectorImpl<MVT> &Params,
702726b88cSDan Gohman                                SmallVectorImpl<MVT> &Results) {
7108670d43SYuta Saito   computeLegalValueVTs(ContextFunc, TM, Ty->getReturnType(), Results);
722726b88cSDan Gohman 
7377a7a380SDerek Schuff   MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
7400f9e5aaSThomas Lively   if (Results.size() > 1 &&
7508670d43SYuta Saito       !TM.getSubtarget<WebAssemblySubtarget>(ContextFunc).hasMultivalue()) {
7600f9e5aaSThomas Lively     // WebAssembly can't lower returns of multiple values without demoting to
7700f9e5aaSThomas Lively     // sret unless multivalue is enabled (see
7800f9e5aaSThomas Lively     // WebAssemblyTargetLowering::CanLowerReturn). So replace multiple return
7900f9e5aaSThomas Lively     // values with a poitner parameter.
802726b88cSDan Gohman     Results.clear();
8177a7a380SDerek Schuff     Params.push_back(PtrVT);
822726b88cSDan Gohman   }
832726b88cSDan Gohman 
8477a7a380SDerek Schuff   for (auto *Param : Ty->params())
8508670d43SYuta Saito     computeLegalValueVTs(ContextFunc, TM, Param, Params);
8677a7a380SDerek Schuff   if (Ty->isVarArg())
8777a7a380SDerek Schuff     Params.push_back(PtrVT);
8808670d43SYuta Saito 
8908670d43SYuta Saito   // For swiftcc, emit additional swiftself and swifterror parameters
9008670d43SYuta Saito   // if there aren't. These additional parameters are also passed for caller.
9108670d43SYuta Saito   // They are necessary to match callee and caller signature for indirect
9208670d43SYuta Saito   // call.
9308670d43SYuta Saito 
9408670d43SYuta Saito   if (TargetFunc && TargetFunc->getCallingConv() == CallingConv::Swift) {
9508670d43SYuta Saito     MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
9608670d43SYuta Saito     bool HasSwiftErrorArg = false;
9708670d43SYuta Saito     bool HasSwiftSelfArg = false;
9808670d43SYuta Saito     for (const auto &Arg : TargetFunc->args()) {
9908670d43SYuta Saito       HasSwiftErrorArg |= Arg.hasAttribute(Attribute::SwiftError);
10008670d43SYuta Saito       HasSwiftSelfArg |= Arg.hasAttribute(Attribute::SwiftSelf);
10108670d43SYuta Saito     }
10208670d43SYuta Saito     if (!HasSwiftErrorArg)
10308670d43SYuta Saito       Params.push_back(PtrVT);
10408670d43SYuta Saito     if (!HasSwiftSelfArg)
10508670d43SYuta Saito       Params.push_back(PtrVT);
10608670d43SYuta Saito   }
10777a7a380SDerek Schuff }
10877a7a380SDerek Schuff 
valTypesFromMVTs(const ArrayRef<MVT> & In,SmallVectorImpl<wasm::ValType> & Out)10918c56a07SHeejin Ahn void llvm::valTypesFromMVTs(const ArrayRef<MVT> &In,
11049482f82SWouter van Oortmerssen                             SmallVectorImpl<wasm::ValType> &Out) {
11149482f82SWouter van Oortmerssen   for (MVT Ty : In)
11249482f82SWouter van Oortmerssen     Out.push_back(WebAssembly::toValType(Ty));
11349482f82SWouter van Oortmerssen }
11449482f82SWouter van Oortmerssen 
11577a7a380SDerek Schuff std::unique_ptr<wasm::WasmSignature>
signatureFromMVTs(const SmallVectorImpl<MVT> & Results,const SmallVectorImpl<MVT> & Params)11618c56a07SHeejin Ahn llvm::signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
11777a7a380SDerek Schuff                         const SmallVectorImpl<MVT> &Params) {
1180eaee545SJonas Devlieghere   auto Sig = std::make_unique<wasm::WasmSignature>();
11918c56a07SHeejin Ahn   valTypesFromMVTs(Results, Sig->Returns);
12018c56a07SHeejin Ahn   valTypesFromMVTs(Params, Sig->Params);
12177a7a380SDerek Schuff   return Sig;
1222726b88cSDan Gohman }
12352221d56SHeejin Ahn 
WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo & MFI)12452221d56SHeejin Ahn yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
1251aaa481fSHeejin Ahn     const llvm::WebAssemblyFunctionInfo &MFI)
12651fb5bf4SHeejin Ahn     : CFGStackified(MFI.isCFGStackified()) {
12751fb5bf4SHeejin Ahn   auto *EHInfo = MFI.getWasmEHFuncInfo();
12851fb5bf4SHeejin Ahn   const llvm::MachineFunction &MF = MFI.getMachineFunction();
129b3e88ccbSHeejin Ahn 
130b3e88ccbSHeejin Ahn   for (auto VT : MFI.getParams())
131b3e88ccbSHeejin Ahn     Params.push_back(EVT(VT).getEVTString());
132b3e88ccbSHeejin Ahn   for (auto VT : MFI.getResults())
133b3e88ccbSHeejin Ahn     Results.push_back(EVT(VT).getEVTString());
134b3e88ccbSHeejin Ahn 
13551fb5bf4SHeejin Ahn   //  MFI.getWasmEHFuncInfo() is non-null only for functions with the
13651fb5bf4SHeejin Ahn   //  personality function.
13751fb5bf4SHeejin Ahn   if (EHInfo) {
13851fb5bf4SHeejin Ahn     // SrcToUnwindDest can contain stale mappings in case BBs are removed in
13951fb5bf4SHeejin Ahn     // optimizations, in case, for example, they are unreachable. We should not
14051fb5bf4SHeejin Ahn     // include their info.
14151fb5bf4SHeejin Ahn     SmallPtrSet<const MachineBasicBlock *, 16> MBBs;
14251fb5bf4SHeejin Ahn     for (const auto &MBB : MF)
14351fb5bf4SHeejin Ahn       MBBs.insert(&MBB);
14451fb5bf4SHeejin Ahn     for (auto KV : EHInfo->SrcToUnwindDest) {
14551fb5bf4SHeejin Ahn       auto *SrcBB = KV.first.get<MachineBasicBlock *>();
14651fb5bf4SHeejin Ahn       auto *DestBB = KV.second.get<MachineBasicBlock *>();
14751fb5bf4SHeejin Ahn       if (MBBs.count(SrcBB) && MBBs.count(DestBB))
14851fb5bf4SHeejin Ahn         SrcToUnwindDest[SrcBB->getNumber()] = DestBB->getNumber();
14951fb5bf4SHeejin Ahn     }
15051fb5bf4SHeejin Ahn   }
15151fb5bf4SHeejin Ahn }
15252221d56SHeejin Ahn 
mappingImpl(yaml::IO & YamlIO)15352221d56SHeejin Ahn void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
15452221d56SHeejin Ahn   MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, *this);
15552221d56SHeejin Ahn }
15652221d56SHeejin Ahn 
initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo & YamlMFI)15752221d56SHeejin Ahn void WebAssemblyFunctionInfo::initializeBaseYamlFields(
1581aaa481fSHeejin Ahn     const yaml::WebAssemblyFunctionInfo &YamlMFI) {
1591aaa481fSHeejin Ahn   CFGStackified = YamlMFI.CFGStackified;
160b3e88ccbSHeejin Ahn   for (auto VT : YamlMFI.Params)
161b3e88ccbSHeejin Ahn     addParam(WebAssembly::parseMVT(VT.Value));
162b3e88ccbSHeejin Ahn   for (auto VT : YamlMFI.Results)
163b3e88ccbSHeejin Ahn     addResult(WebAssembly::parseMVT(VT.Value));
16451fb5bf4SHeejin Ahn   if (WasmEHInfo) {
16551fb5bf4SHeejin Ahn     for (auto KV : YamlMFI.SrcToUnwindDest)
166*cc5a1b3dSMatt Arsenault       WasmEHInfo->setUnwindDest(MF->getBlockNumbered(KV.first),
167*cc5a1b3dSMatt Arsenault                                 MF->getBlockNumbered(KV.second));
16851fb5bf4SHeejin Ahn   }
1691aaa481fSHeejin Ahn }
170