[lld] 3a05c39 - [WebAssembly] Track frame registers through VReg and local allocation

Derek Schuff via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 16 13:52:29 PST 2020


Author: Derek Schuff
Date: 2020-01-16T13:51:17-08:00
New Revision: 3a05c3969c18b5520e360b78fc63cda39a6be98f

URL: https://github.com/llvm/llvm-project/commit/3a05c3969c18b5520e360b78fc63cda39a6be98f
DIFF: https://github.com/llvm/llvm-project/commit/3a05c3969c18b5520e360b78fc63cda39a6be98f.diff

LOG: [WebAssembly] Track frame registers through VReg and local allocation

This change has 2 components:

Target-independent: add a method getDwarfFrameBase to TargetFrameLowering. It
describes how the Dwarf frame base will be encoded.  That can be a register (the
default), the CFA (which replaces NVPTX-specific logic in DwarfCompileUnit), or
a DW_OP_WASM_location descriptr.

WebAssembly: Allow WebAssemblyFunctionInfo::getFrameRegister to return the
correct virtual register instead of FP32/SP32 after WebAssemblyReplacePhysRegs
has run.  Make WebAssemblyExplicitLocals store the local it allocates for the
frame register. Use this local information to implement getDwarfFrameBase

The result is that the DW_AT_frame_base attribute is correctly encoded for each
subprogram, and each param and local variable has a correct DW_AT_location that
uses DW_OP_fbreg to refer to the frame base.

Differential Revision: https://reviews.llvm.org/D71681

Added: 
    llvm/test/MC/WebAssembly/debug-localvar.ll

Modified: 
    lld/test/wasm/debuginfo.test
    llvm/include/llvm/CodeGen/TargetFrameLowering.h
    llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
    llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
    llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp
    llvm/lib/Target/NVPTX/NVPTXFrameLowering.h
    llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
    llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
    llvm/lib/Target/WebAssembly/WebAssemblyOptimizeLiveIntervals.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyReplacePhysRegs.cpp
    llvm/test/CodeGen/WebAssembly/multi-return.ll
    llvm/test/MC/WebAssembly/debug-info.ll
    llvm/test/MC/WebAssembly/dwarfdump.ll

Removed: 
    


################################################################################
diff  --git a/lld/test/wasm/debuginfo.test b/lld/test/wasm/debuginfo.test
index 3e07ad960842..59c36979b4b6 100644
--- a/lld/test/wasm/debuginfo.test
+++ b/lld/test/wasm/debuginfo.test
@@ -14,6 +14,7 @@ CHECK-NEXT:              DW_AT_name	("hi.c")
 CHECK:   DW_TAG_subprogram
 CHECK-NEXT:                DW_AT_low_pc
 CHECK-NEXT:                DW_AT_high_pc
+CHECK-NEXT:                DW_AT_frame_base
 CHECK-NEXT:                DW_AT_name	("test")
 CHECK-NEXT:                DW_AT_decl_file	("/Users/yury/llvmwasm{{(/|\\)}}hi.c")
 CHECK-NEXT:                DW_AT_decl_line	(3)
@@ -27,6 +28,7 @@ CHECK-NEXT:                  DW_AT_decl_line	(3)
 CHECK:   DW_TAG_subprogram
 CHECK-NEXT:                DW_AT_low_pc
 CHECK-NEXT:                DW_AT_high_pc
+CHECK-NEXT:                DW_AT_frame_base
 CHECK-NEXT:                DW_AT_name	("_start")
 CHECK-NEXT:                DW_AT_decl_file	("/Users/yury/llvmwasm{{(/|\\)}}hi.c")
 CHECK-NEXT:                DW_AT_decl_line	(7)
@@ -43,7 +45,7 @@ CHECK-NEXT:              DW_AT_name	("hi_foo.c")
 
 CHECK:   DW_TAG_variable
 CHECK-NEXT:                DW_AT_name	("y")
-CHECK-NEXT:                DW_AT_type	(0x00000097 "int[2]")
+CHECK-NEXT:                DW_AT_type	(0x000000a1 "int[2]")
 CHECK-NEXT:                DW_AT_external	(true)
 CHECK-NEXT:                DW_AT_decl_file	("{{.*}}hi_foo.c")
 CHECK-NEXT:                DW_AT_decl_line	(1)
@@ -65,7 +67,7 @@ CHECK-NEXT:                DW_AT_encoding	(DW_ATE_unsigned)
 
 CHECK:   DW_TAG_variable
 CHECK-NEXT:                DW_AT_name	("z")
-CHECK-NEXT:                DW_AT_type	(0x00000097 "int[2]")
+CHECK-NEXT:                DW_AT_type	(0x000000a1 "int[2]")
 CHECK-NEXT:                DW_AT_external	(true)
 CHECK-NEXT:                DW_AT_decl_file	("{{.*}}hi_foo.c")
 CHECK-NEXT:                DW_AT_decl_line	(8)
