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 
24 void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
25   assert(WARegs.empty());
26   unsigned Reg = UnusedReg;
27   WARegs.resize(MRI.getNumVirtRegs(), Reg);
28 }
29 
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 
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 
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>
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 
105 yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
106     const llvm::WebAssemblyFunctionInfo &MFI)
107     : CFGStackified(MFI.isCFGStackified()) {
108   auto *EHInfo = MFI.getWasmEHFuncInfo();
109   const llvm::MachineFunction &MF = MFI.getMachineFunction();
110   //  MFI.getWasmEHFuncInfo() is non-null only for functions with the
111   //  personality function.
112   if (EHInfo) {
113     // SrcToUnwindDest can contain stale mappings in case BBs are removed in
114     // optimizations, in case, for example, they are unreachable. We should not
115     // include their info.
116     SmallPtrSet<const MachineBasicBlock *, 16> MBBs;
117     for (const auto &MBB : MF)
118       MBBs.insert(&MBB);
119     for (auto KV : EHInfo->SrcToUnwindDest) {
120       auto *SrcBB = KV.first.get<MachineBasicBlock *>();
121       auto *DestBB = KV.second.get<MachineBasicBlock *>();
122       if (MBBs.count(SrcBB) && MBBs.count(DestBB))
123         SrcToUnwindDest[SrcBB->getNumber()] = DestBB->getNumber();
124     }
125   }
126 }
127 
128 void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
129   MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, *this);
130 }
131 
132 void WebAssemblyFunctionInfo::initializeBaseYamlFields(
133     const yaml::WebAssemblyFunctionInfo &YamlMFI) {
134   CFGStackified = YamlMFI.CFGStackified;
135   if (WasmEHInfo) {
136     for (auto KV : YamlMFI.SrcToUnwindDest)
137       WasmEHInfo->setUnwindDest(MF.getBlockNumbered(KV.first),
138                                 MF.getBlockNumbered(KV.second));
139   }
140 }
141