Files
llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
Heejin Ahn 6cad48ae72 [WebAssembly] Remove WasmEHFuncInfo (NFC) (#194972)
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.
2026-04-29 16:51:30 -07:00

206 lines
7.3 KiB
C++

// WebAssemblyMachineFunctionInfo.h-WebAssembly machine function info-*- C++ -*-
//
// 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 declares WebAssembly-specific per-machine-function
/// information.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
#define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYMACHINEFUNCTIONINFO_H
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/MC/MCSymbolWasm.h"
namespace llvm {
class WebAssemblyTargetLowering;
namespace yaml {
struct WebAssemblyFunctionInfo;
}
/// This class is derived from MachineFunctionInfo and contains private
/// WebAssembly-specific information for each MachineFunction.
class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
std::vector<MVT> Params;
std::vector<MVT> Results;
std::vector<MVT> Locals;
/// A mapping from CodeGen vreg index to WebAssembly register number.
std::vector<unsigned> WARegs;
/// A mapping from CodeGen vreg index to a boolean value indicating whether
/// the given register is considered to be "stackified", meaning it has been
/// determined or made to meet the stack requirements:
/// - single use (per path)
/// - single def (per path)
/// - defined and used in LIFO order with other stack registers
BitVector VRegStackified;
// A virtual register holding the pointer to the vararg buffer for vararg
// functions. It is created and set in TLI::LowerFormalArguments and read by
// TLI::LowerVASTART
unsigned VarargVreg = -1U;
// A virtual register holding the base pointer for functions that have
// overaligned values on the user stack.
unsigned BasePtrVreg = -1U;
// A virtual register holding the frame base. This is either FP or SP
// after it has been replaced by a vreg
unsigned FrameBaseVreg = -1U;
// The local holding the frame base. This is either FP or SP
// after WebAssemblyExplicitLocals
unsigned FrameBaseLocal = -1U;
// Function properties.
bool CFGStackified = false;
public:
explicit WebAssemblyFunctionInfo(const Function &F,
const TargetSubtargetInfo *STI) {}
~WebAssemblyFunctionInfo() override;
MachineFunctionInfo *
clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
const override;
void initializeBaseYamlFields(MachineFunction &MF,
const yaml::WebAssemblyFunctionInfo &YamlMFI);
void addParam(MVT VT) { Params.push_back(VT); }
const std::vector<MVT> &getParams() const { return Params; }
void addResult(MVT VT) { Results.push_back(VT); }
const std::vector<MVT> &getResults() const { return Results; }
void clearParamsAndResults() {
Params.clear();
Results.clear();
}
void setNumLocals(size_t NumLocals) { Locals.resize(NumLocals, MVT::i32); }
void setLocal(size_t i, MVT VT) { Locals[i] = VT; }
void addLocal(MVT VT) { Locals.push_back(VT); }
const std::vector<MVT> &getLocals() const { return Locals; }
unsigned getVarargBufferVreg() const {
assert(VarargVreg != -1U && "Vararg vreg hasn't been set");
return VarargVreg;
}
void setVarargBufferVreg(unsigned Reg) { VarargVreg = Reg; }
unsigned getBasePointerVreg() const {
assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set");
return BasePtrVreg;
}
void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; }
unsigned getFrameBaseVreg() const {
assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set");
return FrameBaseVreg;
}
void clearFrameBaseVreg() { FrameBaseVreg = -1U; }
// Return true if the frame base physreg has been replaced by a virtual reg.
bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; }
void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; }
unsigned getFrameBaseLocal() const {
assert(FrameBaseLocal != -1U && "Frame base local hasn't been set");
return FrameBaseLocal;
}
void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; }
void stackifyVReg(MachineRegisterInfo &MRI, Register VReg) {
assert(MRI.getUniqueVRegDef(VReg));
auto I = VReg.virtRegIndex();
if (I >= VRegStackified.size())
VRegStackified.resize(I + 1);
VRegStackified.set(I);
}
void unstackifyVReg(Register VReg) {
auto I = VReg.virtRegIndex();
if (I < VRegStackified.size())
VRegStackified.reset(I);
}
bool isVRegStackified(Register VReg) const {
auto I = VReg.virtRegIndex();
if (I >= VRegStackified.size())
return false;
return VRegStackified.test(I);
}
void initWARegs(MachineRegisterInfo &MRI);
void setWAReg(Register VReg, unsigned WAReg) {
assert(WAReg != WebAssembly::UnusedReg);
auto I = VReg.virtRegIndex();
assert(I < WARegs.size());
WARegs[I] = WAReg;
}
unsigned getWAReg(Register VReg) const {
auto I = VReg.virtRegIndex();
assert(I < WARegs.size());
return WARegs[I];
}
bool isCFGStackified() const { return CFGStackified; }
void setCFGStackified(bool Value = true) { CFGStackified = Value; }
};
void computeLegalValueVTs(const WebAssemblyTargetLowering &TLI,
LLVMContext &Ctx, const DataLayout &DL, Type *Ty,
SmallVectorImpl<MVT> &ValueVTs);
void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty,
SmallVectorImpl<MVT> &ValueVTs);
// Compute the signature for a given FunctionType (Ty). Note that it's not the
// signature for ContextFunc (ContextFunc is just used to get varous context)
void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc,
const Function &ContextFunc, const TargetMachine &TM,
SmallVectorImpl<MVT> &Params,
SmallVectorImpl<MVT> &Results);
void valTypesFromMVTs(ArrayRef<MVT> In, SmallVectorImpl<wasm::ValType> &Out);
wasm::WasmSignature *signatureFromMVTs(MCContext &Ctx,
const SmallVectorImpl<MVT> &Results,
const SmallVectorImpl<MVT> &Params);
namespace yaml {
using BBNumberMap = DenseMap<int, int>;
struct WebAssemblyFunctionInfo final : public yaml::MachineFunctionInfo {
std::vector<FlowStringValue> Params;
std::vector<FlowStringValue> Results;
bool CFGStackified = false;
WebAssemblyFunctionInfo() = default;
WebAssemblyFunctionInfo(const llvm::MachineFunction &MF,
const llvm::WebAssemblyFunctionInfo &MFI);
void mappingImpl(yaml::IO &YamlIO) override;
~WebAssemblyFunctionInfo() override = default;
};
template <> struct MappingTraits<WebAssemblyFunctionInfo> {
static void mapping(IO &YamlIO, WebAssemblyFunctionInfo &MFI) {
YamlIO.mapOptional("params", MFI.Params, std::vector<FlowStringValue>());
YamlIO.mapOptional("results", MFI.Results, std::vector<FlowStringValue>());
YamlIO.mapOptional("isCFGStackified", MFI.CFGStackified, false);
}
};
} // end namespace yaml
} // end namespace llvm
#endif