10b57cec5SDimitry Andric //===-- WebAssemblyFrameLowering.cpp - WebAssembly Frame Lowering ----------==// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// This file contains the WebAssembly implementation of 110b57cec5SDimitry Andric /// TargetFrameLowering class. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric /// On WebAssembly, there aren't a lot of things to do here. There are no 140b57cec5SDimitry Andric /// callee-saved registers to save, and no spill slots. 150b57cec5SDimitry Andric /// 160b57cec5SDimitry Andric /// The stack grows downward. 170b57cec5SDimitry Andric /// 180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "WebAssemblyFrameLowering.h" 210b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 22*5ffd83dbSDimitry Andric #include "WebAssembly.h" 230b57cec5SDimitry Andric #include "WebAssemblyInstrInfo.h" 240b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h" 250b57cec5SDimitry Andric #include "WebAssemblySubtarget.h" 260b57cec5SDimitry Andric #include "WebAssemblyTargetMachine.h" 270b57cec5SDimitry Andric #include "WebAssemblyUtilities.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 330b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 340b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 350b57cec5SDimitry Andric using namespace llvm; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-frame-info" 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric // TODO: wasm64 400b57cec5SDimitry Andric // TODO: Emit TargetOpcode::CFI_INSTRUCTION instructions 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric /// We need a base pointer in the case of having items on the stack that 430b57cec5SDimitry Andric /// require stricter alignment than the stack pointer itself. Because we need 440b57cec5SDimitry Andric /// to shift the stack pointer by some unknown amount to force the alignment, 450b57cec5SDimitry Andric /// we need to record the value of the stack pointer on entry to the function. 460b57cec5SDimitry Andric bool WebAssemblyFrameLowering::hasBP(const MachineFunction &MF) const { 470b57cec5SDimitry Andric const auto *RegInfo = 480b57cec5SDimitry Andric MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo(); 490b57cec5SDimitry Andric return RegInfo->needsStackRealignment(MF); 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric /// Return true if the specified function should have a dedicated frame pointer 530b57cec5SDimitry Andric /// register. 540b57cec5SDimitry Andric bool WebAssemblyFrameLowering::hasFP(const MachineFunction &MF) const { 550b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // When we have var-sized objects, we move the stack pointer by an unknown 580b57cec5SDimitry Andric // amount, and need to emit a frame pointer to restore the stack to where we 590b57cec5SDimitry Andric // were on function entry. 600b57cec5SDimitry Andric // If we already need a base pointer, we use that to fix up the stack pointer. 610b57cec5SDimitry Andric // If there are no fixed-size objects, we would have no use of a frame 620b57cec5SDimitry Andric // pointer, and thus should not emit one. 630b57cec5SDimitry Andric bool HasFixedSizedObjects = MFI.getStackSize() > 0; 640b57cec5SDimitry Andric bool NeedsFixedReference = !hasBP(MF) || HasFixedSizedObjects; 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric return MFI.isFrameAddressTaken() || 670b57cec5SDimitry Andric (MFI.hasVarSizedObjects() && NeedsFixedReference) || 680b57cec5SDimitry Andric MFI.hasStackMap() || MFI.hasPatchPoint(); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric /// Under normal circumstances, when a frame pointer is not required, we reserve 720b57cec5SDimitry Andric /// argument space for call sites in the function immediately on entry to the 730b57cec5SDimitry Andric /// current function. This eliminates the need for add/sub sp brackets around 740b57cec5SDimitry Andric /// call sites. Returns true if the call frame is included as part of the stack 750b57cec5SDimitry Andric /// frame. 760b57cec5SDimitry Andric bool WebAssemblyFrameLowering::hasReservedCallFrame( 770b57cec5SDimitry Andric const MachineFunction &MF) const { 780b57cec5SDimitry Andric return !MF.getFrameInfo().hasVarSizedObjects(); 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric // Returns true if this function needs a local user-space stack pointer for its 820b57cec5SDimitry Andric // local frame (not for exception handling). 830b57cec5SDimitry Andric bool WebAssemblyFrameLowering::needsSPForLocalFrame( 840b57cec5SDimitry Andric const MachineFunction &MF) const { 850b57cec5SDimitry Andric auto &MFI = MF.getFrameInfo(); 860b57cec5SDimitry Andric return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric // In function with EH pads, we need to make a copy of the value of 90*5ffd83dbSDimitry Andric // __stack_pointer global in SP32/64 register, in order to use it when 91*5ffd83dbSDimitry Andric // restoring __stack_pointer after an exception is caught. 920b57cec5SDimitry Andric bool WebAssemblyFrameLowering::needsPrologForEH( 930b57cec5SDimitry Andric const MachineFunction &MF) const { 940b57cec5SDimitry Andric auto EHType = MF.getTarget().getMCAsmInfo()->getExceptionHandlingType(); 950b57cec5SDimitry Andric return EHType == ExceptionHandling::Wasm && 960b57cec5SDimitry Andric MF.getFunction().hasPersonalityFn() && MF.getFrameInfo().hasCalls(); 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric /// Returns true if this function needs a local user-space stack pointer. 1000b57cec5SDimitry Andric /// Unlike a machine stack pointer, the wasm user stack pointer is a global 1010b57cec5SDimitry Andric /// variable, so it is loaded into a register in the prolog. 1020b57cec5SDimitry Andric bool WebAssemblyFrameLowering::needsSP(const MachineFunction &MF) const { 1030b57cec5SDimitry Andric return needsSPForLocalFrame(MF) || needsPrologForEH(MF); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric /// Returns true if the local user-space stack pointer needs to be written back 1070b57cec5SDimitry Andric /// to __stack_pointer global by this function (this is not meaningful if 1080b57cec5SDimitry Andric /// needsSP is false). If false, the stack red zone can be used and only a local 1090b57cec5SDimitry Andric /// SP is needed. 1100b57cec5SDimitry Andric bool WebAssemblyFrameLowering::needsSPWriteback( 1110b57cec5SDimitry Andric const MachineFunction &MF) const { 1120b57cec5SDimitry Andric auto &MFI = MF.getFrameInfo(); 1130b57cec5SDimitry Andric assert(needsSP(MF)); 1140b57cec5SDimitry Andric // When we don't need a local stack pointer for its local frame but only to 1150b57cec5SDimitry Andric // support EH, we don't need to write SP back in the epilog, because we don't 1160b57cec5SDimitry Andric // bump down the stack pointer in the prolog. We need to write SP back in the 1170b57cec5SDimitry Andric // epilog only if 1180b57cec5SDimitry Andric // 1. We need SP not only for EH support but also because we actually use 1190b57cec5SDimitry Andric // stack or we have a frame address taken. 1200b57cec5SDimitry Andric // 2. We cannot use the red zone. 1210b57cec5SDimitry Andric bool CanUseRedZone = MFI.getStackSize() <= RedZoneSize && !MFI.hasCalls() && 1220b57cec5SDimitry Andric !MF.getFunction().hasFnAttribute(Attribute::NoRedZone); 1230b57cec5SDimitry Andric return needsSPForLocalFrame(MF) && !CanUseRedZone; 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric 126*5ffd83dbSDimitry Andric unsigned WebAssemblyFrameLowering::getSPReg(const MachineFunction &MF) { 127*5ffd83dbSDimitry Andric return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 128*5ffd83dbSDimitry Andric ? WebAssembly::SP64 129*5ffd83dbSDimitry Andric : WebAssembly::SP32; 130*5ffd83dbSDimitry Andric } 131*5ffd83dbSDimitry Andric 132*5ffd83dbSDimitry Andric unsigned WebAssemblyFrameLowering::getFPReg(const MachineFunction &MF) { 133*5ffd83dbSDimitry Andric return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 134*5ffd83dbSDimitry Andric ? WebAssembly::FP64 135*5ffd83dbSDimitry Andric : WebAssembly::FP32; 136*5ffd83dbSDimitry Andric } 137*5ffd83dbSDimitry Andric 138*5ffd83dbSDimitry Andric unsigned 139*5ffd83dbSDimitry Andric WebAssemblyFrameLowering::getOpcConst(const MachineFunction &MF) { 140*5ffd83dbSDimitry Andric return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 141*5ffd83dbSDimitry Andric ? WebAssembly::CONST_I64 142*5ffd83dbSDimitry Andric : WebAssembly::CONST_I32; 143*5ffd83dbSDimitry Andric } 144*5ffd83dbSDimitry Andric 145*5ffd83dbSDimitry Andric unsigned WebAssemblyFrameLowering::getOpcAdd(const MachineFunction &MF) { 146*5ffd83dbSDimitry Andric return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 147*5ffd83dbSDimitry Andric ? WebAssembly::ADD_I64 148*5ffd83dbSDimitry Andric : WebAssembly::ADD_I32; 149*5ffd83dbSDimitry Andric } 150*5ffd83dbSDimitry Andric 151*5ffd83dbSDimitry Andric unsigned WebAssemblyFrameLowering::getOpcSub(const MachineFunction &MF) { 152*5ffd83dbSDimitry Andric return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 153*5ffd83dbSDimitry Andric ? WebAssembly::SUB_I64 154*5ffd83dbSDimitry Andric : WebAssembly::SUB_I32; 155*5ffd83dbSDimitry Andric } 156*5ffd83dbSDimitry Andric 157*5ffd83dbSDimitry Andric unsigned WebAssemblyFrameLowering::getOpcAnd(const MachineFunction &MF) { 158*5ffd83dbSDimitry Andric return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 159*5ffd83dbSDimitry Andric ? WebAssembly::AND_I64 160*5ffd83dbSDimitry Andric : WebAssembly::AND_I32; 161*5ffd83dbSDimitry Andric } 162*5ffd83dbSDimitry Andric 163*5ffd83dbSDimitry Andric unsigned 164*5ffd83dbSDimitry Andric WebAssemblyFrameLowering::getOpcGlobGet(const MachineFunction &MF) { 165*5ffd83dbSDimitry Andric return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 166*5ffd83dbSDimitry Andric ? WebAssembly::GLOBAL_GET_I64 167*5ffd83dbSDimitry Andric : WebAssembly::GLOBAL_GET_I32; 168*5ffd83dbSDimitry Andric } 169*5ffd83dbSDimitry Andric 170*5ffd83dbSDimitry Andric unsigned 171*5ffd83dbSDimitry Andric WebAssemblyFrameLowering::getOpcGlobSet(const MachineFunction &MF) { 172*5ffd83dbSDimitry Andric return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() 173*5ffd83dbSDimitry Andric ? WebAssembly::GLOBAL_SET_I64 174*5ffd83dbSDimitry Andric : WebAssembly::GLOBAL_SET_I32; 175*5ffd83dbSDimitry Andric } 176*5ffd83dbSDimitry Andric 1770b57cec5SDimitry Andric void WebAssemblyFrameLowering::writeSPToGlobal( 1780b57cec5SDimitry Andric unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, 1790b57cec5SDimitry Andric MachineBasicBlock::iterator &InsertStore, const DebugLoc &DL) const { 1800b57cec5SDimitry Andric const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric const char *ES = "__stack_pointer"; 1830b57cec5SDimitry Andric auto *SPSymbol = MF.createExternalSymbolName(ES); 184*5ffd83dbSDimitry Andric 185*5ffd83dbSDimitry Andric BuildMI(MBB, InsertStore, DL, TII->get(getOpcGlobSet(MF))) 1860b57cec5SDimitry Andric .addExternalSymbol(SPSymbol) 1870b57cec5SDimitry Andric .addReg(SrcReg); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric MachineBasicBlock::iterator 1910b57cec5SDimitry Andric WebAssemblyFrameLowering::eliminateCallFramePseudoInstr( 1920b57cec5SDimitry Andric MachineFunction &MF, MachineBasicBlock &MBB, 1930b57cec5SDimitry Andric MachineBasicBlock::iterator I) const { 1940b57cec5SDimitry Andric assert(!I->getOperand(0).getImm() && (hasFP(MF) || hasBP(MF)) && 1950b57cec5SDimitry Andric "Call frame pseudos should only be used for dynamic stack adjustment"); 196*5ffd83dbSDimitry Andric auto &ST = MF.getSubtarget<WebAssemblySubtarget>(); 197*5ffd83dbSDimitry Andric const auto *TII = ST.getInstrInfo(); 1980b57cec5SDimitry Andric if (I->getOpcode() == TII->getCallFrameDestroyOpcode() && 1990b57cec5SDimitry Andric needsSPWriteback(MF)) { 2000b57cec5SDimitry Andric DebugLoc DL = I->getDebugLoc(); 201*5ffd83dbSDimitry Andric writeSPToGlobal(getSPReg(MF), MF, MBB, I, DL); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric return MBB.erase(I); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF, 2070b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 2080b57cec5SDimitry Andric // TODO: Do ".setMIFlag(MachineInstr::FrameSetup)" on emitted instructions 2090b57cec5SDimitry Andric auto &MFI = MF.getFrameInfo(); 2100b57cec5SDimitry Andric assert(MFI.getCalleeSavedInfo().empty() && 2110b57cec5SDimitry Andric "WebAssembly should not have callee-saved registers"); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric if (!needsSP(MF)) 2140b57cec5SDimitry Andric return; 2150b57cec5SDimitry Andric uint64_t StackSize = MFI.getStackSize(); 2160b57cec5SDimitry Andric 217*5ffd83dbSDimitry Andric auto &ST = MF.getSubtarget<WebAssemblySubtarget>(); 218*5ffd83dbSDimitry Andric const auto *TII = ST.getInstrInfo(); 2190b57cec5SDimitry Andric auto &MRI = MF.getRegInfo(); 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric auto InsertPt = MBB.begin(); 2220b57cec5SDimitry Andric while (InsertPt != MBB.end() && 2230b57cec5SDimitry Andric WebAssembly::isArgument(InsertPt->getOpcode())) 2240b57cec5SDimitry Andric ++InsertPt; 2250b57cec5SDimitry Andric DebugLoc DL; 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric const TargetRegisterClass *PtrRC = 2280b57cec5SDimitry Andric MRI.getTargetRegisterInfo()->getPointerRegClass(MF); 229*5ffd83dbSDimitry Andric unsigned SPReg = getSPReg(MF); 2300b57cec5SDimitry Andric if (StackSize) 2310b57cec5SDimitry Andric SPReg = MRI.createVirtualRegister(PtrRC); 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric const char *ES = "__stack_pointer"; 2340b57cec5SDimitry Andric auto *SPSymbol = MF.createExternalSymbolName(ES); 235*5ffd83dbSDimitry Andric BuildMI(MBB, InsertPt, DL, TII->get(getOpcGlobGet(MF)), SPReg) 2360b57cec5SDimitry Andric .addExternalSymbol(SPSymbol); 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric bool HasBP = hasBP(MF); 2390b57cec5SDimitry Andric if (HasBP) { 2400b57cec5SDimitry Andric auto FI = MF.getInfo<WebAssemblyFunctionInfo>(); 2418bcb0991SDimitry Andric Register BasePtr = MRI.createVirtualRegister(PtrRC); 2420b57cec5SDimitry Andric FI->setBasePointerVreg(BasePtr); 2430b57cec5SDimitry Andric BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), BasePtr) 2440b57cec5SDimitry Andric .addReg(SPReg); 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric if (StackSize) { 2470b57cec5SDimitry Andric // Subtract the frame size 2488bcb0991SDimitry Andric Register OffsetReg = MRI.createVirtualRegister(PtrRC); 249*5ffd83dbSDimitry Andric BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), OffsetReg) 2500b57cec5SDimitry Andric .addImm(StackSize); 251*5ffd83dbSDimitry Andric BuildMI(MBB, InsertPt, DL, TII->get(getOpcSub(MF)), getSPReg(MF)) 2520b57cec5SDimitry Andric .addReg(SPReg) 2530b57cec5SDimitry Andric .addReg(OffsetReg); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric if (HasBP) { 2568bcb0991SDimitry Andric Register BitmaskReg = MRI.createVirtualRegister(PtrRC); 257*5ffd83dbSDimitry Andric Align Alignment = MFI.getMaxAlign(); 258*5ffd83dbSDimitry Andric BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), BitmaskReg) 259*5ffd83dbSDimitry Andric .addImm((int64_t) ~(Alignment.value() - 1)); 260*5ffd83dbSDimitry Andric BuildMI(MBB, InsertPt, DL, TII->get(getOpcAnd(MF)), getSPReg(MF)) 261*5ffd83dbSDimitry Andric .addReg(getSPReg(MF)) 2620b57cec5SDimitry Andric .addReg(BitmaskReg); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric if (hasFP(MF)) { 2650b57cec5SDimitry Andric // Unlike most conventional targets (where FP points to the saved FP), 2660b57cec5SDimitry Andric // FP points to the bottom of the fixed-size locals, so we can use positive 2670b57cec5SDimitry Andric // offsets in load/store instructions. 268*5ffd83dbSDimitry Andric BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), getFPReg(MF)) 269*5ffd83dbSDimitry Andric .addReg(getSPReg(MF)); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric if (StackSize && needsSPWriteback(MF)) { 272*5ffd83dbSDimitry Andric writeSPToGlobal(getSPReg(MF), MF, MBB, InsertPt, DL); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF, 2770b57cec5SDimitry Andric MachineBasicBlock &MBB) const { 2780b57cec5SDimitry Andric uint64_t StackSize = MF.getFrameInfo().getStackSize(); 2790b57cec5SDimitry Andric if (!needsSP(MF) || !needsSPWriteback(MF)) 2800b57cec5SDimitry Andric return; 281*5ffd83dbSDimitry Andric auto &ST = MF.getSubtarget<WebAssemblySubtarget>(); 282*5ffd83dbSDimitry Andric const auto *TII = ST.getInstrInfo(); 2830b57cec5SDimitry Andric auto &MRI = MF.getRegInfo(); 2840b57cec5SDimitry Andric auto InsertPt = MBB.getFirstTerminator(); 2850b57cec5SDimitry Andric DebugLoc DL; 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric if (InsertPt != MBB.end()) 2880b57cec5SDimitry Andric DL = InsertPt->getDebugLoc(); 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric // Restore the stack pointer. If we had fixed-size locals, add the offset 2910b57cec5SDimitry Andric // subtracted in the prolog. 2920b57cec5SDimitry Andric unsigned SPReg = 0; 293*5ffd83dbSDimitry Andric unsigned SPFPReg = hasFP(MF) ? getFPReg(MF) : getSPReg(MF); 2940b57cec5SDimitry Andric if (hasBP(MF)) { 2950b57cec5SDimitry Andric auto FI = MF.getInfo<WebAssemblyFunctionInfo>(); 2960b57cec5SDimitry Andric SPReg = FI->getBasePointerVreg(); 2970b57cec5SDimitry Andric } else if (StackSize) { 2980b57cec5SDimitry Andric const TargetRegisterClass *PtrRC = 2990b57cec5SDimitry Andric MRI.getTargetRegisterInfo()->getPointerRegClass(MF); 3008bcb0991SDimitry Andric Register OffsetReg = MRI.createVirtualRegister(PtrRC); 301*5ffd83dbSDimitry Andric BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), OffsetReg) 3020b57cec5SDimitry Andric .addImm(StackSize); 303*5ffd83dbSDimitry Andric // In the epilog we don't need to write the result back to the SP32/64 304*5ffd83dbSDimitry Andric // physreg because it won't be used again. We can use a stackified register 305*5ffd83dbSDimitry Andric // instead. 3060b57cec5SDimitry Andric SPReg = MRI.createVirtualRegister(PtrRC); 307*5ffd83dbSDimitry Andric BuildMI(MBB, InsertPt, DL, TII->get(getOpcAdd(MF)), SPReg) 308*5ffd83dbSDimitry Andric .addReg(SPFPReg) 3090b57cec5SDimitry Andric .addReg(OffsetReg); 3100b57cec5SDimitry Andric } else { 311*5ffd83dbSDimitry Andric SPReg = SPFPReg; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric writeSPToGlobal(SPReg, MF, MBB, InsertPt, DL); 3150b57cec5SDimitry Andric } 316*5ffd83dbSDimitry Andric 317*5ffd83dbSDimitry Andric TargetFrameLowering::DwarfFrameBase 318*5ffd83dbSDimitry Andric WebAssemblyFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const { 319*5ffd83dbSDimitry Andric DwarfFrameBase Loc; 320*5ffd83dbSDimitry Andric Loc.Kind = DwarfFrameBase::WasmFrameBase; 321*5ffd83dbSDimitry Andric const WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 322*5ffd83dbSDimitry Andric if (needsSP(MF) && MFI.isFrameBaseVirtual()) { 323*5ffd83dbSDimitry Andric unsigned LocalNum = MFI.getFrameBaseLocal(); 324*5ffd83dbSDimitry Andric Loc.Location.WasmLoc = {WebAssembly::TI_LOCAL, LocalNum}; 325*5ffd83dbSDimitry Andric } else { 326*5ffd83dbSDimitry Andric // TODO: This should work on a breakpoint at a function with no frame, 327*5ffd83dbSDimitry Andric // but probably won't work for traversing up the stack. 328*5ffd83dbSDimitry Andric Loc.Location.WasmLoc = {WebAssembly::TI_GLOBAL_RELOC, 0}; 329*5ffd83dbSDimitry Andric } 330*5ffd83dbSDimitry Andric return Loc; 331*5ffd83dbSDimitry Andric } 332