diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h --- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -219,6 +219,18 @@ unsigned WeightLimit; }; +struct FrameBaseLocation { + enum LocationKind { Register, CFA, TargetIndex } Kind; + struct TargetIndexInfo { + unsigned Index; + signed Offset; + }; + union { + unsigned Reg; + TargetIndexInfo TI; + }; +}; + /// TargetRegisterInfo base class - We assume that the target defines a static /// array of TargetRegisterDesc objects that represent all of the machine /// registers that the target has. As such, we simply have to track a pointer @@ -959,6 +971,14 @@ /// for values allocated in the current stack frame. virtual Register getFrameRegister(const MachineFunction &MF) const = 0; + virtual FrameBaseLocation + getFrameBaseLocation(const MachineFunction &MF) const { + FrameBaseLocation Loc; + Loc.Kind = FrameBaseLocation::Register; + Loc.Reg = getFrameRegister(MF); + return Loc; + } + /// Mark a register and all its aliases as reserved in the given set. void markSuperRegs(BitVector &RegisterSet, unsigned Reg) const; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -391,13 +391,24 @@ // Only include DW_AT_frame_base in full debug info if (!includeMinimalInlineScopes()) { - if (Asm->MF->getTarget().getTargetTriple().isNVPTX()) { + const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo(); + auto FBL = RI->getFrameBaseLocation(*Asm->MF); + if (FBL.Kind == FrameBaseLocation::CFA) { DIELoc *Loc = new (DIEValueAllocator) DIELoc; addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_call_frame_cfa); addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc); + } else if (FBL.Kind == FrameBaseLocation::TargetIndex) { + if (FBL.TI.Offset >= 0) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc; + DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); + DIExpressionCursor Cursor({}); + DwarfExpr.addTargetIndexLocation(FBL.TI.Index, FBL.TI.Offset); + DwarfExpr.addExpression(std::move(Cursor)); + addBlock(*SPDie, dwarf::DW_AT_frame_base, DwarfExpr.finalize()); + } } else { - const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo(); - MachineLocation Location(RI->getFrameRegister(*Asm->MF)); + assert(FBL.Kind == FrameBaseLocation::Register); + MachineLocation Location(FBL.Reg); if (Register::isPhysicalRegister(Location.getReg())) addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); } diff --git a/llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h b/llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h --- a/llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h +++ b/llvm/lib/Target/NVPTX/NVPTXRegisterInfo.h @@ -44,6 +44,13 @@ Register getFrameRegister(const MachineFunction &MF) const override; + FrameBaseLocation + getFrameBaseLocation(const MachineFunction &MF) const override { + FrameBaseLocation Loc; + Loc.Kind = FrameBaseLocation::CFA; + return Loc; + } + ManagedStringPool *getStrPool() const { return const_cast(&ManagedStrPool); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp @@ -385,6 +385,16 @@ Changed = true; } + // Recording in which local we store SP. Usually global.set precede with TEE or GET. + if (MachineInstr *GI = MFI.SPInstr) { + auto TI = std::prev(GI->getIterator()); + if (TI->getOpcode() == WebAssembly::LOCAL_TEE_I32 || + TI->getOpcode() == WebAssembly::LOCAL_TEE_I64 || + TI->getOpcode() == WebAssembly::LOCAL_GET_I32 || + TI->getOpcode() == WebAssembly::LOCAL_GET_I64) + MFI.SPLocal = TI->getOperand(1).getImm(); + } + #ifndef NDEBUG // Assert that all registers have been stackified at this point. for (const MachineBasicBlock &MBB : MF) { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h @@ -19,6 +19,7 @@ namespace llvm { class MachineFrameInfo; +class MachineInstr; class WebAssemblyFrameLowering final : public TargetFrameLowering { public: @@ -48,7 +49,7 @@ bool needsPrologForEH(const MachineFunction &MF) const; /// Write SP back to __stack_pointer global. - void writeSPToGlobal(unsigned SrcReg, MachineFunction &MF, + MachineInstr *writeSPToGlobal(unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator &InsertStore, const DebugLoc &DL) const; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp @@ -26,6 +26,7 @@ #include "WebAssemblyUtilities.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -122,14 +123,14 @@ return needsSPForLocalFrame(MF) && !CanUseRedZone; } -void WebAssemblyFrameLowering::writeSPToGlobal( +MachineInstr *WebAssemblyFrameLowering::writeSPToGlobal( unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator &InsertStore, const DebugLoc &DL) const { const auto *TII = MF.getSubtarget().getInstrInfo(); const char *ES = "__stack_pointer"; auto *SPSymbol = MF.createExternalSymbolName(ES); - BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::GLOBAL_SET_I32)) + return BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::GLOBAL_SET_I32)) .addExternalSymbol(SPSymbol) .addReg(SrcReg); } @@ -218,7 +219,8 @@ .addReg(WebAssembly::SP32); } if (StackSize && needsSPWriteback(MF)) { - writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPt, DL); + auto FI = MF.getInfo(); + FI->SPInstr = writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPt, DL); } } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -27,6 +27,8 @@ struct WebAssemblyFunctionInfo; } +class MachineInstr; + /// This class is derived from MachineFunctionInfo and contains private /// WebAssembly-specific information for each MachineFunction. class WebAssemblyFunctionInfo final : public MachineFunctionInfo { @@ -60,7 +62,8 @@ bool CFGStackified = false; public: - explicit WebAssemblyFunctionInfo(MachineFunction &MF) : MF(MF) {} + explicit WebAssemblyFunctionInfo(MachineFunction &MF) + : MF(MF), SPInstr(nullptr), SPLocal(-1) {} ~WebAssemblyFunctionInfo() override; void initializeBaseYamlFields(const yaml::WebAssemblyFunctionInfo &YamlMFI); @@ -134,6 +137,9 @@ bool isCFGStackified() const { return CFGStackified; } void setCFGStackified(bool Value = true) { CFGStackified = Value; } + + MachineInstr* SPInstr; + unsigned SPLocal; }; void computeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h @@ -41,6 +41,9 @@ // Debug information queries. Register getFrameRegister(const MachineFunction &MF) const override; + FrameBaseLocation + getFrameBaseLocation(const MachineFunction &MF) const override; + const TargetRegisterClass * getPointerRegClass(const MachineFunction &MF, unsigned Kind = 0) const override; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp @@ -140,6 +140,16 @@ return Regs[TFI->hasFP(MF)][TT.isArch64Bit()]; } +FrameBaseLocation +WebAssemblyRegisterInfo::getFrameBaseLocation(const MachineFunction &MF) const { + const WebAssemblyFunctionInfo &MFI = *MF.getInfo(); + FrameBaseLocation Loc; + Loc.Kind = FrameBaseLocation::TargetIndex; + signed Local = MFI.SPInstr != nullptr ? MFI.SPLocal : -1; + Loc.TI = {0, Local}; + return Loc; +} + const TargetRegisterClass * WebAssemblyRegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind) const {