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 "llvm/CodeGen/Analysis.h"
20 #include "llvm/CodeGen/WasmEHFuncInfo.h"
21 #include "llvm/Target/TargetMachine.h"
22 using namespace llvm;
23 
24 WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
25 
26 void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
27   assert(WARegs.empty());
28   unsigned Reg = UnusedReg;
29   WARegs.resize(MRI.getNumVirtRegs(), Reg);
30 }
31 
32 void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM,
33                                 Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
34   const DataLayout &DL(F.getParent()->getDataLayout());
35   const WebAssemblyTargetLowering &TLI =
36       *TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
37   SmallVector<EVT, 4> VTs;
38   ComputeValueVTs(TLI, DL, Ty, VTs);
39 
40   for (EVT VT : VTs) {
41     unsigned NumRegs = TLI.getNumRegisters(F.getContext(), VT);
42     MVT RegisterVT = TLI.getRegisterType(F.getContext(), VT);
43     for (unsigned I = 0; I != NumRegs; ++I)
44       ValueVTs.push_back(RegisterVT);
45   }
46 }
47 
48 void llvm::computeSignatureVTs(const FunctionType *Ty,
49                                const Function *TargetFunc,
50                                const Function &ContextFunc,
51                                const TargetMachine &TM,
52                                SmallVectorImpl<MVT> &Params,
53                                SmallVectorImpl<MVT> &Results) {
54   computeLegalValueVTs(ContextFunc, TM, Ty->getReturnType(), Results);
55 
56   MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
57   if (Results.size() > 1 &&
58       !TM.getSubtarget<WebAssemblySubtarget>(ContextFunc).hasMultivalue()) {
59     // WebAssembly can't lower returns of multiple values without demoting to
60     // sret unless multivalue is enabled (see
61     // WebAssemblyTargetLowering::CanLowerReturn). So replace multiple return
62     // values with a poitner parameter.
63     Results.clear();
64     Params.push_back(PtrVT);
65   }
66 
67   for (auto *Param : Ty->params())
68     computeLegalValueVTs(ContextFunc, TM, Param, Params);
69   if (Ty->isVarArg())
70     Params.push_back(PtrVT);
71 
72   // For swiftcc, emit additional swiftself and swifterror parameters
73   // if there aren't. These additional parameters are also passed for caller.
74   // They are necessary to match callee and caller signature for indirect
75   // call.
76 
77   if (TargetFunc && TargetFunc->getCallingConv() == CallingConv::Swift) {
78     MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
79     bool HasSwiftErrorArg = false;
80     bool HasSwiftSelfArg = false;
81     for (const auto &Arg : TargetFunc->args()) {
82       HasSwiftErrorArg |= Arg.hasAttribute(Attribute::SwiftError);
83       HasSwiftSelfArg |= Arg.hasAttribute(Attribute::SwiftSelf);
84     }
85     if (!HasSwiftErrorArg)
86       Params.push_back(PtrVT);
87     if (!HasSwiftSelfArg)
88       Params.push_back(PtrVT);
89   }
90 }
91 
92 void llvm::valTypesFromMVTs(const ArrayRef<MVT> &In,
93                             SmallVectorImpl<wasm::ValType> &Out) {
94   for (MVT Ty : In)
95     Out.push_back(WebAssembly::toValType(Ty));
96 }
97 
98 std::unique_ptr<wasm::WasmSignature>
99 llvm::signatureFromMVTs(const SmallVectorImpl<MVT> &Results,
100                         const SmallVectorImpl<MVT> &Params) {
101   auto Sig = std::make_unique<wasm::WasmSignature>();
102   valTypesFromMVTs(Results, Sig->Returns);
103   valTypesFromMVTs(Params, Sig->Params);
104   return Sig;
105 }
106 
107 yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
108     const llvm::WebAssemblyFunctionInfo &MFI)
109     : CFGStackified(MFI.isCFGStackified()) {
110   auto *EHInfo = MFI.getWasmEHFuncInfo();
111   const llvm::MachineFunction &MF = MFI.getMachineFunction();
112   //  MFI.getWasmEHFuncInfo() is non-null only for functions with the
113   //  personality function.
114   if (EHInfo) {
115     // SrcToUnwindDest can contain stale mappings in case BBs are removed in
116     // optimizations, in case, for example, they are unreachable. We should not
117     // include their info.
118     SmallPtrSet<const MachineBasicBlock *, 16> MBBs;
119     for (const auto &MBB : MF)
120       MBBs.insert(&MBB);
121     for (auto KV : EHInfo->SrcToUnwindDest) {
122       auto *SrcBB = KV.first.get<MachineBasicBlock *>();
123       auto *DestBB = KV.second.get<MachineBasicBlock *>();
124       if (MBBs.count(SrcBB) && MBBs.count(DestBB))
125         SrcToUnwindDest[SrcBB->getNumber()] = DestBB->getNumber();
126     }
127   }
128 }
129 
130 void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
131   MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, *this);
132 }
133 
134 void WebAssemblyFunctionInfo::initializeBaseYamlFields(
135     const yaml::WebAssemblyFunctionInfo &YamlMFI) {
136   CFGStackified = YamlMFI.CFGStackified;
137   if (WasmEHInfo) {
138     for (auto KV : YamlMFI.SrcToUnwindDest)
139       WasmEHInfo->setUnwindDest(MF.getBlockNumbered(KV.first),
140                                 MF.getBlockNumbered(KV.second));
141   }
142 }
143