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 "Utils/WebAssemblyTypeUtilities.h"
17#include "WebAssemblyISelLowering.h"
18#include "WebAssemblySubtarget.h"
19#include "WebAssemblyUtilities.h"
20#include "llvm/CodeGen/Analysis.h"
21#include "llvm/IR/Module.h"
22#include "llvm/Target/TargetMachine.h"
23using namespace llvm;
24
25WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
26
27MachineFunctionInfo *WebAssemblyFunctionInfo::clone(
28 BumpPtrAllocator &Allocator, MachineFunction &DestMF,
29 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
30 const {
31 return DestMF.cloneInfo<WebAssemblyFunctionInfo>(Old: *this);
32}
33
34void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
35 assert(WARegs.empty());
36 unsigned Reg = WebAssembly::UnusedReg;
37 WARegs.resize(new_size: MRI.getNumVirtRegs(), x: Reg);
38}
39
40void llvm::computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
41 LLVMContext &Ctx, const DataLayout &DL,
42 Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
43 SmallVector<EVT, 4> VTs;
44 ComputeValueVTs(TLI, DL, Ty, ValueVTs&: VTs);
45
46 for (EVT VT : VTs) {
47 unsigned NumRegs = TLI.getNumRegisters(Context&: Ctx, VT);
48 MVT RegisterVT = TLI.getRegisterType(Context&: Ctx, VT);
49 for (unsigned I = 0; I != NumRegs; ++I)
50 ValueVTs.push_back(Elt: RegisterVT);
51 }
52}
53
54void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM,
55 Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
56 const DataLayout &DL(F.getDataLayout());
57 const WebAssemblyTargetLowering &TLI =
58 *TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
59 computeLegalValueVTs(TLI, Ctx&: F.getContext(), DL, Ty, ValueVTs);
60}
61
62void llvm::computeSignatureVTs(const FunctionType *Ty,
63 const Function *TargetFunc,
64 const Function &ContextFunc,
65 const TargetMachine &TM,
66 SmallVectorImpl<MVT> &Params,
67 SmallVectorImpl<MVT> &Results) {
68 computeLegalValueVTs(F: ContextFunc, TM, Ty: Ty->getReturnType(), ValueVTs&: Results);
69
70 const DataLayout &DL = ContextFunc.getParent()->getDataLayout();
71 MVT PtrVT = MVT::getIntegerVT(BitWidth: DL.getPointerSizeInBits());
72 if (!WebAssembly::canLowerReturn(
73 ResultSize: Results.size(),
74 Subtarget: &TM.getSubtarget<WebAssemblySubtarget>(F: ContextFunc))) {
75 // WebAssembly can't lower returns of multiple values without demoting to
76 // sret unless multivalue is enabled (see
77 // WebAssemblyTargetLowering::CanLowerReturn). So replace multiple return
78 // values with a pointer parameter.
79 Results.clear();
80 Params.push_back(Elt: PtrVT);
81 }
82
83 for (auto *Param : Ty->params())
84 computeLegalValueVTs(F: ContextFunc, TM, Ty: Param, ValueVTs&: Params);
85 if (Ty->isVarArg())
86 Params.push_back(Elt: PtrVT);
87
88 // For swiftcc and swifttailcc, emit additional swiftself, swifterror, and
89 // (for swifttailcc) swiftasync parameters if there aren't. These additional
90 // parameters are also passed for caller. They are necessary to match callee
91 // and caller signature for indirect call.
92
93 if (TargetFunc && (TargetFunc->getCallingConv() == CallingConv::Swift ||
94 TargetFunc->getCallingConv() == CallingConv::SwiftTail)) {
95 MVT PtrVT = MVT::getIntegerVT(BitWidth: DL.getPointerSizeInBits());
96 bool HasSwiftErrorArg = false;
97 bool HasSwiftSelfArg = false;
98 bool HasSwiftAsyncArg = false;
99 for (const auto &Arg : TargetFunc->args()) {
100 HasSwiftErrorArg |= Arg.hasAttribute(Kind: Attribute::SwiftError);
101 HasSwiftSelfArg |= Arg.hasAttribute(Kind: Attribute::SwiftSelf);
102 HasSwiftAsyncArg |= Arg.hasAttribute(Kind: Attribute::SwiftAsync);
103 }
104 if (!HasSwiftSelfArg)
105 Params.push_back(Elt: PtrVT);
106 if (!HasSwiftErrorArg)
107 Params.push_back(Elt: PtrVT);
108 if (TargetFunc->getCallingConv() == CallingConv::SwiftTail &&
109 !HasSwiftAsyncArg)
110 Params.push_back(Elt: PtrVT);
111 }
112}
113
114void llvm::valTypesFromMVTs(ArrayRef<MVT> In,
115 SmallVectorImpl<wasm::ValType> &Out) {
116 for (MVT Ty : In)
117 Out.push_back(Elt: WebAssembly::toValType(Type: Ty));
118}
119
120wasm::WasmSignature *
121llvm::signatureFromMVTs(MCContext &Ctx, const SmallVectorImpl<MVT> &Results,
122 const SmallVectorImpl<MVT> &Params) {
123 auto Sig = Ctx.createWasmSignature();
124 valTypesFromMVTs(In: Results, Out&: Sig->Returns);
125 valTypesFromMVTs(In: Params, Out&: Sig->Params);
126 return Sig;
127}
128
129yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
130 const llvm::MachineFunction &MF, const llvm::WebAssemblyFunctionInfo &MFI)
131 : CFGStackified(MFI.isCFGStackified()) {
132 for (auto VT : MFI.getParams())
133 Params.push_back(x: EVT(VT).getEVTString());
134 for (auto VT : MFI.getResults())
135 Results.push_back(x: EVT(VT).getEVTString());
136}
137
138void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
139 MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, MFI&: *this);
140}
141
142void WebAssemblyFunctionInfo::initializeBaseYamlFields(
143 MachineFunction &MF, const yaml::WebAssemblyFunctionInfo &YamlMFI) {
144 CFGStackified = YamlMFI.CFGStackified;
145 for (auto VT : YamlMFI.Params)
146 addParam(VT: WebAssembly::parseMVT(Type: VT.Value));
147 for (auto VT : YamlMFI.Results)
148 addResult(VT: WebAssembly::parseMVT(Type: VT.Value));
149}
150