110e730a2SDan Gohman //===-- WebAssemblyFrameLowering.cpp - WebAssembly Frame Lowering ----------==// 210e730a2SDan Gohman // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 610e730a2SDan Gohman // 710e730a2SDan Gohman //===----------------------------------------------------------------------===// 810e730a2SDan Gohman /// 910e730a2SDan Gohman /// \file 105f8f34e4SAdrian Prantl /// This file contains the WebAssembly implementation of 1110e730a2SDan Gohman /// TargetFrameLowering class. 1210e730a2SDan Gohman /// 1310e730a2SDan Gohman /// On WebAssembly, there aren't a lot of things to do here. There are no 1410e730a2SDan Gohman /// callee-saved registers to save, and no spill slots. 1510e730a2SDan Gohman /// 1610e730a2SDan Gohman /// The stack grows downward. 1710e730a2SDan Gohman /// 1810e730a2SDan Gohman //===----------------------------------------------------------------------===// 1910e730a2SDan Gohman 2010e730a2SDan Gohman #include "WebAssemblyFrameLowering.h" 2110e730a2SDan Gohman #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 22*0b2bc69bSHeejin Ahn #include "Utils/WebAssemblyUtilities.h" 23ff171acfSDerek Schuff #include "WebAssembly.h" 2410e730a2SDan Gohman #include "WebAssemblyInstrInfo.h" 2510e730a2SDan Gohman #include "WebAssemblyMachineFunctionInfo.h" 2610e730a2SDan Gohman #include "WebAssemblySubtarget.h" 2710e730a2SDan Gohman #include "WebAssemblyTargetMachine.h" 2810e730a2SDan Gohman #include "llvm/CodeGen/MachineFrameInfo.h" 2910e730a2SDan Gohman #include "llvm/CodeGen/MachineFunction.h" 3010e730a2SDan Gohman #include "llvm/CodeGen/MachineInstrBuilder.h" 3182607f56SDan Gohman #include "llvm/CodeGen/MachineModuleInfoImpls.h" 3210e730a2SDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h" 3378d19108SHeejin Ahn #include "llvm/MC/MCAsmInfo.h" 3410e730a2SDan Gohman #include "llvm/Support/Debug.h" 3510e730a2SDan Gohman using namespace llvm; 3610e730a2SDan Gohman 3703855df1SJF Bastien #define DEBUG_TYPE "wasm-frame-info" 3810e730a2SDan Gohman 399769debfSDerek Schuff // TODO: wasm64 409769debfSDerek Schuff // TODO: Emit TargetOpcode::CFI_INSTRUCTION instructions 4110e730a2SDan Gohman 420d41b7b3SDerek Schuff /// We need a base pointer in the case of having items on the stack that 430d41b7b3SDerek Schuff /// require stricter alignment than the stack pointer itself. Because we need 440d41b7b3SDerek Schuff /// to shift the stack pointer by some unknown amount to force the alignment, 450d41b7b3SDerek Schuff /// we need to record the value of the stack pointer on entry to the function. 46f208f631SHeejin Ahn bool WebAssemblyFrameLowering::hasBP(const MachineFunction &MF) const { 470d41b7b3SDerek Schuff const auto *RegInfo = 480d41b7b3SDerek Schuff MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo(); 49a9968c0aSTomas Matheson return RegInfo->hasStackRealignment(MF); 500d41b7b3SDerek Schuff } 510d41b7b3SDerek Schuff 5210e730a2SDan Gohman /// Return true if the specified function should have a dedicated frame pointer 5310e730a2SDan Gohman /// register. 5410e730a2SDan Gohman bool WebAssemblyFrameLowering::hasFP(const MachineFunction &MF) const { 55941a705bSMatthias Braun const MachineFrameInfo &MFI = MF.getFrameInfo(); 560d41b7b3SDerek Schuff 570d41b7b3SDerek Schuff // When we have var-sized objects, we move the stack pointer by an unknown 580d41b7b3SDerek Schuff // amount, and need to emit a frame pointer to restore the stack to where we 590d41b7b3SDerek Schuff // were on function entry. 600d41b7b3SDerek Schuff // If we already need a base pointer, we use that to fix up the stack pointer. 610d41b7b3SDerek Schuff // If there are no fixed-size objects, we would have no use of a frame 620d41b7b3SDerek Schuff // pointer, and thus should not emit one. 630d41b7b3SDerek Schuff bool HasFixedSizedObjects = MFI.getStackSize() > 0; 640d41b7b3SDerek Schuff bool NeedsFixedReference = !hasBP(MF) || HasFixedSizedObjects; 650d41b7b3SDerek Schuff 660d41b7b3SDerek Schuff return MFI.isFrameAddressTaken() || 670d41b7b3SDerek Schuff (MFI.hasVarSizedObjects() && NeedsFixedReference) || 680d41b7b3SDerek Schuff MFI.hasStackMap() || MFI.hasPatchPoint(); 6910e730a2SDan Gohman } 7010e730a2SDan Gohman 7110e730a2SDan Gohman /// Under normal circumstances, when a frame pointer is not required, we reserve 7210e730a2SDan Gohman /// argument space for call sites in the function immediately on entry to the 7310e730a2SDan Gohman /// current function. This eliminates the need for add/sub sp brackets around 7410e730a2SDan Gohman /// call sites. Returns true if the call frame is included as part of the stack 7510e730a2SDan Gohman /// frame. 7610e730a2SDan Gohman bool WebAssemblyFrameLowering::hasReservedCallFrame( 7710e730a2SDan Gohman const MachineFunction &MF) const { 78941a705bSMatthias Braun return !MF.getFrameInfo().hasVarSizedObjects(); 7910e730a2SDan Gohman } 8010e730a2SDan Gohman 81972fc358SHeejin Ahn // Returns true if this function needs a local user-space stack pointer for its 82972fc358SHeejin Ahn // local frame (not for exception handling). 83972fc358SHeejin Ahn bool WebAssemblyFrameLowering::needsSPForLocalFrame( 84972fc358SHeejin Ahn const MachineFunction &MF) const { 85972fc358SHeejin Ahn auto &MFI = MF.getFrameInfo(); 86972fc358SHeejin Ahn return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF); 87972fc358SHeejin Ahn } 88972fc358SHeejin Ahn 8978d19108SHeejin Ahn // In function with EH pads, we need to make a copy of the value of 90b9a539c0SWouter van Oortmerssen // __stack_pointer global in SP32/64 register, in order to use it when 91b9a539c0SWouter van Oortmerssen // restoring __stack_pointer after an exception is caught. 9278d19108SHeejin Ahn bool WebAssemblyFrameLowering::needsPrologForEH( 9378d19108SHeejin Ahn const MachineFunction &MF) const { 9478d19108SHeejin Ahn auto EHType = MF.getTarget().getMCAsmInfo()->getExceptionHandlingType(); 9578d19108SHeejin Ahn return EHType == ExceptionHandling::Wasm && 9678d19108SHeejin Ahn MF.getFunction().hasPersonalityFn() && MF.getFrameInfo().hasCalls(); 9778d19108SHeejin Ahn } 984b3bb213SDerek Schuff 994b3bb213SDerek Schuff /// Returns true if this function needs a local user-space stack pointer. 1004b3bb213SDerek Schuff /// Unlike a machine stack pointer, the wasm user stack pointer is a global 1014b3bb213SDerek Schuff /// variable, so it is loaded into a register in the prolog. 102bc6d8970SHeejin Ahn bool WebAssemblyFrameLowering::needsSP(const MachineFunction &MF) const { 103972fc358SHeejin Ahn return needsSPForLocalFrame(MF) || needsPrologForEH(MF); 1044b3bb213SDerek Schuff } 1054b3bb213SDerek Schuff 1064b3bb213SDerek Schuff /// Returns true if the local user-space stack pointer needs to be written back 107c4df1d18SHeejin Ahn /// to __stack_pointer global by this function (this is not meaningful if 108c4df1d18SHeejin Ahn /// needsSP is false). If false, the stack red zone can be used and only a local 109c4df1d18SHeejin Ahn /// SP is needed. 1104b3bb213SDerek Schuff bool WebAssemblyFrameLowering::needsSPWriteback( 111bc6d8970SHeejin Ahn const MachineFunction &MF) const { 112bc6d8970SHeejin Ahn auto &MFI = MF.getFrameInfo(); 113bc6d8970SHeejin Ahn assert(needsSP(MF)); 114972fc358SHeejin Ahn // When we don't need a local stack pointer for its local frame but only to 115972fc358SHeejin Ahn // support EH, we don't need to write SP back in the epilog, because we don't 116972fc358SHeejin Ahn // bump down the stack pointer in the prolog. We need to write SP back in the 117972fc358SHeejin Ahn // epilog only if 118972fc358SHeejin Ahn // 1. We need SP not only for EH support but also because we actually use 119972fc358SHeejin Ahn // stack or we have a frame address taken. 120972fc358SHeejin Ahn // 2. We cannot use the red zone. 121972fc358SHeejin Ahn bool CanUseRedZone = MFI.getStackSize() <= RedZoneSize && !MFI.hasCalls() && 122972fc358SHeejin Ahn !MF.getFunction().hasFnAttribute(Attribute::NoRedZone); 123972fc358SHeejin Ahn return needsSPForLocalFrame(MF) && !CanUseRedZone; 1244b3bb213SDerek Schuff } 1254b3bb213SDerek Schuff 126b9a539c0SWouter van Oortmerssen unsigned WebAssemblyFrameLowering::getSPReg(const MachineFunction &MF) { 127b9a539c0SWouter van Oortmerssen return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 128b9a539c0SWouter van Oortmerssen ? WebAssembly::SP64 129b9a539c0SWouter van Oortmerssen : WebAssembly::SP32; 130b9a539c0SWouter van Oortmerssen } 131b9a539c0SWouter van Oortmerssen 132b9a539c0SWouter van Oortmerssen unsigned WebAssemblyFrameLowering::getFPReg(const MachineFunction &MF) { 133b9a539c0SWouter van Oortmerssen return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 134b9a539c0SWouter van Oortmerssen ? WebAssembly::FP64 135b9a539c0SWouter van Oortmerssen : WebAssembly::FP32; 136b9a539c0SWouter van Oortmerssen } 137b9a539c0SWouter van Oortmerssen 138b9a539c0SWouter van Oortmerssen unsigned 139b9a539c0SWouter van Oortmerssen WebAssemblyFrameLowering::getOpcConst(const MachineFunction &MF) { 140b9a539c0SWouter van Oortmerssen return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 141b9a539c0SWouter van Oortmerssen ? WebAssembly::CONST_I64 142b9a539c0SWouter van Oortmerssen : WebAssembly::CONST_I32; 143b9a539c0SWouter van Oortmerssen } 144b9a539c0SWouter van Oortmerssen 145b9a539c0SWouter van Oortmerssen unsigned WebAssemblyFrameLowering::getOpcAdd(const MachineFunction &MF) { 146b9a539c0SWouter van Oortmerssen return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 147b9a539c0SWouter van Oortmerssen ? WebAssembly::ADD_I64 148b9a539c0SWouter van Oortmerssen : WebAssembly::ADD_I32; 149b9a539c0SWouter van Oortmerssen } 150b9a539c0SWouter van Oortmerssen 151b9a539c0SWouter van Oortmerssen unsigned WebAssemblyFrameLowering::getOpcSub(const MachineFunction &MF) { 152b9a539c0SWouter van Oortmerssen return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 153b9a539c0SWouter van Oortmerssen ? WebAssembly::SUB_I64 154b9a539c0SWouter van Oortmerssen : WebAssembly::SUB_I32; 155b9a539c0SWouter van Oortmerssen } 156b9a539c0SWouter van Oortmerssen 157b9a539c0SWouter van Oortmerssen unsigned WebAssemblyFrameLowering::getOpcAnd(const MachineFunction &MF) { 158b9a539c0SWouter van Oortmerssen return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 159b9a539c0SWouter van Oortmerssen ? WebAssembly::AND_I64 160b9a539c0SWouter van Oortmerssen : WebAssembly::AND_I32; 161b9a539c0SWouter van Oortmerssen } 162b9a539c0SWouter van Oortmerssen 163b9a539c0SWouter van Oortmerssen unsigned 164b9a539c0SWouter van Oortmerssen WebAssemblyFrameLowering::getOpcGlobGet(const MachineFunction &MF) { 165b9a539c0SWouter van Oortmerssen return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 166b9a539c0SWouter van Oortmerssen ? WebAssembly::GLOBAL_GET_I64 167b9a539c0SWouter van Oortmerssen : WebAssembly::GLOBAL_GET_I32; 168b9a539c0SWouter van Oortmerssen } 169b9a539c0SWouter van Oortmerssen 170b9a539c0SWouter van Oortmerssen unsigned 171b9a539c0SWouter van Oortmerssen WebAssemblyFrameLowering::getOpcGlobSet(const MachineFunction &MF) { 172b9a539c0SWouter van Oortmerssen return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 173b9a539c0SWouter van Oortmerssen ? WebAssembly::GLOBAL_SET_I64 174b9a539c0SWouter van Oortmerssen : WebAssembly::GLOBAL_SET_I32; 175b9a539c0SWouter van Oortmerssen } 176b9a539c0SWouter van Oortmerssen 17778d19108SHeejin Ahn void WebAssemblyFrameLowering::writeSPToGlobal( 17878d19108SHeejin Ahn unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, 17978d19108SHeejin Ahn MachineBasicBlock::iterator &InsertStore, const DebugLoc &DL) const { 18082607f56SDan Gohman const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 18182607f56SDan Gohman 182d08cd15fSDan Gohman const char *ES = "__stack_pointer"; 183d08cd15fSDan Gohman auto *SPSymbol = MF.createExternalSymbolName(ES); 184b9a539c0SWouter van Oortmerssen 185b9a539c0SWouter van Oortmerssen BuildMI(MBB, InsertStore, DL, TII->get(getOpcGlobSet(MF))) 186ef4c66c1SSam Clegg .addExternalSymbol(SPSymbol) 18782607f56SDan Gohman .addReg(SrcReg); 18882607f56SDan Gohman } 18927e3b8a6SDerek Schuff 190e1a2e90fSHans Wennborg MachineBasicBlock::iterator 191e1a2e90fSHans Wennborg WebAssemblyFrameLowering::eliminateCallFramePseudoInstr( 1928bb5f292SDerek Schuff MachineFunction &MF, MachineBasicBlock &MBB, 1938bb5f292SDerek Schuff MachineBasicBlock::iterator I) const { 1940d41b7b3SDerek Schuff assert(!I->getOperand(0).getImm() && (hasFP(MF) || hasBP(MF)) && 19527e3b8a6SDerek Schuff "Call frame pseudos should only be used for dynamic stack adjustment"); 196b9a539c0SWouter van Oortmerssen auto &ST = MF.getSubtarget<WebAssemblySubtarget>(); 197b9a539c0SWouter van Oortmerssen const auto *TII = ST.getInstrInfo(); 1984b3bb213SDerek Schuff if (I->getOpcode() == TII->getCallFrameDestroyOpcode() && 199bc6d8970SHeejin Ahn needsSPWriteback(MF)) { 20027e3b8a6SDerek Schuff DebugLoc DL = I->getDebugLoc(); 201b9a539c0SWouter van Oortmerssen writeSPToGlobal(getSPReg(MF), MF, MBB, I, DL); 20227e3b8a6SDerek Schuff } 203e1a2e90fSHans Wennborg return MBB.erase(I); 2048bb5f292SDerek Schuff } 2058bb5f292SDerek Schuff 2068bb5f292SDerek Schuff void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF, 2078bb5f292SDerek Schuff MachineBasicBlock &MBB) const { 2088bb5f292SDerek Schuff // TODO: Do ".setMIFlag(MachineInstr::FrameSetup)" on emitted instructions 209941a705bSMatthias Braun auto &MFI = MF.getFrameInfo(); 210941a705bSMatthias Braun assert(MFI.getCalleeSavedInfo().empty() && 2118bb5f292SDerek Schuff "WebAssembly should not have callee-saved registers"); 2126ea637afSDerek Schuff 213f208f631SHeejin Ahn if (!needsSP(MF)) 214f208f631SHeejin Ahn return; 215941a705bSMatthias Braun uint64_t StackSize = MFI.getStackSize(); 2168bb5f292SDerek Schuff 217b9a539c0SWouter van Oortmerssen auto &ST = MF.getSubtarget<WebAssemblySubtarget>(); 218b9a539c0SWouter van Oortmerssen const auto *TII = ST.getInstrInfo(); 2196ea637afSDerek Schuff auto &MRI = MF.getRegInfo(); 2208bb5f292SDerek Schuff 2218bb5f292SDerek Schuff auto InsertPt = MBB.begin(); 222d8ddf839SWouter van Oortmerssen while (InsertPt != MBB.end() && 223d8ddf839SWouter van Oortmerssen WebAssembly::isArgument(InsertPt->getOpcode())) 224d934cb88SDan Gohman ++InsertPt; 2258bb5f292SDerek Schuff DebugLoc DL; 2268bb5f292SDerek Schuff 2270cfb5f85SDan Gohman const TargetRegisterClass *PtrRC = 2280cfb5f85SDan Gohman MRI.getTargetRegisterInfo()->getPointerRegClass(MF); 229b9a539c0SWouter van Oortmerssen unsigned SPReg = getSPReg(MF); 2300d41b7b3SDerek Schuff if (StackSize) 2310d41b7b3SDerek Schuff SPReg = MRI.createVirtualRegister(PtrRC); 2329d24fb7fSSam Clegg 233d08cd15fSDan Gohman const char *ES = "__stack_pointer"; 234d08cd15fSDan Gohman auto *SPSymbol = MF.createExternalSymbolName(ES); 235b9a539c0SWouter van Oortmerssen BuildMI(MBB, InsertPt, DL, TII->get(getOpcGlobGet(MF)), SPReg) 236ef4c66c1SSam Clegg .addExternalSymbol(SPSymbol); 2376ea637afSDerek Schuff 2380d41b7b3SDerek Schuff bool HasBP = hasBP(MF); 2390d41b7b3SDerek Schuff if (HasBP) { 2400d41b7b3SDerek Schuff auto FI = MF.getInfo<WebAssemblyFunctionInfo>(); 24105c145d6SDaniel Sanders Register BasePtr = MRI.createVirtualRegister(PtrRC); 2420d41b7b3SDerek Schuff FI->setBasePointerVreg(BasePtr); 2430d41b7b3SDerek Schuff BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), BasePtr) 2440d41b7b3SDerek Schuff .addReg(SPReg); 2450d41b7b3SDerek Schuff } 2466ea637afSDerek Schuff if (StackSize) { 2476ea637afSDerek Schuff // Subtract the frame size 24805c145d6SDaniel Sanders Register OffsetReg = MRI.createVirtualRegister(PtrRC); 249b9a539c0SWouter van Oortmerssen BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), OffsetReg) 2506ea637afSDerek Schuff .addImm(StackSize); 251b9a539c0SWouter van Oortmerssen BuildMI(MBB, InsertPt, DL, TII->get(getOpcSub(MF)), getSPReg(MF)) 2526ea637afSDerek Schuff .addReg(SPReg) 2536ea637afSDerek Schuff .addReg(OffsetReg); 2546ea637afSDerek Schuff } 2550d41b7b3SDerek Schuff if (HasBP) { 25605c145d6SDaniel Sanders Register BitmaskReg = MRI.createVirtualRegister(PtrRC); 257d000655aSGuillaume Chatelet Align Alignment = MFI.getMaxAlign(); 258b9a539c0SWouter van Oortmerssen BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), BitmaskReg) 259b9a539c0SWouter van Oortmerssen .addImm((int64_t) ~(Alignment.value() - 1)); 260b9a539c0SWouter van Oortmerssen BuildMI(MBB, InsertPt, DL, TII->get(getOpcAnd(MF)), getSPReg(MF)) 261b9a539c0SWouter van Oortmerssen .addReg(getSPReg(MF)) 2620d41b7b3SDerek Schuff .addReg(BitmaskReg); 2630d41b7b3SDerek Schuff } 2646ea637afSDerek Schuff if (hasFP(MF)) { 2656ea637afSDerek Schuff // Unlike most conventional targets (where FP points to the saved FP), 2666ea637afSDerek Schuff // FP points to the bottom of the fixed-size locals, so we can use positive 2676ea637afSDerek Schuff // offsets in load/store instructions. 268b9a539c0SWouter van Oortmerssen BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), getFPReg(MF)) 269b9a539c0SWouter van Oortmerssen .addReg(getSPReg(MF)); 2706ea637afSDerek Schuff } 271bc6d8970SHeejin Ahn if (StackSize && needsSPWriteback(MF)) { 272b9a539c0SWouter van Oortmerssen writeSPToGlobal(getSPReg(MF), MF, MBB, InsertPt, DL); 2736ea637afSDerek Schuff } 2748bb5f292SDerek Schuff } 2758bb5f292SDerek Schuff 2769769debfSDerek Schuff void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF, 2779769debfSDerek Schuff MachineBasicBlock &MBB) const { 278bc6d8970SHeejin Ahn uint64_t StackSize = MF.getFrameInfo().getStackSize(); 279f208f631SHeejin Ahn if (!needsSP(MF) || !needsSPWriteback(MF)) 280f208f631SHeejin Ahn return; 281b9a539c0SWouter van Oortmerssen auto &ST = MF.getSubtarget<WebAssemblySubtarget>(); 282b9a539c0SWouter van Oortmerssen const auto *TII = ST.getInstrInfo(); 2839769debfSDerek Schuff auto &MRI = MF.getRegInfo(); 2849769debfSDerek Schuff auto InsertPt = MBB.getFirstTerminator(); 2859769debfSDerek Schuff DebugLoc DL; 2869769debfSDerek Schuff 2870cfb5f85SDan Gohman if (InsertPt != MBB.end()) 2889769debfSDerek Schuff DL = InsertPt->getDebugLoc(); 289450a8075SDan Gohman 2906ea637afSDerek Schuff // Restore the stack pointer. If we had fixed-size locals, add the offset 2916ea637afSDerek Schuff // subtracted in the prolog. 292d4207ba0SDerek Schuff unsigned SPReg = 0; 293b9a539c0SWouter van Oortmerssen unsigned SPFPReg = hasFP(MF) ? getFPReg(MF) : getSPReg(MF); 2940d41b7b3SDerek Schuff if (hasBP(MF)) { 2950d41b7b3SDerek Schuff auto FI = MF.getInfo<WebAssemblyFunctionInfo>(); 2960d41b7b3SDerek Schuff SPReg = FI->getBasePointerVreg(); 2970d41b7b3SDerek Schuff } else if (StackSize) { 2980cfb5f85SDan Gohman const TargetRegisterClass *PtrRC = 2990cfb5f85SDan Gohman MRI.getTargetRegisterInfo()->getPointerRegClass(MF); 30005c145d6SDaniel Sanders Register OffsetReg = MRI.createVirtualRegister(PtrRC); 301b9a539c0SWouter van Oortmerssen BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), OffsetReg) 3029769debfSDerek Schuff .addImm(StackSize); 303b9a539c0SWouter van Oortmerssen // In the epilog we don't need to write the result back to the SP32/64 304b9a539c0SWouter van Oortmerssen // physreg because it won't be used again. We can use a stackified register 305b9a539c0SWouter van Oortmerssen // instead. 3060cfb5f85SDan Gohman SPReg = MRI.createVirtualRegister(PtrRC); 307b9a539c0SWouter van Oortmerssen BuildMI(MBB, InsertPt, DL, TII->get(getOpcAdd(MF)), SPReg) 308b9a539c0SWouter van Oortmerssen .addReg(SPFPReg) 3099769debfSDerek Schuff .addReg(OffsetReg); 310d4207ba0SDerek Schuff } else { 311b9a539c0SWouter van Oortmerssen SPReg = SPFPReg; 3126ea637afSDerek Schuff } 3136ea637afSDerek Schuff 31420c9c443SHeejin Ahn writeSPToGlobal(SPReg, MF, MBB, InsertPt, DL); 31510e730a2SDan Gohman } 316ff171acfSDerek Schuff 317ff171acfSDerek Schuff TargetFrameLowering::DwarfFrameBase 318ff171acfSDerek Schuff WebAssemblyFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const { 319ff171acfSDerek Schuff DwarfFrameBase Loc; 320ff171acfSDerek Schuff Loc.Kind = DwarfFrameBase::WasmFrameBase; 321ff171acfSDerek Schuff const WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 322d966bf83SDerek Schuff if (needsSP(MF) && MFI.isFrameBaseVirtual()) { 323ff171acfSDerek Schuff unsigned LocalNum = MFI.getFrameBaseLocal(); 32448139ebcSWouter van Oortmerssen Loc.Location.WasmLoc = {WebAssembly::TI_LOCAL, LocalNum}; 325ff171acfSDerek Schuff } else { 326ff171acfSDerek Schuff // TODO: This should work on a breakpoint at a function with no frame, 327ff171acfSDerek Schuff // but probably won't work for traversing up the stack. 32848139ebcSWouter van Oortmerssen Loc.Location.WasmLoc = {WebAssembly::TI_GLOBAL_RELOC, 0}; 329ff171acfSDerek Schuff } 330ff171acfSDerek Schuff return Loc; 331ff171acfSDerek Schuff } 332