1*0b57cec5SDimitry Andric //=- WebAssemblyMachineFunctionInfo.cpp - WebAssembly Machine Function Info -=//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric ///
9*0b57cec5SDimitry Andric /// \file
10*0b57cec5SDimitry Andric /// This file implements WebAssembly-specific per-machine-function
11*0b57cec5SDimitry Andric /// information.
12*0b57cec5SDimitry Andric ///
13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14*0b57cec5SDimitry Andric 
15*0b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
16*0b57cec5SDimitry Andric #include "WebAssemblyISelLowering.h"
17*0b57cec5SDimitry Andric #include "WebAssemblySubtarget.h"
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/Analysis.h"
195ffd83dbSDimitry Andric #include "llvm/Target/TargetMachine.h"
20*0b57cec5SDimitry Andric using namespace llvm;
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
23*0b57cec5SDimitry Andric 
245ffd83dbSDimitry Andric void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
25*0b57cec5SDimitry Andric   assert(WARegs.empty());
26*0b57cec5SDimitry Andric   unsigned Reg = UnusedReg;
275ffd83dbSDimitry Andric   WARegs.resize(MRI.getNumVirtRegs(), Reg);
28*0b57cec5SDimitry Andric }
29*0b57cec5SDimitry Andric 
30*0b57cec5SDimitry Andric void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM,
31*0b57cec5SDimitry Andric                                 Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
32*0b57cec5SDimitry Andric   const DataLayout &DL(F.getParent()->getDataLayout());
33*0b57cec5SDimitry Andric   const WebAssemblyTargetLowering &TLI =
34*0b57cec5SDimitry Andric       *TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
35*0b57cec5SDimitry Andric   SmallVector<EVT, 4> VTs;
36*0b57cec5SDimitry Andric   ComputeValueVTs(TLI, DL, Ty, VTs);
37*0b57cec5SDimitry Andric 
38*0b57cec5SDimitry Andric   for (EVT VT : VTs) {
39*0b57cec5SDimitry Andric     unsigned NumRegs = TLI.getNumRegisters(F.getContext(), VT);
40*0b57cec5SDimitry Andric     MVT RegisterVT = TLI.getRegisterType(F.getContext(), VT);
41*0b57cec5SDimitry Andric     for (unsigned I = 0; I != NumRegs; ++I)
42*0b57cec5SDimitry Andric       ValueVTs.push_back(RegisterVT);
43*0b57cec5SDimitry Andric   }
44*0b57cec5SDimitry Andric }
45*0b57cec5SDimitry Andric 
465ffd83dbSDimitry Andric void llvm::computeSignatureVTs(const FunctionType *Ty,
475ffd83dbSDimitry Andric                                const Function *TargetFunc,
485ffd83dbSDimitry Andric                                const Function &ContextFunc,
49*0b57cec5SDimitry Andric                                const TargetMachine &TM,
50*0b57cec5SDimitry Andric                                SmallVectorImpl<MVT> &Params,
51*0b57cec5SDimitry Andric                                SmallVectorImpl<MVT> &Results) {
525ffd83dbSDimitry Andric   computeLegalValueVTs(ContextFunc, TM, Ty->getReturnType(), Results);
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric   MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
558bcb0991SDimitry Andric   if (Results.size() > 1 &&
565ffd83dbSDimitry Andric       !TM.getSubtarget<WebAssemblySubtarget>(ContextFunc).hasMultivalue()) {
578bcb0991SDimitry Andric     // WebAssembly can't lower returns of multiple values without demoting to
588bcb0991SDimitry Andric     // sret unless multivalue is enabled (see
598bcb0991SDimitry Andric     // WebAssemblyTargetLowering::CanLowerReturn). So replace multiple return
608bcb0991SDimitry Andric     // values with a poitner parameter.
61*0b57cec5SDimitry Andric     Results.clear();
62*0b57cec5SDimitry Andric     Params.push_back(PtrVT);
63*0b57cec5SDimitry Andric   }
64*0b57cec5SDimitry Andric 
65*0b57cec5SDimitry Andric   for (auto *Param : Ty->params())
665ffd83dbSDimitry Andric     computeLegalValueVTs(ContextFunc, TM, Param, Params);
67*0b57cec5SDimitry Andric   if (Ty->isVarArg())
68*0b57cec5SDimitry Andric     Params.push_back(PtrVT);
695ffd83dbSDimitry Andric 
705ffd83dbSDimitry Andric   // For swiftcc, emit additional swiftself and swifterror parameters
715ffd83dbSDimitry Andric   // if there aren't. These additional parameters are also passed for caller.
725ffd83dbSDimitry Andric   // They are necessary to match callee and caller signature for indirect
735ffd83dbSDimitry Andric   // call.
745ffd83dbSDimitry Andric 
755ffd83dbSDimitry Andric   if (TargetFunc && TargetFunc->getCallingConv() == CallingConv::Swift) {
765ffd83dbSDimitry Andric     MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
775ffd83dbSDimitry Andric     bool HasSwiftErrorArg = false;
785ffd83dbSDimitry Andric     bool HasSwiftSelfArg = false;
795ffd83dbSDimitry Andric     for (const auto &Arg : TargetFunc->args()) {
805ffd83dbSDimitry Andric       HasSwiftErrorArg |= Arg.hasAttribute(Attribute::SwiftError);
815ffd83dbSDimitry Andric       HasSwiftSelfArg |= Arg.hasAttribute(Attribute::SwiftSelf);
825ffd83dbSDimitry Andric     }
835ffd83dbSDimitry Andric     if (!HasSwiftErrorArg)
845ffd83dbSDimitry Andric       Params.push_back(PtrVT);
855ffd83dbSDimitry Andric     if (!HasSwiftSelfArg)
865ffd83dbSDimitry Andric       Params.push_back(PtrVT);
875ffd83dbSDimitry Andric   }
88*0b57cec5SDimitry Andric }
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric void llvm::valTypesFromMVTs(const ArrayRef<MVT> &In,
91*0b57cec5SDimitry Andric                             SmallVectorImpl<wasm::ValType> &Out) {
92*0b57cec5SDimitry Andric   for (MVT Ty : In)
93*0b57cec5SDimitry Andric     Out.push_back(WebAssembly::toValType(Ty));
94*0b57cec5SDimitry Andric }
95*0b57cec5SDimitry Andric 
96*0b57cec5SDimitry Andric std::unique_ptr<wasm::WasmSignature>
97*0b57cec5SDimitry Andric llvm::signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
98*0b57cec5SDimitry Andric                         const SmallVectorImpl<MVT> &Params) {
998bcb0991SDimitry Andric   auto Sig = std::make_unique<wasm::WasmSignature>();
100*0b57cec5SDimitry Andric   valTypesFromMVTs(Results, Sig->Returns);
101*0b57cec5SDimitry Andric   valTypesFromMVTs(Params, Sig->Params);
102*0b57cec5SDimitry Andric   return Sig;
103*0b57cec5SDimitry Andric }
104*0b57cec5SDimitry Andric 
105*0b57cec5SDimitry Andric yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
106*0b57cec5SDimitry Andric     const llvm::WebAssemblyFunctionInfo &MFI)
107*0b57cec5SDimitry Andric     : CFGStackified(MFI.isCFGStackified()) {}
108*0b57cec5SDimitry Andric 
109*0b57cec5SDimitry Andric void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
110*0b57cec5SDimitry Andric   MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, *this);
111*0b57cec5SDimitry Andric }
112*0b57cec5SDimitry Andric 
113*0b57cec5SDimitry Andric void WebAssemblyFunctionInfo::initializeBaseYamlFields(
114*0b57cec5SDimitry Andric     const yaml::WebAssemblyFunctionInfo &YamlMFI) {
115*0b57cec5SDimitry Andric   CFGStackified = YamlMFI.CFGStackified;
116*0b57cec5SDimitry Andric }
117