mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
a98c027f78
Summary: This is a fix for PR45009. When working on D67492 I made DwarfExpression emit a single DW_OP_entry_value operation covering the whole composite location description that is produced if a register does not have a valid DWARF number, and is instead composed of multiple register pieces. Looking closer at the standard, this appears to not be valid DWARF. A DW_OP_entry_value operation's block can only be a DWARF expression or a register location description, so it appears to not be valid for it to hold a composite location description like that. See DWARFv5 sec. 2.5.1.7: "The DW_OP_entry_value operation pushes the value that the described location held upon entering the current subprogram. It has two operands: an unsigned LEB128 length, followed by a block containing a DWARF expression or a register location description (see Section 2.6.1.1.3 on page 39)." Here is a dwarf-discuss mail thread regarding this: http://lists.dwarfstd.org/pipermail/dwarf-discuss-dwarfstd.org/2020-March/004610.html There was not a strong consensus reached there, but people seem to lean towards that operations specified under 2.6 (e.g. DW_OP_piece) may not be part of a DWARF expression, and thus the DW_OP_entry_value operation can't contain those. Perhaps we instead want to emit a entry value operation per each DW_OP_reg* operation, e.g.: - DW_OP_entry_value(DW_OP_regx sub_reg0), DW_OP_stack_value, DW_OP_piece 8, - DW_OP_entry_value(DW_OP_regx sub_reg1), DW_OP_stack_value, DW_OP_piece 8, [...] The question then becomes how the call site should look; should a composite location description be emitted there, and we then leave it up to the debugger to match those two composite location descriptions? Another alternative could be to emit a call site parameter entry for each sub-register, but firstly I'm unsure if that is even valid DWARF, and secondly it seems like that would complicate the collection of call site values quite a bit. As far as I can tell GCC does not emit any entry values / call sites in these cases, so we do not have something to compare with, but the former seems like the more reasonable approach. Currently when trying to emit a call site entry for a parameter composed of multiple DWARF registers a (DwarfRegs.size() == 1) assert is triggered in addMachineRegExpression(). Until the call site representation is figured out, and until there is use for these entry values in practice, this commit simply stops the invalid DWARF from being emitted. Reviewers: djtodoro, vsk, aprantl Reviewed By: djtodoro, vsk Subscribers: jyknight, hiraditya, fedor.sergeev, jrtc27, llvm-commits Tags: #debug-info, #llvm Differential Revision: https://reviews.llvm.org/D75270
87 lines
3.5 KiB
LLVM
87 lines
3.5 KiB
LLVM
; RUN: llc -debug-entry-values -filetype=asm -o - %s | FileCheck %s
|
|
|
|
; The q0 register does not have a DWARF register number, and is instead emitted
|
|
; as a composite location description with two sub-registers. Previously we
|
|
; emitted a single DW_OP_entry_value wrapping that whole composite location
|
|
; description, but that is not valid DWARF; DW_OP_entry_value operations can
|
|
; only hold DWARF expressions and register location descriptions.
|
|
;
|
|
; In the future we may want to emit a composite location description where each
|
|
; DW_OP_regx operation is wrapped in an entry value operation, but for now
|
|
; just verify that no invalid DWARF is emitted.
|
|
|
|
target datalayout = "E-m:e-i64:64-n32:64-S128"
|
|
target triple = "sparc64"
|
|
|
|
; Based on the following C reproducer:
|
|
;
|
|
; volatile long double global;
|
|
; extern void clobber();
|
|
; int foo(long double p) {
|
|
; global = p;
|
|
; clobber();
|
|
; return 123;
|
|
; }
|
|
|
|
; Verify that we got an entry value in the DIExpression...
|
|
; CHECK: DEBUG_VALUE: foo:p <- [DW_OP_LLVM_entry_value 1] $q0
|
|
|
|
; ... but that no entry value location was emitted:
|
|
; CHECK: .half 8 ! Loc expr size
|
|
; CHECK-NEXT: .byte 144 ! sub-register DW_OP_regx
|
|
; CHECK-NEXT: .byte 72 ! 72
|
|
; CHECK-NEXT: .byte 147 ! DW_OP_piece
|
|
; CHECK-NEXT: .byte 8 ! 8
|
|
; CHECK-NEXT: .byte 144 ! sub-register DW_OP_regx
|
|
; CHECK-NEXT: .byte 73 ! 73
|
|
; CHECK-NEXT: .byte 147 ! DW_OP_piece
|
|
; CHECK-NEXT: .byte 8 ! 8
|
|
; CHECK-NEXT: .xword 0
|
|
; CHECK-NEXT: .xword 0
|
|
|
|
@global = common global fp128 0xL00000000000000000000000000000000, align 16, !dbg !0
|
|
|
|
; Function Attrs: nounwind
|
|
define signext i32 @foo(fp128 %p) #0 !dbg !12 {
|
|
entry:
|
|
call void @llvm.dbg.value(metadata fp128 %p, metadata !17, metadata !DIExpression()), !dbg !18
|
|
store volatile fp128 %p, fp128* @global, align 16, !dbg !19
|
|
tail call void @clobber(), !dbg !20
|
|
ret i32 123, !dbg !21
|
|
}
|
|
|
|
declare void @clobber()
|
|
|
|
; Function Attrs: nounwind readnone speculatable willreturn
|
|
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
|
|
|
|
attributes #0 = { nounwind }
|
|
attributes #1 = { nounwind readnone speculatable willreturn }
|
|
|
|
!llvm.dbg.cu = !{!2}
|
|
!llvm.module.flags = !{!8, !9, !10}
|
|
!llvm.ident = !{!11}
|
|
|
|
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
|
!1 = distinct !DIGlobalVariable(name: "global", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true)
|
|
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
|
|
!3 = !DIFile(filename: "entry-value-complex-reg-expr.c", directory: "/")
|
|
!4 = !{}
|
|
!5 = !{!0}
|
|
!6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
|
|
!7 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float)
|
|
!8 = !{i32 2, !"Dwarf Version", i32 4}
|
|
!9 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!10 = !{i32 1, !"wchar_size", i32 4}
|
|
!11 = !{!"clang version 10.0.0"}
|
|
!12 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 3, type: !13, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !16)
|
|
!13 = !DISubroutineType(types: !14)
|
|
!14 = !{!15, !7}
|
|
!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!16 = !{!17}
|
|
!17 = !DILocalVariable(name: "p", arg: 1, scope: !12, file: !3, line: 3, type: !7)
|
|
!18 = !DILocation(line: 0, scope: !12)
|
|
!19 = !DILocation(line: 4, scope: !12)
|
|
!20 = !DILocation(line: 5, scope: !12)
|
|
!21 = !DILocation(line: 6, scope: !12)
|