@@ -74,6 +76,7 @@ CHECK-NEXT:                DW_AT_location	(DW_OP_addr 0x0)
 CHECK:   DW_TAG_subprogram
 CHECK-NEXT:                DW_AT_low_pc	
 CHECK-NEXT:                DW_AT_high_pc
+CHECK-NEXT:                DW_AT_frame_base
 CHECK-NEXT:                DW_AT_name	("foo")
 CHECK-NEXT:                DW_AT_decl_file	("{{.*}}hi_foo.c")
 CHECK-NEXT:                DW_AT_decl_line	(3)

diff  --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
index c7d4c4d7e5d4..74d35580ad6e 100644
--- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
@@ -52,6 +52,21 @@ class TargetFrameLowering {
     unsigned Reg;
     int Offset; // Offset relative to stack pointer on function entry.
   };
+
+  struct DwarfFrameBase {
+    // The frame base may be either a register (the default), the CFA,
+    // or a WebAssembly-specific location description.
+    enum FrameBaseKind { Register, CFA, WasmFrameBase } Kind;
+    struct WasmFrameBase {
+      unsigned Kind; // Wasm local, global, or value stack
+      unsigned Index;
+    };
+    union {
+      unsigned Reg;
+      struct WasmFrameBase WasmLoc;
+    } Location;
+  };
+
 private:
   StackDirection StackDir;
   Align StackAlignment;
@@ -394,6 +409,10 @@ class TargetFrameLowering {
   /// Return initial CFA register value i.e. the one valid at the beginning of
   /// the function (before any stack operations).
   virtual unsigned getInitialCFARegister(const MachineFunction &MF) const;
+
+  /// Return the frame base information to be encoded in the DWARF subprogram
+  /// debug info.
+  virtual DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const;
 };
 
 } // End llvm namespace

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 1fbffc1939eb..69a39d55910d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -400,15 +400,33 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
 
   // Only include DW_AT_frame_base in full debug info
   if (!includeMinimalInlineScopes()) {
-    if (Asm->MF->getTarget().getTargetTriple().isNVPTX()) {
+    const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
+    TargetFrameLowering::DwarfFrameBase FrameBase =
+        TFI->getDwarfFrameBase(*Asm->MF);
+    switch (FrameBase.Kind) {
+    case TargetFrameLowering::DwarfFrameBase::Register: {
+      if (Register::isPhysicalRegister(FrameBase.Location.Reg)) {
+        MachineLocation Location(FrameBase.Location.Reg);
+        addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
+      }
+      break;
+    }
+    case TargetFrameLowering::DwarfFrameBase::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 {
-      const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
-      MachineLocation Location(RI->getFrameRegister(*Asm->MF));
-      if (Register::isPhysicalRegister(Location.getReg()))
-        addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
+      break;
+    }
+    case TargetFrameLowering::DwarfFrameBase::WasmFrameBase: {
+      DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+      DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+      DIExpressionCursor Cursor({});
+      DwarfExpr.addWasmLocation(FrameBase.Location.WasmLoc.Kind,
+                                FrameBase.Location.WasmLoc.Index);
+      DwarfExpr.addExpression(std::move(Cursor));
+      addBlock(*SPDie, dwarf::DW_AT_frame_base, DwarfExpr.finalize());
+      break;
+    }
     }
   }
 

diff  --git a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
index bc59be890c97..9d9bc265550c 100644
--- a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
+++ b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
@@ -154,3 +154,9 @@ unsigned TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF)
     const {
   llvm_unreachable("getInitialCFARegister() not implemented!");
 }
+
+TargetFrameLowering::DwarfFrameBase
+TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {
+  const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
+  return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF)}};
+}

diff  --git a/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp
index d26912f47e50..2aad49052f78 100644
--- a/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp
@@ -83,3 +83,8 @@ MachineBasicBlock::iterator NVPTXFrameLowering::eliminateCallFramePseudoInstr(
   // ADJCALLSTACKUP instructions.
   return MBB.erase(I);
 }
+
+TargetFrameLowering::DwarfFrameBase
+NVPTXFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {
+  return {DwarfFrameBase::CFA, {0}};
+}

diff  --git a/llvm/lib/Target/NVPTX/NVPTXFrameLowering.h b/llvm/lib/Target/NVPTX/NVPTXFrameLowering.h
index 40269f58f06e..2e58eb75f696 100644
--- a/llvm/lib/Target/NVPTX/NVPTXFrameLowering.h
+++ b/llvm/lib/Target/NVPTX/NVPTXFrameLowering.h
@@ -30,6 +30,7 @@ class NVPTXFrameLowering : public TargetFrameLowering {
   MachineBasicBlock::iterator
   eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
                                 MachineBasicBlock::iterator I) const override;
