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 @@ -411,8 +411,13 @@ } else { const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); - if (Register::isPhysicalRegister(Location.getReg())) + if (Register::isPhysicalRegister(Location.getReg())) { addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); + } else { + WebAssemblyFunctionInfo &MFI = *MF.getInfo(); // oops, layering violation + // I'd like to encode a dwarf op_wasm_location here to encode the local value using something like + // MFI->getFrameBaseLocal() but that's in the wasm backend and not target-independent. + } } } 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 @@ -72,10 +72,14 @@ /// Return a local id number for the given register, assigning it a new one /// if it doesn't yet have one. static unsigned getLocalId(DenseMap &Reg2Local, + WebAssemblyFunctionInfo &MFI, unsigned &CurLocal, unsigned Reg) { auto P = Reg2Local.insert(std::make_pair(Reg, CurLocal)); - if (P.second) + if (P.second) { + if (Reg == MFI.getFrameBaseVreg()) + MFI.setFrameBaseLocal(CurLocal); ++CurLocal; + } return P.first->second; } @@ -244,7 +248,7 @@ // Stackify the input if it isn't stackified yet. if (!MFI.isVRegStackified(OldReg)) { - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); Register NewReg = MRI.createVirtualRegister(RC); unsigned Opc = getLocalGetOpcode(RC); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Opc), NewReg) @@ -255,7 +259,7 @@ // Replace the TEE with a LOCAL_TEE. unsigned LocalId = - getLocalId(Reg2Local, CurLocal, MI.getOperand(1).getReg()); + getLocalId(Reg2Local, MFI, CurLocal, MI.getOperand(1).getReg()); unsigned Opc = getLocalTeeOpcode(RC); BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Opc), MI.getOperand(0).getReg()) @@ -291,7 +295,7 @@ // After the drop instruction, this reg operand will not be used Drop->getOperand(0).setIsKill(); } else { - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); unsigned Opc = getLocalSetOpcode(RC); WebAssemblyDebugValueManager(&MI).replaceWithLocal(LocalId); @@ -323,7 +327,7 @@ // immediates. if (MO.isDef()) { assert(MI.isInlineAsm()); - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); // If this register operand is tied to another operand, we can't // change it to an immediate. Untie it first. MI.untieRegOperand(MI.getOperandNo(&MO)); @@ -341,7 +345,7 @@ // Our contract with inline asm register operands is to provide local // indices as immediates. if (MI.isInlineAsm()) { - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); // Untie it first if this reg operand is tied to another operand. MI.untieRegOperand(MI.getOperandNo(&MO)); MO.ChangeToImmediate(LocalId); @@ -349,7 +353,7 @@ } // Insert a local.get. - unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg); + unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg); const TargetRegisterClass *RC = MRI.getRegClass(OldReg); Register NewReg = MRI.createVirtualRegister(RC); unsigned Opc = getLocalGetOpcode(RC); 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 @@ -55,6 +55,12 @@ // A virtual register holding the base pointer for functions that have // overaligned values on the user stack. unsigned BasePtrVreg = -1U; + // A virtual register holding the frame base. This is either FP or SP + // after it has been replaced by a vreg + unsigned FrameBaseVreg = -1U; + // The local holding the frame base. This is either FP or SP + // after WebAssemblyExplicitLocals + unsigned FrameBaseLocal = -1U; // Function properties. bool CFGStackified = false; @@ -90,6 +96,16 @@ assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set"); return BasePtrVreg; } + void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; } + unsigned getFrameBaseVreg() const { + //assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set"); + return FrameBaseVreg; + } + void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; } + unsigned getFrameBaseLocal() const { + assert(FrameBaseLocal != -1U && "Frame base local hasn't been set"); + return FrameBaseLocal; + } void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; } static const unsigned UnusedReg = -1u; 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 @@ -46,6 +46,7 @@ unsigned Kind = 0) const override; // This does not apply to wasm. const uint32_t *getNoPreservedMask() const override { return nullptr; } + }; } // end namespace llvm 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 @@ -132,6 +132,10 @@ Register WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + // If the PReg has been replaced by a VReg, return that. + auto FI = MF.getInfo(); + if (FI->getFrameBaseVreg() != -1) // TODO is there a better check for this? + return FI->getFrameBaseVreg(); static const unsigned Regs[2][2] = { /* !isArch64Bit isArch64Bit */ /* !hasFP */ {WebAssembly::SP32, WebAssembly::SP64}, diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyReplacePhysRegs.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyReplacePhysRegs.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyReplacePhysRegs.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyReplacePhysRegs.cpp @@ -67,7 +67,7 @@ }); MachineRegisterInfo &MRI = MF.getRegInfo(); - const auto &TRI = *MF.getSubtarget().getRegisterInfo(); + auto &TRI = *MF.getSubtarget().getRegisterInfo(); bool Changed = false; assert(!mustPreserveAnalysisID(LiveIntervalsID) && @@ -88,8 +88,16 @@ for (auto I = MRI.reg_begin(PReg), E = MRI.reg_end(); I != E;) { MachineOperand &MO = *I++; if (!MO.isImplicit()) { - if (VReg == WebAssembly::NoRegister) + if (VReg == WebAssembly::NoRegister) { VReg = MRI.createVirtualRegister(RC); + if (PReg == TRI.getFrameRegister(MF)) { + auto FI = MF.getInfo(); + assert(FI->getFrameBaseVreg() == -1U); + FI->setFrameBaseVreg(VReg); + errs() << "replacing reg " << PReg << " with " << VReg<< " (" << Register::virtReg2Index(VReg)<< + ")\n"; + } + } MO.setReg(VReg); if (MO.getParent()->isDebugValue()) MO.setIsDebug();