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