diff options
author | Andy Wingo <wingo@igalia.com> | 2021-04-21 15:41:48 +0200 |
---|---|---|
committer | Andy Wingo <wingo@igalia.com> | 2021-05-28 11:07:41 +0200 |
commit | 00ecf18979e3326b3afee8af3dc701c53ffdc93f (patch) | |
tree | d52d989b7c8b05350818c4ffd8f422a120f8b4c7 /llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp | |
parent | bd04d78d649bec9b0e10c42d7dcf48af38c3b8f4 (diff) | |
download | llvm-00ecf18979e3326b3afee8af3dc701c53ffdc93f.zip llvm-00ecf18979e3326b3afee8af3dc701c53ffdc93f.tar.gz llvm-00ecf18979e3326b3afee8af3dc701c53ffdc93f.tar.bz2 |
[WebAssembly][CodeGen] IR support for WebAssembly local variables
This patch adds TargetStackID::WasmLocal. This stack holds locations of
values that are only addressable by name -- not via a pointer to memory.
For the WebAssembly target, these objects are lowered to WebAssembly
local variables, which are managed by the WebAssembly run-time and are
not addressable by linear memory.
For the WebAssembly target IR indicates that an AllocaInst should be put
on TargetStackID::WasmLocal by putting it in the non-integral address
space WASM_ADDRESS_SPACE_WASM_VAR, with value 1. SROA will mostly lift
these allocations to SSA locals, but any alloca that reaches instruction
selection (usually in non-optimized builds) will be assigned the new
TargetStackID there. Loads and stores to those values are transformed
to new WebAssemblyISD::LOCAL_GET / WebAssemblyISD::LOCAL_SET nodes,
which then lower to the type-specific LOCAL_GET_I32 etc instructions via
tablegen patterns.
Differential Revision: https://reviews.llvm.org/D101140
Diffstat (limited to 'llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp index 824d336..60e3d1a 100644 --- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp +++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.cpp @@ -13,8 +13,12 @@ #include "WebAssemblyUtilities.h" #include "WebAssemblyMachineFunctionInfo.h" +#include "WebAssemblySubtarget.h" +#include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/IR/Instructions.h" #include "llvm/MC/MCContext.h" using namespace llvm; @@ -24,6 +28,50 @@ const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev"; const char *const WebAssembly::PersonalityWrapperFn = "_Unwind_Wasm_CallPersonality"; +// In an ideal world, when objects are added to the MachineFrameInfo by +// FunctionLoweringInfo::set, we could somehow hook into target-specific code to +// ensure they are assigned the right stack ID. However there isn't a hook that +// runs between then and DAG building time, though, so instead we hoist stack +// objects lazily when they are first used, and comprehensively after the DAG is +// built via the PreprocessISelDAG hook, called by the +// SelectionDAGISel::runOnMachineFunction. We have to do it in two places +// because we want to do it while building the selection DAG for uses of alloca, +// but not all alloca instructions are used so we have to follow up afterwards. +Optional<unsigned> WebAssembly::getLocalForStackObject(MachineFunction &MF, + int FrameIndex) { + auto &MFI = MF.getFrameInfo(); + + // If already hoisted to a local, done. + if (MFI.getStackID(FrameIndex) == TargetStackID::WasmLocal) + return static_cast<unsigned>(MFI.getObjectOffset(FrameIndex)); + + // If not allocated in the object address space, this object will be in + // linear memory. + const AllocaInst *AI = MFI.getObjectAllocation(FrameIndex); + if (!AI || !isWasmVarAddressSpace(AI->getType()->getAddressSpace())) + return None; + + // Otherwise, allocate this object in the named value stack, outside of linear + // memory. + SmallVector<EVT, 4> ValueVTs; + const WebAssemblyTargetLowering &TLI = + *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering(); + WebAssemblyFunctionInfo *FuncInfo = MF.getInfo<WebAssemblyFunctionInfo>(); + ComputeValueVTs(TLI, MF.getDataLayout(), AI->getAllocatedType(), ValueVTs); + MFI.setStackID(FrameIndex, TargetStackID::WasmLocal); + // Abuse SP offset to record the index of the first local in the object. + unsigned Local = FuncInfo->getParams().size() + FuncInfo->getLocals().size(); + MFI.setObjectOffset(FrameIndex, Local); + // Allocate WebAssembly locals for each non-aggregate component of the + // allocation. + for (EVT ValueVT : ValueVTs) + FuncInfo->addLocal(ValueVT.getSimpleVT()); + // Abuse object size to record number of WebAssembly locals allocated to + // this object. + MFI.setObjectSize(FrameIndex, ValueVTs.size()); + return static_cast<unsigned>(Local); +} + /// Test whether MI is a child of some other node in an expression tree. bool WebAssembly::isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI) { |