Skip to content

[llvm/DebugInfo] Emit DW_OP_implicit_value when tuning for LLDB #2035

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2513,8 +2513,22 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
// encoding is supported.
DwarfExpr.addWasmLocation(Loc.Index, static_cast<uint64_t>(Loc.Offset));
} else if (Value.isConstantFP()) {
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
DwarfExpr.addUnsignedConstant(RawBytes);
if (AP.getDwarfVersion() >= 4 && (AP.getDwarfDebug()->tuneForGDB() ||
AP.getDwarfDebug()->tuneForLLDB())) {
DwarfExpr.addConstantFP(Value.getConstantFP()->getValueAPF(), AP);
return;
} else if (Value.getConstantFP()
->getValueAPF()
.bitcastToAPInt()
.getBitWidth() <= 64 /*bits*/)
DwarfExpr.addUnsignedConstant(
Value.getConstantFP()->getValueAPF().bitcastToAPInt());
else
LLVM_DEBUG(
dbgs()
<< "Skipped DwarfExpression creation for ConstantFP of size"
<< Value.getConstantFP()->getValueAPF().bitcastToAPInt().getBitWidth()
<< " bits\n");
}
DwarfExpr.addExpression(std::move(ExprCursor));
}
Expand Down
28 changes: 28 additions & 0 deletions llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
Expand All @@ -25,6 +26,8 @@

using namespace llvm;

#define DEBUG_TYPE "dwarfdebug"

void DwarfExpression::emitConstu(uint64_t Value) {
if (Value < 32)
emitOp(dwarf::DW_OP_lit0 + Value);
Expand Down Expand Up @@ -219,6 +222,31 @@ void DwarfExpression::addUnsignedConstant(const APInt &Value) {
}
}

void DwarfExpression::addConstantFP(const APFloat &APF, const AsmPrinter &AP) {
assert(isImplicitLocation() || isUnknownLocation());
APInt API = APF.bitcastToAPInt();
int NumBytes = API.getBitWidth() / 8;
if (NumBytes == 4 /*float*/ || NumBytes == 8 /*double*/) {
// FIXME: Add support for `long double`.
emitOp(dwarf::DW_OP_implicit_value);
emitUnsigned(NumBytes /*Size of the block in bytes*/);

const uint64_t *Value = API.getRawData();
const bool IsLittleEndian = AP.getDataLayout().isLittleEndian();
uint64_t Swapped = support::endian::byte_swap(
*Value, IsLittleEndian ? support::little : support::big);

const char *SwappedBytes = reinterpret_cast<const char *>(&Swapped);
for (int i = 0; i < NumBytes; ++i)
emitData1(SwappedBytes[i]);

return;
}
LLVM_DEBUG(
dbgs() << "Skipped DW_OP_implicit_value creation for ConstantFP of size: "
<< API.getBitWidth() << " bits\n");
}

bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
DIExpressionCursor &ExprCursor,
unsigned MachineReg,
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,9 @@ class DwarfExpression {
/// Emit an unsigned constant.
void addUnsignedConstant(const APInt &Value);

/// Emit an floating point constant.
void addConstantFP(const APFloat &Value, const AsmPrinter &AP);

/// Lock this down to become a memory location description.
void setMemoryLocationKind() {
assert(isUnknownLocation());
Expand Down
4 changes: 1 addition & 3 deletions llvm/test/DebugInfo/X86/float_const_loclist.ll
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@
;
; CHECK: .debug_info contents:
; CHECK: DW_TAG_variable
; CHECK-NEXT: DW_AT_location {{.*}} (
; CHECK-NEXT: [0x[[START:.*]], 0x[[END:.*]]): DW_OP_constu 0xc8f5c28f5c28f800, DW_OP_piece 0x8, DW_OP_constu 0x4000, DW_OP_bit_piece 0x10 0x40)
; CHECK-NEXT: DW_AT_name {{.*}}"ld"
; CHECK: DW_TAG_variable
; CHECK-NEXT: DW_AT_location {{.*}} (
; CHECK-NEXT: [0x[[START]], 0x[[END]]): DW_OP_constu 0x4048f5c3)
; CHECK-NEXT: [0x{{.*}}, 0x{{.*}}): DW_OP_constu 0x4048f5c3)
; CHECK-NEXT: DW_AT_name {{.*}}"f"

source_filename = "test.c"
Expand Down
75 changes: 75 additions & 0 deletions llvm/test/DebugInfo/X86/implicit_value-double.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
;; 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
; RUN: llc -debugger-tune=lldb -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")

; RUN: llc -debugger-tune=sce -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s -check-prefix=SCE-CHECK

; SCE-CHECK: .debug_info contents:
; SCE-CHECK: DW_TAG_variable
; SCE-CHECK-NEXT: DW_AT_location ({{.*}}
; SCE-CHECK-NEXT: [{{.*}}): DW_OP_constu 0x40091eb851eb851f, DW_OP_stack_value)
; SCE-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)
74 changes: 74 additions & 0 deletions llvm/test/DebugInfo/X86/implicit_value-float.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
;; 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
; RUN: llc -debugger-tune=lldb -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")

; RUN: llc -debugger-tune=sce -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s -check-prefix=SCE-CHECK

; SCE-CHECK: .debug_info contents:
; SCE-CHECK: DW_TAG_variable
; SCE-CHECK-NEXT: DW_AT_location ({{.*}}
; SCE-CHECK-NEXT: [{{.*}}): DW_OP_constu 0x4048f5c3, DW_OP_stack_value)
; SCE-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)
6 changes: 3 additions & 3 deletions llvm/test/DebugInfo/X86/stack-value-piece.ll
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@
; CHECK: DW_AT_name ("f")
; CHECK: DW_TAG_variable
; CHECK-NEXT: DW_AT_location ([[F:0x[0-9a-f]+]]
; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_reg17 XMM0, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4
; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4)
; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_reg17 XMM0, DW_OP_piece 0x4, {{(DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4|DW_OP_implicit_value 0x4 0x00 0x00 0x00 0x00)}}
; CHECK-NEXT: [{{.*}}, {{.*}}): DW_OP_piece 0x4, {{(DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4|DW_OP_implicit_value 0x4 0x00 0x00 0x00 0x00)}})
; CHECK-NEXT: DW_AT_name ("r")
;
; CHECK: .debug_loc contents:
; CHECK: [[I]]:
; CHECK-NEXT: ({{.*}}, {{.*}}): DW_OP_reg5 RDI, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4
; CHECK: [[F]]:
; CHECK-NEXT: ({{.*}}, {{.*}}): DW_OP_reg17 XMM0, DW_OP_piece 0x4, DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4
; CHECK-NEXT: ({{.*}}, {{.*}}): DW_OP_reg17 XMM0, DW_OP_piece 0x4, {{DW_OP_lit0, DW_OP_stack_value, DW_OP_piece 0x4|DW_OP_implicit_value 0x4 0x00 0x00 0x00 0x00}}

source_filename = "stack-value-piece.c"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
Expand Down