diff options
author | Derek Schuff <dschuff@google.com> | 2016-02-23 18:13:07 +0000 |
---|---|---|
committer | Derek Schuff <dschuff@google.com> | 2016-02-23 18:13:07 +0000 |
commit | 4b3bb213b2d21d862542cfe1965fbd4cab28f1a8 (patch) | |
tree | d52642210677862f16aa2797f371911c258dbc71 /llvm/lib/Target/WebAssembly | |
parent | 1b9fae5a40a92e2bb6c35286b2b9f2a58809423b (diff) | |
download | bcm5719-llvm-4b3bb213b2d21d862542cfe1965fbd4cab28f1a8.tar.gz bcm5719-llvm-4b3bb213b2d21d862542cfe1965fbd4cab28f1a8.zip |
[WebAssembly] Implement red zone for user stack
Implements a mostly-conventional redzone for the userspace
stack. Because we have unsigned load/store offsets we continue to use a
local SP subtracted from the incoming SP but do not write it back to
memory.
Differential Revision: http://reviews.llvm.org/D17525
llvm-svn: 261662
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp | 28 | ||||
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h | 8 |
2 files changed, 31 insertions, 5 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp index c5f43d806ed..ece8974408b 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp @@ -34,7 +34,6 @@ using namespace llvm; #define DEBUG_TYPE "wasm-frame-info" -// TODO: Implement a red zone? // TODO: wasm64 // TODO: Emit TargetOpcode::CFI_INSTRUCTION instructions @@ -59,6 +58,24 @@ bool WebAssemblyFrameLowering::hasReservedCallFrame( return !MF.getFrameInfo()->hasVarSizedObjects(); } + +/// Returns true if this function needs a local user-space stack pointer. +/// Unlike a machine stack pointer, the wasm user stack pointer is a global +/// variable, so it is loaded into a register in the prolog. +bool WebAssemblyFrameLowering::needsSP(const MachineFunction &MF, + const MachineFrameInfo &MFI) const { + return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF); +} + +/// Returns true if the local user-space stack pointer needs to be written back +/// to memory by this function (this is not meaningful if needsSP is false). If +/// false, the stack red zone can be used and only a local SP is needed. +bool WebAssemblyFrameLowering::needsSPWriteback( + const MachineFunction &MF, const MachineFrameInfo &MFI) const { + return MFI.getStackSize() > RedZoneSize || MFI.hasCalls() || + MF.getFunction()->hasFnAttribute(Attribute::NoRedZone); +} + static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator &InsertPt, @@ -88,7 +105,8 @@ void WebAssemblyFrameLowering::eliminateCallFramePseudoInstr( assert(!I->getOperand(0).getImm() && hasFP(MF) && "Call frame pseudos should only be used for dynamic stack adjustment"); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); - if (I->getOpcode() == TII->getCallFrameDestroyOpcode()) { + if (I->getOpcode() == TII->getCallFrameDestroyOpcode() && + needsSPWriteback(MF, *MF.getFrameInfo())) { DebugLoc DL = I->getDebugLoc(); writeSPToMemory(WebAssembly::SP32, MF, MBB, I, DL); } @@ -103,8 +121,8 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF, "WebAssembly should not have callee-saved registers"); auto *WFI = MF.getInfo<WebAssemblyFunctionInfo>(); + if (!needsSP(MF, *MFI)) return; uint64_t StackSize = MFI->getStackSize(); - if (!StackSize && !MFI->adjustsStack() && !hasFP(MF)) return; const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); auto &MRI = MF.getRegInfo(); @@ -152,7 +170,7 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF, WebAssembly::FP32) .addReg(WebAssembly::SP32); } - if (StackSize) { + if (StackSize && needsSPWriteback(MF, *MFI)) { writeSPToMemory(WebAssembly::SP32, MF, MBB, InsertPt, DL); } } @@ -161,7 +179,7 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { auto *MFI = MF.getFrameInfo(); uint64_t StackSize = MFI->getStackSize(); - if (!StackSize && !MFI->adjustsStack() && !hasFP(MF)) return; + if (!needsSP(MF, *MFI) || !needsSPWriteback(MF, *MFI)) return; auto *WFI = MF.getInfo<WebAssemblyFunctionInfo>(); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); auto &MRI = MF.getRegInfo(); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h index 39f3f04e68d..cb3b011aeb8 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h @@ -19,9 +19,12 @@ #include "llvm/Target/TargetFrameLowering.h" namespace llvm { +class MachineFrameInfo; class WebAssemblyFrameLowering final : public TargetFrameLowering { public: + static const size_t RedZoneSize = 128; + WebAssemblyFrameLowering() : TargetFrameLowering(StackGrowsDown, /*StackAlignment=*/16, /*LocalAreaOffset=*/0, @@ -38,6 +41,11 @@ class WebAssemblyFrameLowering final : public TargetFrameLowering { bool hasFP(const MachineFunction &MF) const override; bool hasReservedCallFrame(const MachineFunction &MF) const override; + + private: + bool needsSP(const MachineFunction &MF, const MachineFrameInfo &MFI) const; + bool needsSPWriteback(const MachineFunction &MF, + const MachineFrameInfo &MFI) const; }; } // end namespace llvm |