+  DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const override;
 };
 
 } // End llvm namespace

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
index acbd4c9921b0..1196b5dd63d0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
@@ -72,10 +72,15 @@ FunctionPass *llvm::createWebAssemblyExplicitLocals() {
 /// 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<unsigned, unsigned> &Reg2Local,
-                           unsigned &CurLocal, unsigned Reg) {
+                           WebAssemblyFunctionInfo &MFI, unsigned &CurLocal,
+                           unsigned Reg) {
   auto P = Reg2Local.insert(std::make_pair(Reg, CurLocal));
-  if (P.second)
+  if (P.second) {
+    // Mark the local allocated for the frame base vreg.
+    if (MFI.isFrameBaseVirtual() && Reg == MFI.getFrameBaseVreg())
+      MFI.setFrameBaseLocal(CurLocal);
     ++CurLocal;
+  }
   return P.first->second;
 }
 
@@ -244,7 +249,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
 
         // 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 +260,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
 
         // 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 +296,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
             // 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 +328,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
         // 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 +346,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
         // 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 +354,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
         }
 
         // 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/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
index 71eeebfada4b..9da7f53fe106 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
@@ -19,6 +19,7 @@
 
 #include "WebAssemblyFrameLowering.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "WebAssembly.h"
 #include "WebAssemblyInstrInfo.h"
 #include "WebAssemblyMachineFunctionInfo.h"
 #include "WebAssemblySubtarget.h"
@@ -259,3 +260,20 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
 
   writeSPToGlobal(SPReg, MF, MBB, InsertPt, DL);
 }
+
+TargetFrameLowering::DwarfFrameBase
+WebAssemblyFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {
+  DwarfFrameBase Loc;
+  Loc.Kind = DwarfFrameBase::WasmFrameBase;
+  const WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
+  if (needsSP(MF)) {
+    unsigned LocalNum = MFI.getFrameBaseLocal();
+    Loc.Location.WasmLoc = {WebAssembly::TI_LOCAL_START, LocalNum};
+  } else {
+    // TODO: This should work on a breakpoint at a function with no frame,
+    // but probably won't work for traversing up the stack.
+    // TODO: This needs a relocation for correct __stack_pointer
+    Loc.Location.WasmLoc = {WebAssembly::TI_GLOBAL_START, 0};
+  }
+  return Loc;
+}

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
index fdc0f561dcd9..42fe8e575552 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
@@ -44,6 +44,7 @@ class WebAssemblyFrameLowering final : public TargetFrameLowering {
 
   bool hasFP(const MachineFunction &MF) const override;
   bool hasReservedCallFrame(const MachineFunction &MF) const override;
+  DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const override;
 
   bool needsPrologForEH(const MachineFunction &MF) const;
 

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
index 16e2f4392984..f2bbdb81033f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h
@@ -55,6 +55,12 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
   // 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,18 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
     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;
+  }
+  // Return true if the frame base physreg has been replaced by a virtual reg.
+  bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; }
+  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/WebAssemblyOptimizeLiveIntervals.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyOptimizeLiveIntervals.cpp
index 0bd30791e57c..c9232e52bfdc 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyOptimizeLiveIntervals.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyOptimizeLiveIntervals.cpp
@@ -82,7 +82,8 @@ bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(
   SmallVector<LiveInterval *, 4> SplitLIs;
   for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
     unsigned Reg = Register::index2VirtReg(I);
-    if (MRI.reg_nodbg_empty(Reg))
+    auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
+    if (MRI.reg_nodbg_empty(Reg) || Reg == TRI.getFrameRegister(MF))
       continue;
 
     LIS.splitSeparateComponents(LIS.getInterval(Reg), SplitLIs);

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
index 789a025794ea..205fb6e834e9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
@@ -132,6 +132,10 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
 
 Register
 WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
+  // If the PReg has been replaced by a VReg, return that.
+  const auto &MFI = MF.getInfo<WebAssemblyFunctionInfo>();
+  if (MFI->isFrameBaseVirtual())
+    return MFI->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
index 5eafd6c54e78..9f5d6b2a9a47 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyReplacePhysRegs.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyReplacePhysRegs.cpp
@@ -67,7 +67,7 @@ bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
   });
 
   MachineRegisterInfo &MRI = MF.getRegInfo();
-  const auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
+  auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
   bool Changed = false;
 
   assert(!mustPreserveAnalysisID(LiveIntervalsID) &&
@@ -88,8 +88,18 @@ bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
     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<WebAssemblyFunctionInfo>();
+            assert(!FI->isFrameBaseVirtual());
+            FI->setFrameBaseVreg(VReg);
+            LLVM_DEBUG({
+              dbgs() << "replacing preg " << PReg << " with " << VReg << " ("
+                     << Register::virtReg2Index(VReg) << ")\n";
+            });
+          }
+        }
         MO.setReg(VReg);
         if (MO.getParent()->isDebugValue())
           MO.setIsDebug();

