This removes `WasmEHFuncInfo` class.
This class was created to maintain the information of, "If an exception
is not caught by EHPad A, what is its next unwind destination?". Turns
out this information is already in the CFG.
After #130374, we use the common `findUnwindDestination`:
113479d119/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (L2107-L2164)
Note that in case of `catchswitch`, we follow its unwind destination
chain and add all of them to the invoke BB's successors until it meets a
`cleanuppad`, which always catches an exception. And the order of the
successor is the order of the unwind destination chain. So an invoke
BB's successor list would be like: [normal destination, unwind EHPad 1,
unwind EHPad 2, unwind EHPad 3, ...] where EHPad 2 is the next unwind
destination if EHPad 1 does not catch an exception and so on. So if we
want to know what the current EHPad's next unwind destination is, we can
examine the EHPad's predecessor (invoke BB)'s successor list, and find
the next successor of EHPad. If there is no further next unwind
destination, the list should end with that EHPad.
How we do this is in the added lambda functions in CFGStackify, which
replaces `WasmEHFuncInfo`'s `hasUnwindDest`/`getUnwindDest`.
This depends on the order of successors of a CFG, which someone can
argue may be not guaranteed, in case someone messes up the successor
order in later passes. But I think in practice this should be fine. Also
maintaining `WasmEHFuncInfo` has more risks, because if other passes
change EH-related CFGs, they have to make sure `WasmEHFuncInfo` stays
synced. I haven't personally found (so far) those passes and haven't had
to any adjustments to other passes, but it was always an inherent risk
when you maintain a separate data structure.
I wasn't able to completely delete `WasmEHFuncInfo.h` because it
contains the `Tag` enum. I renamed it to `WasmEHInfo.h`, because we
dont' have `WasmEHFuncInfo` class anymore.
148 lines
5.6 KiB
C++
148 lines
5.6 KiB
C++
//=- WebAssemblyMachineFunctionInfo.cpp - WebAssembly Machine Function Info -=//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file implements WebAssembly-specific per-machine-function
|
|
/// information.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "WebAssemblyMachineFunctionInfo.h"
|
|
#include "Utils/WebAssemblyTypeUtilities.h"
|
|
#include "WebAssemblyISelLowering.h"
|
|
#include "WebAssemblySubtarget.h"
|
|
#include "WebAssemblyUtilities.h"
|
|
#include "llvm/CodeGen/Analysis.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
using namespace llvm;
|
|
|
|
WebAssemblyFunctionInfo::~WebAssemblyFunctionInfo() = default; // anchor.
|
|
|
|
MachineFunctionInfo *WebAssemblyFunctionInfo::clone(
|
|
BumpPtrAllocator &Allocator, MachineFunction &DestMF,
|
|
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
|
|
const {
|
|
return DestMF.cloneInfo<WebAssemblyFunctionInfo>(*this);
|
|
}
|
|
|
|
void WebAssemblyFunctionInfo::initWARegs(MachineRegisterInfo &MRI) {
|
|
assert(WARegs.empty());
|
|
unsigned Reg = WebAssembly::UnusedReg;
|
|
WARegs.resize(MRI.getNumVirtRegs(), Reg);
|
|
}
|
|
|
|
void llvm::computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
|
|
LLVMContext &Ctx, const DataLayout &DL,
|
|
Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
|
|
SmallVector<EVT, 4> VTs;
|
|
ComputeValueVTs(TLI, DL, Ty, VTs);
|
|
|
|
for (EVT VT : VTs) {
|
|
unsigned NumRegs = TLI.getNumRegisters(Ctx, VT);
|
|
MVT RegisterVT = TLI.getRegisterType(Ctx, VT);
|
|
for (unsigned I = 0; I != NumRegs; ++I)
|
|
ValueVTs.push_back(RegisterVT);
|
|
}
|
|
}
|
|
|
|
void llvm::computeLegalValueVTs(const Function &F, const TargetMachine &TM,
|
|
Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
|
|
const DataLayout &DL(F.getDataLayout());
|
|
const WebAssemblyTargetLowering &TLI =
|
|
*TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
|
|
computeLegalValueVTs(TLI, F.getContext(), DL, Ty, ValueVTs);
|
|
}
|
|
|
|
void llvm::computeSignatureVTs(const FunctionType *Ty,
|
|
const Function *TargetFunc,
|
|
const Function &ContextFunc,
|
|
const TargetMachine &TM,
|
|
SmallVectorImpl<MVT> &Params,
|
|
SmallVectorImpl<MVT> &Results) {
|
|
computeLegalValueVTs(ContextFunc, TM, Ty->getReturnType(), Results);
|
|
|
|
MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
|
|
if (!WebAssembly::canLowerReturn(
|
|
Results.size(),
|
|
&TM.getSubtarget<WebAssemblySubtarget>(ContextFunc))) {
|
|
// WebAssembly can't lower returns of multiple values without demoting to
|
|
// sret unless multivalue is enabled (see
|
|
// WebAssemblyTargetLowering::CanLowerReturn). So replace multiple return
|
|
// values with a poitner parameter.
|
|
Results.clear();
|
|
Params.push_back(PtrVT);
|
|
}
|
|
|
|
for (auto *Param : Ty->params())
|
|
computeLegalValueVTs(ContextFunc, TM, Param, Params);
|
|
if (Ty->isVarArg())
|
|
Params.push_back(PtrVT);
|
|
|
|
// For swiftcc and swifttailcc, emit additional swiftself, swifterror, and
|
|
// (for swifttailcc) swiftasync parameters if there aren't. These additional
|
|
// parameters are also passed for caller. They are necessary to match callee
|
|
// and caller signature for indirect call.
|
|
|
|
if (TargetFunc && (TargetFunc->getCallingConv() == CallingConv::Swift ||
|
|
TargetFunc->getCallingConv() == CallingConv::SwiftTail)) {
|
|
MVT PtrVT = MVT::getIntegerVT(TM.createDataLayout().getPointerSizeInBits());
|
|
bool HasSwiftErrorArg = false;
|
|
bool HasSwiftSelfArg = false;
|
|
bool HasSwiftAsyncArg = false;
|
|
for (const auto &Arg : TargetFunc->args()) {
|
|
HasSwiftErrorArg |= Arg.hasAttribute(Attribute::SwiftError);
|
|
HasSwiftSelfArg |= Arg.hasAttribute(Attribute::SwiftSelf);
|
|
HasSwiftAsyncArg |= Arg.hasAttribute(Attribute::SwiftAsync);
|
|
}
|
|
if (!HasSwiftSelfArg)
|
|
Params.push_back(PtrVT);
|
|
if (!HasSwiftErrorArg)
|
|
Params.push_back(PtrVT);
|
|
if (TargetFunc->getCallingConv() == CallingConv::SwiftTail &&
|
|
!HasSwiftAsyncArg)
|
|
Params.push_back(PtrVT);
|
|
}
|
|
}
|
|
|
|
void llvm::valTypesFromMVTs(ArrayRef<MVT> In,
|
|
SmallVectorImpl<wasm::ValType> &Out) {
|
|
for (MVT Ty : In)
|
|
Out.push_back(WebAssembly::toValType(Ty));
|
|
}
|
|
|
|
wasm::WasmSignature *
|
|
llvm::signatureFromMVTs(MCContext &Ctx, const SmallVectorImpl<MVT> &Results,
|
|
const SmallVectorImpl<MVT> &Params) {
|
|
auto Sig = Ctx.createWasmSignature();
|
|
valTypesFromMVTs(Results, Sig->Returns);
|
|
valTypesFromMVTs(Params, Sig->Params);
|
|
return Sig;
|
|
}
|
|
|
|
yaml::WebAssemblyFunctionInfo::WebAssemblyFunctionInfo(
|
|
const llvm::MachineFunction &MF, const llvm::WebAssemblyFunctionInfo &MFI)
|
|
: CFGStackified(MFI.isCFGStackified()) {
|
|
for (auto VT : MFI.getParams())
|
|
Params.push_back(EVT(VT).getEVTString());
|
|
for (auto VT : MFI.getResults())
|
|
Results.push_back(EVT(VT).getEVTString());
|
|
}
|
|
|
|
void yaml::WebAssemblyFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
|
|
MappingTraits<WebAssemblyFunctionInfo>::mapping(YamlIO, *this);
|
|
}
|
|
|
|
void WebAssemblyFunctionInfo::initializeBaseYamlFields(
|
|
MachineFunction &MF, const yaml::WebAssemblyFunctionInfo &YamlMFI) {
|
|
CFGStackified = YamlMFI.CFGStackified;
|
|
for (auto VT : YamlMFI.Params)
|
|
addParam(WebAssembly::parseMVT(VT.Value));
|
|
for (auto VT : YamlMFI.Results)
|
|
addResult(WebAssembly::parseMVT(VT.Value));
|
|
}
|