static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator &InsertAddr, MachineBasicBlock::iterator &InsertStore, const DebugLoc &DL) { const char *ES = "__stack_pointer"; auto *SPSymbol = MF.createExternalSymbolName(ES); MachineRegisterInfo &MRI = MF.getRegInfo(); const TargetRegisterClass *PtrRC = MRI.getTargetRegisterInfo()->getPointerRegClass(MF); unsigned Zero = MRI.createVirtualRegister(PtrRC); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), Zero) .addImm(0); MachineMemOperand *MMO = MF.getMachineMemOperand( MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)), MachineMemOperand::MOStore, 4, 4); BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32)) .addImm(2) // p2align .addExternalSymbol(SPSymbol) .addReg(Zero) .addReg(SrcReg) .addMemOperand(MMO); }
void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { uint64_t StackSize = MF.getFrameInfo()->getStackSize(); if (!StackSize) return; const auto *TII = MF.getSubtarget().getInstrInfo(); auto &MRI = MF.getRegInfo(); unsigned OffsetReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); auto InsertPt = MBB.getFirstTerminator(); DebugLoc DL; if (InsertPt != MBB.end()) { DL = InsertPt->getDebugLoc(); } // Restore the stack pointer. Without FP its value is just SP32 - stacksize BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg) .addImm(StackSize); auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer"); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::ADD_I32), WebAssembly::SP32) .addReg(WebAssembly::SP32) .addReg(OffsetReg); // Re-use OffsetReg to hold the address of the stacktop BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg) .addExternalSymbol(SPSymbol); auto *MMO = new MachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOStore, 4, 4); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::STORE_I32), WebAssembly::SP32) .addImm(0) .addReg(OffsetReg) .addReg(WebAssembly::SP32) .addMemOperand(MMO); }
void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { // TODO: Do ".setMIFlag(MachineInstr::FrameSetup)" on emitted instructions auto &MFI = MF.getFrameInfo(); assert(MFI.getCalleeSavedInfo().empty() && "WebAssembly should not have callee-saved registers"); if (!needsSP(MF, MFI)) return; uint64_t StackSize = MFI.getStackSize(); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); auto &MRI = MF.getRegInfo(); auto InsertPt = MBB.begin(); DebugLoc DL; const TargetRegisterClass *PtrRC = MRI.getTargetRegisterInfo()->getPointerRegClass(MF); unsigned Zero = MRI.createVirtualRegister(PtrRC); unsigned SPReg = MRI.createVirtualRegister(PtrRC); const char *ES = "__stack_pointer"; auto *SPSymbol = MF.createExternalSymbolName(ES); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), Zero) .addImm(0); MachineMemOperand *LoadMMO = MF.getMachineMemOperand( MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)), MachineMemOperand::MOLoad, 4, 4); // Load the SP value. BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), StackSize ? SPReg : (unsigned)WebAssembly::SP32) .addImm(2) // p2align .addExternalSymbol(SPSymbol) .addReg(Zero) // addr .addMemOperand(LoadMMO); if (StackSize) { // Subtract the frame size unsigned OffsetReg = MRI.createVirtualRegister(PtrRC); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg) .addImm(StackSize); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::SUB_I32), WebAssembly::SP32) .addReg(SPReg) .addReg(OffsetReg); } if (hasFP(MF)) { // Unlike most conventional targets (where FP points to the saved FP), // FP points to the bottom of the fixed-size locals, so we can use positive // offsets in load/store instructions. BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), WebAssembly::FP32) .addReg(WebAssembly::SP32); } if (StackSize && needsSPWriteback(MF, MFI)) { writeSPToMemory(WebAssembly::SP32, MF, MBB, InsertPt, InsertPt, DL); } }
static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator &InsertAddr, MachineBasicBlock::iterator &InsertStore, const DebugLoc &DL) { const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); const char *ES = "__stack_pointer"; auto *SPSymbol = MF.createExternalSymbolName(ES); BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::SET_GLOBAL_I32)) .addExternalSymbol(SPSymbol) .addReg(SrcReg); }
/// Adjust the stack pointer by a constant amount. static void adjustStackPointer(unsigned StackSize, bool AdjustUp, MachineFunction& MF, MachineBasicBlock& MBB, const TargetInstrInfo* TII, MachineBasicBlock::iterator InsertPt, const DebugLoc& DL) { auto &MRI = MF.getRegInfo(); unsigned SPReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer"); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), SPReg) .addExternalSymbol(SPSymbol); // This MachinePointerInfo should reference __stack_pointer as well but // doesn't because MachinePointerInfo() takes a GV which we don't have for // __stack_pointer. TODO: check if PseudoSourceValue::ExternalSymbolCallEntry // is appropriate instead. (likewise for EmitEpologue below) auto *LoadMMO = new MachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOLoad, 4, 4); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), SPReg) .addImm(0) .addReg(SPReg) .addImm(2) // p2align .addMemOperand(LoadMMO); // Add/Subtract the frame size unsigned OffsetReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg) .addImm(StackSize); BuildMI(MBB, InsertPt, DL, TII->get(AdjustUp ? WebAssembly::ADD_I32 : WebAssembly::SUB_I32), WebAssembly::SP32) .addReg(SPReg) .addReg(OffsetReg); // The SP32 register now has the new stacktop. Also write it back to memory. BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg) .addExternalSymbol(SPSymbol); auto *MMO = new MachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOStore, 4, 4); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::STORE_I32), WebAssembly::SP32) .addImm(0) .addReg(OffsetReg) .addImm(2) // p2align .addReg(WebAssembly::SP32) .addMemOperand(MMO); }
static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator &InsertAddr, MachineBasicBlock::iterator &InsertStore, DebugLoc DL) { auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer"); unsigned SPAddr = MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), SPAddr) .addExternalSymbol(SPSymbol); auto *MMO = new MachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOStore, 4, 4); BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32), SrcReg) .addImm(0) .addReg(SPAddr) .addImm(2) // p2align .addReg(SrcReg) .addMemOperand(MMO); MF.getInfo<WebAssemblyFunctionInfo>()->stackifyVReg(SPAddr); }
void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { // TODO: Do ".setMIFlag(MachineInstr::FrameSetup)" on emitted instructions auto &MFI = MF.getFrameInfo(); assert(MFI.getCalleeSavedInfo().empty() && "WebAssembly should not have callee-saved registers"); if (!needsSP(MF, MFI)) return; uint64_t StackSize = MFI.getStackSize(); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); auto &MRI = MF.getRegInfo(); auto InsertPt = MBB.begin(); while (InsertPt != MBB.end() && WebAssembly::isArgument(*InsertPt)) ++InsertPt; DebugLoc DL; const TargetRegisterClass *PtrRC = MRI.getTargetRegisterInfo()->getPointerRegClass(MF); unsigned SPReg = WebAssembly::SP32; if (StackSize) SPReg = MRI.createVirtualRegister(PtrRC); const char *ES = "__stack_pointer"; auto *SPSymbol = MF.createExternalSymbolName(ES); if (MF.getSubtarget<WebAssemblySubtarget>() .getTargetTriple().isOSBinFormatELF()) { unsigned Zero = MRI.createVirtualRegister(PtrRC); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), Zero) .addImm(0); MachineMemOperand *LoadMMO = MF.getMachineMemOperand( MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)), MachineMemOperand::MOLoad, 4, 4); // Load the SP value. BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), SPReg) .addImm(2) // p2align .addExternalSymbol(SPSymbol) .addReg(Zero) // addr .addMemOperand(LoadMMO); } else { BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::GET_GLOBAL_I32), SPReg) .addExternalSymbol(SPSymbol); } bool HasBP = hasBP(MF); if (HasBP) { auto FI = MF.getInfo<WebAssemblyFunctionInfo>(); unsigned BasePtr = MRI.createVirtualRegister(PtrRC); FI->setBasePointerVreg(BasePtr); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), BasePtr) .addReg(SPReg); } if (StackSize) { // Subtract the frame size unsigned OffsetReg = MRI.createVirtualRegister(PtrRC); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg) .addImm(StackSize); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::SUB_I32), WebAssembly::SP32) .addReg(SPReg) .addReg(OffsetReg); } if (HasBP) { unsigned BitmaskReg = MRI.createVirtualRegister(PtrRC); unsigned Alignment = MFI.getMaxAlignment(); assert((1u << countTrailingZeros(Alignment)) == Alignment && "Alignment must be a power of 2"); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), BitmaskReg) .addImm((int)~(Alignment - 1)); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::AND_I32), WebAssembly::SP32) .addReg(WebAssembly::SP32) .addReg(BitmaskReg); } if (hasFP(MF)) { // Unlike most conventional targets (where FP points to the saved FP), // FP points to the bottom of the fixed-size locals, so we can use positive // offsets in load/store instructions. BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), WebAssembly::FP32) .addReg(WebAssembly::SP32); } if (StackSize && needsSPWriteback(MF, MFI)) { writeSPToMemory(WebAssembly::SP32, MF, MBB, InsertPt, InsertPt, DL); } }
void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { // TODO: Do ".setMIFlag(MachineInstr::FrameSetup)" on emitted instructions auto *MFI = MF.getFrameInfo(); assert(MFI->getCalleeSavedInfo().empty() && "WebAssembly should not have callee-saved registers"); auto *WFI = MF.getInfo<WebAssemblyFunctionInfo>(); if (!needsSP(MF, *MFI)) return; uint64_t StackSize = MFI->getStackSize(); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); auto &MRI = MF.getRegInfo(); auto InsertPt = MBB.begin(); DebugLoc DL; unsigned SPAddr = MRI.createVirtualRegister(&WebAssembly::I32RegClass); unsigned SPReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer"); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), SPAddr) .addExternalSymbol(SPSymbol); // This MachinePointerInfo should reference __stack_pointer as well but // doesn't because MachinePointerInfo() takes a GV which we don't have for // __stack_pointer. TODO: check if PseudoSourceValue::ExternalSymbolCallEntry // is appropriate instead. (likewise for EmitEpologue below) auto *LoadMMO = new MachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOLoad, 4, 4); // Load the SP value. BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), StackSize ? SPReg : (unsigned)WebAssembly::SP32) .addImm(0) // offset .addReg(SPAddr) // addr .addImm(2) // p2align .addMemOperand(LoadMMO); WFI->stackifyVReg(SPAddr); if (StackSize) { // Subtract the frame size unsigned OffsetReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg) .addImm(StackSize); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::SUB_I32), WebAssembly::SP32) .addReg(SPReg) .addReg(OffsetReg); WFI->stackifyVReg(OffsetReg); WFI->stackifyVReg(SPReg); } if (hasFP(MF)) { // Unlike most conventional targets (where FP points to the saved FP), // FP points to the bottom of the fixed-size locals, so we can use positive // offsets in load/store instructions. BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY_LOCAL_I32), WebAssembly::FP32) .addReg(WebAssembly::SP32); } if (StackSize && needsSPWriteback(MF, *MFI)) { writeSPToMemory(WebAssembly::SP32, MF, MBB, InsertPt, InsertPt, DL); } }