diff  --git a/llvm/test/CodeGen/WebAssembly/multi-return.ll b/llvm/test/CodeGen/WebAssembly/multi-return.ll
index d5db601b8f3a..a37e71350d52 100644
--- a/llvm/test/CodeGen/WebAssembly/multi-return.ll
+++ b/llvm/test/CodeGen/WebAssembly/multi-return.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
 
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
@@ -12,8 +11,8 @@ declare { i64, i128, i192, i128, i64 } @return_multi_multi()
 define i64 @test0() {
 ; CHECK-LABEL: test0
 ; CHECK: call    	return_multi_multi
-; CHECK: i64.load	$0=, 8($1)
-; CHECK: local.copy	$push8=, $0
+; CHECK: i64.load	$[[RV:[0-9]+]]=, 8(${{[0-9]+}})
+; CHECK: local.copy	$push8=, $[[RV]]
   %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
   %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
   ret i64 %t1
@@ -22,12 +21,12 @@ define i64 @test0() {
 define i128 @test1() {
 ; CHECK-LABEL: test1
 ; CHECK: call    	return_multi_multi
-; CHECK: i64.load	$1=, 16($2)
+; CHECK: i64.load	$[[RV:[0-9]+]]=, 16($[[SP:[0-9]+]])
 ; CHECK: i32.const	$push0=, 24
-; CHECK: i32.add 	$push1=, $2, $pop0
+; CHECK: i32.add 	$push1=, $[[SP]], $pop0
 ; CHECK: i64.load	$push2=, 0($pop1)
 ; CHECK: i64.store	8($0), $pop2
-; CHECK: i64.store	0($0), $1
+; CHECK: i64.store	0($0), $[[RV]]
   %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
   %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
   ret i128 %t1
@@ -37,15 +36,15 @@ define i192 @test2() {
 ; CHECK-LABEL: test2
 ; CHECK: call    	return_multi_multi
 ; CHECK: i32.const	$push0=, 40
-; CHECK: i32.add 	$push1=, $3, $pop0
-; CHECK: i64.load	$1=, 0($pop1)
-; CHECK: i64.load	$2=, 32($3)
+; CHECK: i32.add 	$push1=, $[[SP:[0-9]+]], $pop0
+; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop1)
+; CHECK: i64.load	$[[L2:[0-9]+]]=, 32($[[SP]])
 ; CHECK: i32.const	$push2=, 48
-; CHECK: i32.add 	$push3=, $3, $pop2
+; CHECK: i32.add 	$push3=, $[[SP]], $pop2
 ; CHECK: i64.load	$push4=, 0($pop3)
 ; CHECK: i64.store	16($0), $pop4
-; CHECK: i64.store	0($0), $2
-; CHECK: i64.store	8($0), $1
+; CHECK: i64.store	0($0), $[[L2]]
+; CHECK: i64.store	8($0), $[[L1]]
   %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
   %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
   ret i192 %t1
@@ -54,12 +53,12 @@ define i192 @test2() {
 define i128 @test3() {
 ; CHECK-LABEL: test3
 ; CHECK: call    	return_multi_multi
-; CHECK: i64.load	$1=, 56($2)
+; CHECK: i64.load	$[[L1:[0-9]+]]=, 56($[[SP:[0-9]+]])
 ; CHECK: i32.const	$push0=, 64
-; CHECK: i32.add 	$push1=, $2, $pop0
+; CHECK: i32.add 	$push1=, $[[SP]], $pop0
 ; CHECK: i64.load	$push2=, 0($pop1)
 ; CHECK: i64.store	8($0), $pop2
-; CHECK: i64.store	0($0), $1
+; CHECK: i64.store	0($0), $[[L1]]
   %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
   %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
   ret i128 %t1
@@ -68,8 +67,8 @@ define i128 @test3() {
 define i64 @test4() {
 ; CHECK-LABEL: test4
 ; CHECK: call    	return_multi_multi
-; CHECK: i64.load	$0=, 72($1)
-; CHECK: local.copy	$push8=, $0
+; CHECK: i64.load	$[[L1:[0-9]+]]=, 72($[[SP:[0-9]+]])
+; CHECK: local.copy	$push8=, $[[L1]]
   %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
   %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 4
   ret i64 %t1
@@ -81,17 +80,17 @@ define { i64, i128 } @test5() {
 ; CHECK-LABEL: test5
 ; CHECK: call    	return_multi_multi
 ; CHECK: i32.const	$push10=, 8
-; CHECK: i32.add 	$push11=, $3, $pop10
+; CHECK: i32.add 	$push11=, $[[SP:[0-9]+]], $pop10
 ; CHECK: i32.const	$push0=, 16
 ; CHECK: i32.add 	$push1=, $pop11, $pop0
-; CHECK: i64.load	$1=, 0($pop1)
-; CHECK: i64.load	$2=, 8($3)
-; CHECK: i64.load	$push2=, 16($3)
+; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop1)
+; CHECK: i64.load	$[[L2:[0-9]+]]=, 8($[[SP]])
+; CHECK: i64.load	$push2=, 16($[[SP]])
 ; CHECK: i64.store	8($0), $pop2
 ; CHECK: i32.const	$push12=, 16
 ; CHECK: i32.add 	$push3=, $0, $pop12
-; CHECK: i64.store	0($pop3), $1
-; CHECK: i64.store	0($0), $2
+; CHECK: i64.store	0($pop3), $[[L1]]
+; CHECK: i64.store	0($0), $[[L2]]
   %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
   %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
   %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
@@ -104,19 +103,19 @@ define { i128, i128 } @test6() {
 ; CHECK-LABEL: test6
 ; CHECK: call    	return_multi_multi
 ; CHECK: i32.const	$push0=, 24
-; CHECK: i32.add 	$push1=, $4, $pop0
-; CHECK: i64.load	$1=, 0($pop1)
+; CHECK: i32.add 	$push1=, $[[SP:[0-9]+]], $pop0
+; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop1)
 ; CHECK: i32.const	$push2=, 64
-; CHECK: i32.add 	$push3=, $4, $pop2
-; CHECK: i64.load	$2=, 0($pop3)
-; CHECK: i64.load	$3=, 16($4)
-; CHECK: i64.load	$push4=, 56($4)
+; CHECK: i32.add 	$push3=, $[[SP]], $pop2
+; CHECK: i64.load	$[[L2:[0-9]+]]=, 0($pop3)
+; CHECK: i64.load	$[[L3:[0-9]+]]=, 16($[[SP]])
+; CHECK: i64.load	$push4=, 56($[[SP]])
 ; CHECK: i64.store	16($0), $pop4
 ; CHECK: i32.const	$push5=, 24
 ; CHECK: i32.add 	$push6=, $0, $pop5
-; CHECK: i64.store	0($pop6), $2
-; CHECK: i64.store	0($0), $3
-; CHECK: i64.store	8($0), $1
+; CHECK: i64.store	0($pop6), $[[L2]]
+; CHECK: i64.store	0($0), $[[L3]]
+; CHECK: i64.store	8($0), $[[L1]]
   %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
   %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
   %r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
@@ -129,21 +128,21 @@ define { i64, i192 } @test7() {
 ; CHECK-LABEL: test7
 ; CHECK: call    	return_multi_multi
 ; CHECK: i32.const	$push2=, 40
-; CHECK: i32.add 	$push3=, $4, $pop2
-; CHECK: i64.load	$1=, 0($pop3)
-; CHECK: i64.load	$2=, 8($4)
-; CHECK: i64.load	$3=, 32($4)
+; CHECK: i32.add 	$push3=, $[[SP:[0-9]+]], $pop2
+; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop3)
+; CHECK: i64.load	$[[L2:[0-9]+]]=, 8($[[SP]])
+; CHECK: i64.load	$[[L3:[0-9]+]]=, 32($[[SP]])
 ; CHECK: i32.const	$push0=, 24
 ; CHECK: i32.add 	$push1=, $0, $pop0
 ; CHECK: i32.const	$push4=, 48
-; CHECK: i32.add 	$push5=, $4, $pop4
+; CHECK: i32.add 	$push5=, $[[SP]], $pop4
 ; CHECK: i64.load	$push6=, 0($pop5)
 ; CHECK: i64.store	0($pop1), $pop6
-; CHECK: i64.store	8($0), $3
+; CHECK: i64.store	8($0), $[[L3]]
 ; CHECK: i32.const	$push7=, 16
 ; CHECK: i32.add 	$push8=, $0, $pop7
-; CHECK: i64.store	0($pop8), $1
-; CHECK: i64.store	0($0), $2
+; CHECK: i64.store	0($pop8), $[[L1]]
+; CHECK: i64.store	0($0), $[[L2]]
   %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
   %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
   %r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
@@ -156,37 +155,37 @@ define { i128, i192, i128, i64 } @test8() {
 ; CHECK-LABEL: test8
 ; CHECK: call    	return_multi_multi
 ; CHECK: i32.const	$push0=, 64
-; CHECK: i32.add 	$push1=, $8, $pop0
-; CHECK: i64.load	$1=, 0($pop1)
+; CHECK: i32.add 	$push1=, $[[SP:[0-9]+]], $pop0
+; CHECK: i64.load	$[[L1:[0-9]+]]=, 0($pop1)
 ; CHECK: i32.const	$push20=, 8
-; CHECK: i32.add 	$push21=, $8, $pop20
+; CHECK: i32.add 	$push21=, $[[SP]], $pop20
 ; CHECK: i32.const	$push2=, 32
 ; CHECK: i32.add 	$push3=, $pop21, $pop2
-; CHECK: i64.load	$2=, 0($pop3)
+; CHECK: i64.load	$[[L2:[0-9]+]]=, 0($pop3)
 ; CHECK: i32.const	$push4=, 48
-; CHECK: i32.add 	$push5=, $8, $pop4
-; CHECK: i64.load	$3=, 0($pop5)
+; CHECK: i32.add 	$push5=, $[[SP]], $pop4
+; CHECK: i64.load	$[[L3:[0-9]+]]=, 0($pop5)
 ; CHECK: i32.const	$push6=, 24
-; CHECK: i32.add 	$push7=, $8, $pop6
-; CHECK: i64.load	$4=, 0($pop7)
-; CHECK: i64.load	$5=, 8($8)
-; CHECK: i64.load	$6=, 56($8)
-; CHECK: i64.load	$7=, 32($8)
-; CHECK: i64.load	$push8=, 16($8)
+; CHECK: i32.add 	$push7=, $[[SP]], $pop6
+; CHECK: i64.load	$[[L4:[0-9]+]]=, 0($pop7)
+; CHECK: i64.load	$[[L5:[0-9]+]]=, 8($[[SP]])
+; CHECK: i64.load	$[[L6:[0-9]+]]=, 56($[[SP]])
+; CHECK: i64.load	$[[L7:[0-9]+]]=, 32($[[SP]])
+; CHECK: i64.load	$push8=, 16($[[SP]])
 ; CHECK: i64.store	40($0), $pop8
 ; CHECK: i32.const	$push9=, 48
 ; CHECK: i32.add 	$push10=, $0, $pop9
-; CHECK: i64.store	0($pop10), $4
+; CHECK: i64.store	0($pop10), $[[L4]]
 ; CHECK: i32.const	$push22=, 32
 ; CHECK: i32.add 	$push11=, $0, $pop22
-; CHECK: i64.store	0($pop11), $3
-; CHECK: i64.store	16($0), $7
+; CHECK: i64.store	0($pop11), $[[L3]]
+; CHECK: i64.store	16($0), $[[L7]]
 ; CHECK: i32.const	$push12=, 24
 ; CHECK: i32.add 	$push13=, $0, $pop12
-; CHECK: i64.store	0($pop13), $2
-; CHECK: i64.store	0($0), $6
-; CHECK: i64.store	8($0), $1
-; CHECK: i64.store	56($0), $5
+; CHECK: i64.store	0($pop13), $[[L2]]
+; CHECK: i64.store	0($0), $[[L6]]
+; CHECK: i64.store	8($0), $[[L1]]
+; CHECK: i64.store	56($0), $[[L5]]
   %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
   %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
   %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1

diff  --git a/llvm/test/MC/WebAssembly/debug-info.ll b/llvm/test/MC/WebAssembly/debug-info.ll
index 0ee06ffcd880..2e9dbdd9d191 100644
--- a/llvm/test/MC/WebAssembly/debug-info.ll
+++ b/llvm/test/MC/WebAssembly/debug-info.ll
@@ -59,74 +59,74 @@
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
-; CHECK-NEXT:    Size: 84
+; CHECK-NEXT:    Size: 86
 ; CHECK-NEXT:    Offset: 283
 ; CHECK-NEXT:    Name: .debug_abbrev
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
-; CHECK-NEXT:    Size: 106
-; CHECK-NEXT:    Offset: 387
+; CHECK-NEXT:    Size: 111
+; CHECK-NEXT:    Offset: 389
 ; CHECK-NEXT:    Name: .debug_info
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 42
-; CHECK-NEXT:    Offset: 511
+; CHECK-NEXT:    Offset: 518
 ; CHECK-NEXT:    Name: .debug_pubnames
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 26
-; CHECK-NEXT:    Offset: 575
+; CHECK-NEXT:    Offset: 582
 ; CHECK-NEXT:    Name: .debug_pubtypes
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 57
-; CHECK-NEXT:    Offset: 623
+; CHECK-NEXT:    Offset: 630
 ; CHECK-NEXT:    Name: .debug_line
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 88
-; CHECK-NEXT:    Offset: 698
+; CHECK-NEXT:    Offset: 705
 ; CHECK-NEXT:    Name: linking
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 9
-; CHECK-NEXT:    Offset: 800
+; CHECK-NEXT:    Offset: 807
 ; CHECK-NEXT:    Name: reloc.DATA
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 58
-; CHECK-NEXT:    Offset: 826
+; CHECK-NEXT:    Offset: 833
 ; CHECK-NEXT:    Name: reloc..debug_info
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 6
-; CHECK-NEXT:    Offset: 908
+; CHECK-NEXT:    Offset: 915
 ; CHECK-NEXT:    Name: reloc..debug_pubnames
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 6
-; CHECK-NEXT:    Offset: 942
+; CHECK-NEXT:    Offset: 949
 ; CHECK-NEXT:    Name: reloc..debug_pubtypes
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 6
-; CHECK-NEXT:    Offset: 976
+; CHECK-NEXT:    Offset: 983
 ; CHECK-NEXT:    Name: reloc..debug_line
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section {
 ; CHECK-NEXT:    Type: CUSTOM (0x0)
 ; CHECK-NEXT:    Size: 77
-; CHECK-NEXT:    Offset: 1006
+; CHECK-NEXT:    Offset: 1013
 ; CHECK-NEXT:    Name: producers
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:]
@@ -148,7 +148,7 @@
 ; CHECK-NEXT:    0x44 R_WASM_SECTION_OFFSET_I32 .debug_str 113
 ; CHECK-NEXT:    0x50 R_WASM_MEMORY_ADDR_I32 ptr2 0
 ; CHECK-NEXT:    0x5B R_WASM_FUNCTION_OFFSET_I32 f2 0
-; CHECK-NEXT:    0x63 R_WASM_SECTION_OFFSET_I32 .debug_str 118
+; CHECK-NEXT:    0x68 R_WASM_SECTION_OFFSET_I32 .debug_str 118
 ; CHECK-NEXT:  }
 ; CHECK-NEXT:  Section (11) .debug_pubnames {
 ; CHECK-NEXT:    0x6 R_WASM_SECTION_OFFSET_I32 .debug_info 0

diff  --git a/llvm/test/MC/WebAssembly/debug-localvar.ll b/llvm/test/MC/WebAssembly/debug-localvar.ll
new file mode 100644
index 000000000000..9018f81fe9c8
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/debug-localvar.ll
@@ -0,0 +1,113 @@
+; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump -  | FileCheck %s
+
+; ModuleID = 'debugtest.c'
+source_filename = "debugtest.c"
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32"
+; Function Attrs: noinline nounwind optnone
+define hidden i32 @foo(i32 %arg) #0 !dbg !7 {
+entry:
+  %arg.addr = alloca i32, align 4
+  %a = alloca i32, align 4
+  %b = alloca i32, align 4
+  store i32 %arg, i32* %arg.addr, align 4
+  call void @llvm.dbg.declare(metadata i32* %arg.addr, metadata !11, metadata !DIExpression()), !dbg !12
+  call void @llvm.dbg.declare(metadata i32* %a, metadata !13, metadata !DIExpression()), !dbg !14
+  store i32 1, i32* %a, align 4, !dbg !14
+  call void @llvm.dbg.declare(metadata i32* %b, metadata !15, metadata !DIExpression()), !dbg !17
+  store i32 2, i32* %b, align 4, !dbg !17
+  %0 = load i32, i32* %b, align 4, !dbg !18
+  store i32 %0, i32* %arg.addr, align 4, !dbg !19
+  %1 = load i32, i32* %arg.addr, align 4, !dbg !20
+  %2 = load i32, i32* %a, align 4, !dbg !21
+  %add = add nsw i32 %1, %2, !dbg !22
+  ret i32 %add, !dbg !23
+}
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone speculatable willreturn }
+attributes #2 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 6b38826e3a5f402498f0ea721b8c90d727f36205)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "debugtest.c", directory: "/s/llvm-upstream")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 6b38826e3a5f402498f0ea721b8c90d727f36205)"}
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 1, type: !10)
+!12 = !DILocation(line: 1, column: 14, scope: !7)
+!13 = !DILocalVariable(name: "a", scope: !7, file: !1, line: 2, type: !10)
+!14 = !DILocation(line: 2, column: 7, scope: !7)
+!15 = !DILocalVariable(name: "b", scope: !16, file: !1, line: 4, type: !10)
+!16 = distinct !DILexicalBlock(scope: !7, file: !1, line: 3, column: 3)
+!17 = !DILocation(line: 4, column: 9, scope: !16)
+!18 = !DILocation(line: 5, column: 11, scope: !16)
+!19 = !DILocation(line: 5, column: 9, scope: !16)
+!20 = !DILocation(line: 7, column: 10, scope: !7)
+!21 = !DILocation(line: 7, column: 16, scope: !7)
+!22 = !DILocation(line: 7, column: 14, scope: !7)
+!23 = !DILocation(line: 7, column: 3, scope: !7)
+!24 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 10, type: !8, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!25 = !DILocalVariable(name: "arg", arg: 1, scope: !24, file: !1, line: 10, type: !10)
+!26 = !DILocation(line: 10, column: 14, scope: !24)
+!27 = !DILocation(line: 11, column: 10, scope: !24)
+!28 = !DILocation(line: 11, column: 3, scope: !24)
+!29 = !DILocalVariable(name: "__vla_expr0", scope: !24, type: !30, flags: DIFlagArtificial)
+!30 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!31 = !DILocation(line: 0, scope: !24)
+!32 = !DILocalVariable(name: "aa", scope: !24, file: !1, line: 11, type: !33)
+!33 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, elements: !34)
+!34 = !{!35}
+!35 = !DISubrange(count: !29)
+!36 = !DILocation(line: 11, column: 7, scope: !24)
+!37 = !DILocalVariable(name: "cc", scope: !24, file: !1, line: 13, type: !38)
+!38 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!39 = !DILocation(line: 13, column: 8, scope: !24)
+!40 = !DILocation(line: 15, column: 1, scope: !24)
+
+; CHECK-LABEL: DW_TAG_compile_unit
+; CHECK-LABEL:     DW_TAG_subprogram
+; CHECK-NEXT:                DW_AT_low_pc	(0x0000000000000002)
+; CHECK-NEXT:                DW_AT_high_pc	(0x0000000000000039)
+; CHECK-NEXT:                DW_AT_frame_base	(DW_OP_WASM_location 0x0 +1, DW_OP_stack_value)
+; CHECK-NEXT:                DW_AT_name	("foo")
+; CHECK-NEXT:                DW_AT_decl_file	("/s/llvm-upstream/debugtest.c")
+; CHECK-NEXT:                DW_AT_decl_line	(1)
+; CHECK-NEXT:                DW_AT_prototyped	(true)
+; CHECK-NEXT:                DW_AT_type	(0x00000073 "int")
+; CHECK-NEXT:                DW_AT_external	(true)
+; CHECK-LABEL:     DW_TAG_formal_parameter
+; CHECK-NEXT:                  DW_AT_location	(DW_OP_fbreg +12)
+; CHECK-NEXT:                  DW_AT_name	("arg")
+; CHECK-NEXT:                  DW_AT_decl_file	("/s/llvm-upstream/debugtest.c")
+; CHECK-NEXT:                  DW_AT_decl_line	(1)
+; CHECK-NEXT:                  DW_AT_type	(0x00000073 "int")
+
+; CHECK-LABEL:     DW_TAG_variable
+; CHECK-NEXT:                  DW_AT_location	(DW_OP_fbreg +8)
+; CHECK-NEXT:                  DW_AT_name	("a")
+; CHECK-NEXT:                  DW_AT_decl_file	("/s/llvm-upstream/debugtest.c")
+; CHECK-NEXT:                  DW_AT_decl_line	(2)
+; CHECK-NEXT:                  DW_AT_type	(0x00000073 "int")
+
+; CHECK-LABEL:     DW_TAG_lexical_block
+; CHECK-NEXT:                  DW_AT_low_pc	(0x000000000000001c)
+; CHECK-NEXT:                  DW_AT_high_pc	(0x000000000000002d)
+
+; CHECK-LABEL:       DW_TAG_variable
+; CHECK-NEXT:                    DW_AT_location	(DW_OP_fbreg +4)
+; CHECK-NEXT:                    DW_AT_name	("b")
+; CHECK-NEXT:                    DW_AT_decl_file	("/s/llvm-upstream/debugtest.c")
+; CHECK-NEXT:                    DW_AT_decl_line	(4)
+; CHECK-NEXT:                    DW_AT_type	(0x00000073 "int")

diff  --git a/llvm/test/MC/WebAssembly/dwarfdump.ll b/llvm/test/MC/WebAssembly/dwarfdump.ll
index 55a7217611de..4da57c32a8da 100644
--- a/llvm/test/MC/WebAssembly/dwarfdump.ll
+++ b/llvm/test/MC/WebAssembly/dwarfdump.ll
@@ -1,7 +1,7 @@
 ; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s
 
 ; CHECK: .debug_info contents:
-; CHECK-NEXT: 0x00000000: Compile Unit: length = 0x00000066 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x04 (next unit at 0x0000006a)
+; CHECK-NEXT: 0x00000000: Compile Unit: length = 0x0000006b version = 0x0004 abbr_offset = 0x0000 addr_size = 0x04 (next unit at 0x0000006f)
 
 ; CHECK: 0x0000000b: DW_TAG_compile_unit
 ; CHECK-NEXT:              DW_AT_producer	("clang version 6.0.0 (trunk 315924) (llvm/trunk 315960)")
@@ -46,13 +46,14 @@
 ; CHECK: 0x0000005a:   DW_TAG_subprogram
 ; CHECK-NEXT:                DW_AT_low_pc	(0x0000000000000002)
 ; CHECK-NEXT:                DW_AT_high_pc	(0x0000000000000004)
+; CHECK-NEXT:                DW_AT_frame_base	(DW_OP_WASM_location 0x1 +0, DW_OP_stack_value)
 ; CHECK-NEXT:                DW_AT_name	("f2")
 ; CHECK-NEXT:                DW_AT_decl_file	("/usr/local/google/home/sbc/dev/wasm/simple{{[/\\]}}test.c")
 ; CHECK-NEXT:                DW_AT_decl_line	(2)
 ; CHECK-NEXT:                DW_AT_prototyped	(true)
 ; CHECK-NEXT:                DW_AT_external		(true)
 
-; CHECK: 0x00000069:   NULL
+; CHECK: 0x0000006e:   NULL
 
 target triple = "wasm32-unknown-unknown"
 


        


More information about the llvm-commits mailing list