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 "WebAssemblyISelLowering.h"
17#include "WebAssemblySubtarget.h"
18#include "llvm/CodeGen/Analysis.h"
19#include "llvm/Target/TargetMachine.h"
20using namespace llvm;
21
22WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
23
24void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
25  assert(WARegs.empty());
26  unsigned Reg = UnusedReg;
27  WARegs.resize(MRI.getNumVirtRegs(), Reg);
28}
29
30void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM,
31                                Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
32  const DataLayout &DL(F.getParent()->getDataLayout());
33  const WebAssemblyTargetLowering &TLI =
34      *TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
35  SmallVector<EVT, 4> VTs;
36  ComputeValueVTs(TLI, DL, Ty, VTs);
37
38  for (EVT VT : VTs) {
39    unsigned NumRegs = TLI.getNumRegisters(F.getContext(), VT);
40    MVT RegisterVT = TLI.getRegisterType(F.getContext(), VT);
41    for (unsigned I = 0; I != NumRegs; ++I)
42      ValueVTs.push_back(RegisterVT);
43  }
44}
45
46void llvm::computeSignatureVTs(const FunctionType *Ty,
47                               const Function *TargetFunc,
48                               const Function &ContextFunc,
49                               const TargetMachine &TM,
50                               SmallVectorImpl<MVT> &Params,
51                               SmallVectorImpl<MVT> &Results) {
52  computeLegalValueVTs(ContextFunc, TM, Ty->getReturnType(), Results);
53
54  MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
55  if (Results.size() > 1 &&
56      !TM.getSubtarget<WebAssemblySubtarget>(ContextFunc).hasMultivalue()) {
57    // WebAssembly can't lower returns of multiple values without demoting to
58    // sret unless multivalue is enabled (see
59    // WebAssemblyTargetLowering::CanLowerReturn). So replace multiple return
60    // values with a poitner parameter.
61    Results.clear();
62    Params.push_back(PtrVT);
63  }
64
65  for (auto *Param : Ty->params())
66    computeLegalValueVTs(ContextFunc, TM, Param, Params);
67  if (Ty->isVarArg())
68    Params.push_back(PtrVT);
69
70  // For swiftcc, emit additional swiftself and swifterror parameters
71  // if there aren't. These additional parameters are also passed for caller.
72  // They are necessary to match callee and caller signature for indirect
73  // call.
74
75  if (TargetFunc && TargetFunc->getCallingConv() == CallingConv::Swift) {
76    MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
77    bool HasSwiftErrorArg = false;
78    bool HasSwiftSelfArg = false;
79    for (const auto &Arg : TargetFunc->args()) {
80      HasSwiftErrorArg |= Arg.hasAttribute(Attribute::SwiftError);
81      HasSwiftSelfArg |= Arg.hasAttribute(Attribute::SwiftSelf);
82    }
83    if (!HasSwiftErrorArg)
84      Params.push_back(PtrVT);
85    if (!HasSwiftSelfArg)
86      Params.push_back(PtrVT);
87  }
88}
89
90void llvm::valTypesFromMVTs(const ArrayRef<MVT> &In,
91                            SmallVectorImpl<wasm::ValType> &Out) {
92  for (MVT Ty : In)
93    Out.push_back(WebAssembly::toValType(Ty));
94}
95
96std::unique_ptr<wasm::WasmSignature>
97llvm::signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
98                        const SmallVectorImpl<MVT> &Params) {
99  auto Sig = std::make_unique<wasm::WasmSignature>();
100  valTypesFromMVTs(Results, Sig->Returns);
101  valTypesFromMVTs(Params, Sig->Params);
102  return Sig;
103}
104
105yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
106    const llvm::WebAssemblyFunctionInfo &MFI)
107    : CFGStackified(MFI.isCFGStackified()) {}
108
109void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
110  MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, *this);
111}
112
113void WebAssemblyFunctionInfo::initializeBaseYamlFields(
114    const yaml::WebAssemblyFunctionInfo &YamlMFI) {
115  CFGStackified = YamlMFI.CFGStackified;
116}
117