Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DebugInfo] Emit DW_OP_implicit_value for Floating point constants
Summary: llvm is missing support for DW_OP_implicit_value operation. DW_OP_implicit_value op is indispensable for cases such as optimized out long double variables. For intro refer: DWARFv5 Spec Pg: 40 2.6.1.1.4 Implicit Location Descriptions Consider the following example: ``` int main() { long double ld = 3.14; printf("dummy\n"); ld *= ld; return 0; } ``` when compiled with tunk `clang` as `clang test.c -g -O1` produces following location description of variable `ld`: ``` DW_AT_location (0x00000000: [0x0000000000201691, 0x000000000020169b): DW_OP_constu 0xc8f5c28f5c28f800, DW_OP_stack_value, DW_OP_piece 0x8, DW_OP_constu 0x4000, DW_OP_stack_value, DW_OP_bit_piece 0x10 0x40, DW_OP_stack_value) DW_AT_name ("ld") ``` Here one may notice that this representation is incorrect(DWARF4 stack could only hold integers(and only up to the size of address)). Here the variable size itself is `128` bit. GDB and LLDB confirms this: ``` (gdb) p ld $1 = <invalid float value> (lldb) frame variable ld (long double) ld = <extracting data from value failed> ``` GCC represents/uses DW_OP_implicit_value in these sort of situations. Based on the discussion with Jakub Jelinek regarding GCC's motivation for using this, I concluded that DW_OP_implicit_value is most appropriate in this case. Link: https://gcc.gnu.org/pipermail/gcc/2020-July/233057.html GDB seems happy after this patch:(LLDB doesn't have support for DW_OP_implicit_value) ``` (gdb) p ld p ld $1 = 3.14000000000000012434 ``` Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D83560
- Loading branch information
Showing
7 changed files
with
252 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
;; This test checks for emission of DW_OP_implicit_value operation | ||
;; for double type. | ||
|
||
; RUN: llc -debugger-tune=gdb -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s | ||
|
||
; CHECK: .debug_info contents: | ||
; CHECK: DW_TAG_variable | ||
; CHECK-NEXT: DW_AT_location ({{.*}} | ||
; CHECK-NEXT: [{{.*}}): DW_OP_implicit_value 0x8 0x1f 0x85 0xeb 0x51 0xb8 0x1e 0x09 0x40) | ||
; CHECK-NEXT: DW_AT_name ("d") | ||
|
||
;; Generated from: clang -ggdb -O1 | ||
;;int main() { | ||
;; double d = 3.14; | ||
;; printf("dummy\n"); | ||
;; d *= d; | ||
;; return 0; | ||
;;} | ||
|
||
; ModuleID = 'implicit_value-double.c' | ||
source_filename = "implicit_value-double.c" | ||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
@str = private unnamed_addr constant [6 x i8] c"dummy\00", align 1 | ||
|
||
; Function Attrs: nofree nounwind uwtable | ||
define dso_local i32 @main() local_unnamed_addr #0 !dbg !7 { | ||
entry: | ||
call void @llvm.dbg.value(metadata double 3.140000e+00, metadata !12, metadata !DIExpression()), !dbg !14 | ||
%puts = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @str, i64 0, i64 0)), !dbg !15 | ||
call void @llvm.dbg.value(metadata double undef, metadata !12, metadata !DIExpression()), !dbg !14 | ||
ret i32 0, !dbg !16 | ||
} | ||
|
||
; Function Attrs: nounwind readnone speculatable willreturn | ||
declare void @llvm.dbg.value(metadata, metadata, metadata) #1 | ||
|
||
; Function Attrs: nofree nounwind | ||
declare i32 @puts(i8* nocapture readonly) local_unnamed_addr #2 | ||
|
||
attributes #0 = { nofree nounwind uwtable } | ||
attributes #1 = { nounwind readnone speculatable willreturn } | ||
attributes #2 = { nofree 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 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) | ||
!1 = !DIFile(filename: "implicit_value-double.c", directory: "/home/") | ||
!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 11.0.0"} | ||
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) | ||
!8 = !DISubroutineType(types: !9) | ||
!9 = !{!10} | ||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
!11 = !{!12} | ||
!12 = !DILocalVariable(name: "d", scope: !7, file: !1, line: 2, type: !13) | ||
!13 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float) | ||
!14 = !DILocation(line: 0, scope: !7) | ||
!15 = !DILocation(line: 3, column: 2, scope: !7) | ||
!16 = !DILocation(line: 5, column: 2, scope: !7) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
;; This test checks for emission of DW_OP_implicit_value operation | ||
;; for float type. | ||
|
||
; RUN: llc -debugger-tune=gdb -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s | ||
|
||
; CHECK: .debug_info contents: | ||
; CHECK: DW_TAG_variable | ||
; CHECK-NEXT: DW_AT_location ({{.*}} | ||
; CHECK-NEXT: [{{.*}}): DW_OP_implicit_value 0x4 0xc3 0xf5 0x48 0x40) | ||
; CHECK-NEXT: DW_AT_name ("f") | ||
|
||
;; Generated from: clang -ggdb -O1 | ||
;;int main() { | ||
;; float f = 3.14f; | ||
;; printf("dummy\n"); | ||
;; f *= f; | ||
;; return 0; | ||
;;} | ||
; ModuleID = 'implicit_value-float.c' | ||
source_filename = "implicit_value-float.c" | ||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
@str = private unnamed_addr constant [6 x i8] c"dummy\00", align 1 | ||
|
||
; Function Attrs: nofree nounwind uwtable | ||
define dso_local i32 @main() local_unnamed_addr #0 !dbg !7 { | ||
entry: | ||
call void @llvm.dbg.value(metadata float 0x40091EB860000000, metadata !12, metadata !DIExpression()), !dbg !14 | ||
%puts = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @str, i64 0, i64 0)), !dbg !15 | ||
call void @llvm.dbg.value(metadata float undef, metadata !12, metadata !DIExpression()), !dbg !14 | ||
ret i32 0, !dbg !16 | ||
} | ||
|
||
; Function Attrs: nounwind readnone speculatable willreturn | ||
declare void @llvm.dbg.value(metadata, metadata, metadata) #1 | ||
|
||
; Function Attrs: nofree nounwind | ||
declare i32 @puts(i8* nocapture readonly) local_unnamed_addr #2 | ||
|
||
attributes #0 = { nofree nounwind uwtable } | ||
attributes #1 = { nounwind readnone speculatable willreturn } | ||
attributes #2 = { nofree 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 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) | ||
!1 = !DIFile(filename: "implicit_value-float.c", directory: "/home/") | ||
!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 11.0.0"} | ||
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) | ||
!8 = !DISubroutineType(types: !9) | ||
!9 = !{!10} | ||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
!11 = !{!12} | ||
!12 = !DILocalVariable(name: "f", scope: !7, file: !1, line: 2, type: !13) | ||
!13 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) | ||
!14 = !DILocation(line: 0, scope: !7) | ||
!15 = !DILocation(line: 3, column: 2, scope: !7) | ||
!16 = !DILocation(line: 5, column: 2, scope: !7) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
;; This test checks for emission of DW_OP_implicit_value operation | ||
;; for long double type. | ||
|
||
; RUN: llc -debugger-tune=gdb -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s | ||
|
||
; CHECK: .debug_info contents: | ||
; CHECK: DW_TAG_variable | ||
; CHECK-NEXT: DW_AT_location ({{.*}} | ||
; CHECK-NEXT: [{{.*}}): DW_OP_implicit_value 0x10 0x00 0xf8 0x28 0x5c 0x8f 0xc2 0xf5 0xc8 0x00 0x40 0x00 0x00 0x00 0x00 0x00 0x00) | ||
; CHECK-NEXT: DW_AT_name ("ld") | ||
|
||
;; Generated from: clang -ggdb -O1 | ||
;;int main() { | ||
;; long double ld = 3.14; | ||
;; printf("dummy\n"); | ||
;; ld *= ld; | ||
;; return 0; | ||
;;} | ||
|
||
; ModuleID = 'implicit_value-ld.c' | ||
source_filename = "implicit_value-ld.c" | ||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
@str = private unnamed_addr constant [6 x i8] c"dummy\00", align 1 | ||
|
||
; Function Attrs: nofree nounwind uwtable | ||
define dso_local i32 @main() local_unnamed_addr #0 !dbg !7 { | ||
entry: | ||
call void @llvm.dbg.declare(metadata [6 x i8]* undef, metadata !12, metadata !DIExpression(DW_OP_LLVM_fragment, 80, 48)), !dbg !14 | ||
call void @llvm.dbg.value(metadata x86_fp80 0xK4000C8F5C28F5C28F800, metadata !12, metadata !DIExpression()), !dbg !15 | ||
%puts = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @str, i64 0, i64 0)), !dbg !16 | ||
call void @llvm.dbg.value(metadata x86_fp80 undef, metadata !12, metadata !DIExpression()), !dbg !15 | ||
ret i32 0, !dbg !17 | ||
} | ||
|
||
; Function Attrs: nounwind readnone speculatable willreturn | ||
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 | ||
|
||
; Function Attrs: nounwind readnone speculatable willreturn | ||
declare void @llvm.dbg.value(metadata, metadata, metadata) #1 | ||
|
||
; Function Attrs: nofree nounwind | ||
declare i32 @puts(i8* nocapture readonly) local_unnamed_addr #2 | ||
|
||
attributes #0 = { nofree nounwind uwtable } | ||
attributes #1 = { nounwind readnone speculatable willreturn } | ||
attributes #2 = { nofree 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 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) | ||
!1 = !DIFile(filename: "implicit_value-ld.c", directory: "/home/") | ||
!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 11.0.0"} | ||
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) | ||
!8 = !DISubroutineType(types: !9) | ||
!9 = !{!10} | ||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
!11 = !{!12} | ||
!12 = !DILocalVariable(name: "ld", scope: !7, file: !1, line: 2, type: !13) | ||
!13 = !DIBasicType(name: "long double", size: 128, encoding: DW_ATE_float) | ||
!14 = !DILocation(line: 2, column: 14, scope: !7) | ||
!15 = !DILocation(line: 0, scope: !7) | ||
!16 = !DILocation(line: 3, column: 2, scope: !7) | ||
!17 = !DILocation(line: 5, column: 2, scope: !7) |