diff --git a/lld/test/wasm/debuginfo.test b/lld/test/wasm/debuginfo.test index 3e07ad960842e0..59c36979b4b68e 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 a0beee36c74847..a5ed1d8a9fcc6f 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; @@ -401,6 +416,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 1fbffc1939eb58..69a39d55910d8a 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 bc59be890c9794..9d9bc265550cf0 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 d26912f47e5011..2aad49052f7899 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 40269f58f06e77..2e58eb75f69685 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 acbd4c9921b0e4..1196b5dd63d080 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 &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 71eeebfada4bc9..9da7f53fe10670 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(); + 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 fdc0f561dcd962..42fe8e5755523c 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 16e2f4392984cf..f2bbdb81033f41 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 0bd30791e57cd7..a2da0ea849e046 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyOptimizeLiveIntervals.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyOptimizeLiveIntervals.cpp @@ -20,6 +20,7 @@ //===----------------------------------------------------------------------===// #include "WebAssembly.h" +#include "WebAssemblyMachineFunctionInfo.h" #include "WebAssemblySubtarget.h" #include "llvm/CodeGen/LiveIntervals.h" #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" @@ -82,10 +83,22 @@ bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction( SmallVector SplitLIs; for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) { unsigned Reg = Register::index2VirtReg(I); + auto &TRI = *MF.getSubtarget().getRegisterInfo(); + if (MRI.reg_nodbg_empty(Reg)) continue; LIS.splitSeparateComponents(LIS.getInterval(Reg), SplitLIs); + if (Reg == TRI.getFrameRegister(MF) && SplitLIs.size() > 0) { + // The live interval for the frame register was split, resulting in a new + // VReg. For now we only support debug info output for a single frame base + // value for the function, so just use the last one. It will certainly be + // wrong for some part of the function, but until we are able to track + // values through live-range splitting and stackification, it will have to + // do. + MF.getInfo()->setFrameBaseVreg( + SplitLIs.back()->reg); + } SplitLIs.clear(); } @@ -103,5 +116,5 @@ bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction( } } - return false; + return true; } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp index 789a025794ea0e..205fb6e834e9cc 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(); + 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 5eafd6c54e7824..9f5d6b2a9a47b8 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().getRegisterInfo(); + auto &TRI = *MF.getSubtarget().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(); + 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 d5db601b8f3a33..a37e71350d526f 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 0ee06ffcd8808c..2e9dbdd9d1916c 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 00000000000000..18acae31f39d4a --- /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 55a7217611deff..4da57c32a8da5d 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"