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"
20 using namespace llvm;
21 
22 WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
23 
initWARegs(MachineRegisterInfo & MRI)24 void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
25   assert(WARegs.empty());
26   unsigned Reg = UnusedReg;
27   WARegs.resize(MRI.getNumVirtRegs(), Reg);
28 }
29 
computeLegalValueVTs(const Function & F,const TargetMachine & TM,Type * Ty,SmallVectorImpl<MVT> & ValueVTs)30 void 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 
computeSignatureVTs(const FunctionType * Ty,const Function * TargetFunc,const Function & ContextFunc,const TargetMachine & TM,SmallVectorImpl<MVT> & Params,SmallVectorImpl<MVT> & Results)46 void 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 
valTypesFromMVTs(const ArrayRef<MVT> & In,SmallVectorImpl<wasm::ValType> & Out)90 void 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 
96 std::unique_ptr<wasm::WasmSignature>
signatureFromMVTs(const SmallVectorImpl<MVT> & Results,const SmallVectorImpl<MVT> & Params)97 llvm::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 
WebAssemblyFunctionInfo(const llvm::WebAssemblyFunctionInfo & MFI)105 yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
106     const llvm::WebAssemblyFunctionInfo &MFI)
107     : CFGStackified(MFI.isCFGStackified()) {}
108 
mappingImpl(yaml::IO & YamlIO)109 void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
110   MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, *this);
111 }
112 
initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo & YamlMFI)113 void WebAssemblyFunctionInfo::initializeBaseYamlFields(
114     const yaml::WebAssemblyFunctionInfo &YamlMFI) {
115   CFGStackified = YamlMFI.CFGStackified;
116 }
117