Skip to content

[WebAssembly] DEBUG_VALUEs not collected for non-first defs #136506

Open
@SingleAccretion

Description

@SingleAccretion

In writing a test for an unrelated issue, I came across this code:

// This code differs from MachineInstr::collectDebugValues in that it scans
// the whole BB, not just contiguous DBG_VALUEs, until another definition to
// the same register is encountered.
if (!Def->getOperand(0).isReg())
return;
CurrentReg = Def->getOperand(0).getReg();
for (MachineBasicBlock::iterator MI = std::next(Def->getIterator()),
ME = Def->getParent()->end();
MI != ME; ++MI) {
// If another definition appears, stop
if (MI->definesRegister(CurrentReg, /*TRI=*/nullptr))
break;
if (MI->isDebugValue() && MI->hasDebugOperandForReg(CurrentReg))
DbgValues.push_back(&*MI);
}

This means that any non-first defs of multivalue instructions will get their DEBUG_VALUEs dropped. The reproduction is something like below:

target triple = "wasm32-unknown-unknown"

declare {i32, i32} @extern_func_multivalue(i32, i32)

define i32 @single_non_dbg_use_multivalue(i32 %0, i32 %1) !dbg !15 {
  %full_value = call {i32, i32} @extern_func_multivalue(i32 1, i32 2), !dbg !27
  %full_value_one = extractvalue {i32, i32} %full_value, 0, !dbg !27
  %full_value_two = extractvalue {i32, i32} %full_value, 1, !dbg !27
  call void @llvm.dbg.value(metadata i32 %full_value_two, metadata !16, metadata !DIExpression()), !dbg !28
  %partial_value = call {i32, i32} @extern_func_multivalue(i32 %full_value_one, i32 %full_value_two), !dbg !28
  %partial_value_one = extractvalue {i32, i32} %partial_value, 0, !dbg !28
  %partial_value_two = extractvalue {i32, i32} %partial_value, 1, !dbg !28
  call void @llvm.dbg.value(metadata i32 %partial_value_two, metadata !17, metadata !DIExpression()), !dbg !28
  ret i32 %partial_value_one, !dbg !29
}

!15 = distinct !DISubprogram(name: "single_non_dbg_use_multivalue", scope: !1, file: !1, type: !7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
!16 = !DILocalVariable(name: "value_used", scope: !15, type: !9)
!17 = !DILocalVariable(name: "value_unused", scope: !15, type: !9)
!27 = !DILocation(line: 27, scope: !15)
!28 = !DILocation(line: 28, scope: !15)
!29 = !DILocation(line: 29, scope: !15)

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3}

!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "LLC", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "test.ll", directory: "")
!2 = !{i32 7, !"Dwarf Version", i32 4}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!7 = !DISubroutineType(types: !8)
!8 = !{!9, !9, !9}
!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
> llc test.ll -mattr=+multivalue -target-abi=experimental-mv -O0 -o - --filetype=obj | llvm-dwarfdump -
0x0000000b: DW_TAG_compile_unit
              DW_AT_producer    ("LLC")
              DW_AT_language    (DW_LANG_C_plus_plus_14)
              DW_AT_name        ("test.ll")
              DW_AT_stmt_list   (0x00000000)
              DW_AT_low_pc      (0x00000002)
              DW_AT_high_pc     (0x0000002c)

0x00000022:   DW_TAG_subprogram
                DW_AT_low_pc    (0x00000002)
                DW_AT_high_pc   (0x0000002c)
                DW_AT_frame_base        (DW_OP_WASM_location 0x3 0x0, DW_OP_stack_value)
                DW_AT_name      ("single_non_dbg_use_multivalue")
                DW_AT_type      (0x0000003b "int")
                DW_AT_external  (true)

0x0000003b:   DW_TAG_base_type
                DW_AT_name      ("int")
                DW_AT_encoding  (DW_ATE_signed)
                DW_AT_byte_size (0x04)

We should expect to see the variable record for at least value_used (value_unused looks to be getting dropped earlier).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions