diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2488,8 +2488,11 @@ // encoding is supported. DwarfExpr.addWasmLocation(Loc.Index, static_cast(Loc.Offset)); } else if (Value.isConstantFP()) { - APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt(); - DwarfExpr.addUnsignedConstant(RawBytes); + if (AP.getDwarfVersion() >= 4 && AP.getDwarfDebug()->tuneForGDB()) + DwarfExpr.addConstantFP(Value.getConstantFP()->getValueAPF()); + else + DwarfExpr.addUnsignedConstant( + Value.getConstantFP()->getValueAPF().bitcastToAPInt()); } DwarfExpr.addExpression(std::move(ExprCursor)); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -296,6 +296,9 @@ /// Emit an unsigned constant. void addUnsignedConstant(const APInt &Value); + /// Emit floating point constant. + void addConstantFP(const APFloat &Value); + /// Lock this down to become a memory location description. void setMemoryLocationKind() { assert(isUnknownLocation()); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -219,6 +219,31 @@ } } +void DwarfExpression::addConstantFP(const APFloat &Value) { + assert(isImplicitLocation() || isUnknownLocation()); + APInt RawBytes = Value.bitcastToAPInt(); + int NumBytes = RawBytes.getBitWidth() / 8; + const char *Data = (const char *)RawBytes.getRawData(); + emitOp(dwarf::DW_OP_implicit_value); + if (NumBytes == 4 /*float*/ || NumBytes == 8 /*double*/) { + emitUnsigned(NumBytes /*Size of the block in bytes*/); + for (int i = 0; i < NumBytes; ++i) + emitData1(Data[i]); + } + if (NumBytes == 10 /*long double*/) { + // long double IEEE representation uses 80 bits(10 bytes). + // 6 bytes are padded to make it 128 bits(16 bytes) due to + // addressing restrictions. + emitUnsigned(16 /*Size of the block in bytes*/); + // Emit the block of bytes. + for (int i = 0; i < NumBytes; ++i) + emitData1(Data[i]); + // Emit the rest as padding bytes. + for (int i = 0; i < 16 - NumBytes; ++i) + emitData1(0); + } +} + bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, DIExpressionCursor &ExprCursor, unsigned MachineReg, diff --git a/llvm/test/DebugInfo/X86/implicit_value-double.ll b/llvm/test/DebugInfo/X86/implicit_value-double.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/implicit_value-double.ll @@ -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(""); +;; 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) diff --git a/llvm/test/DebugInfo/X86/implicit_value-float.ll b/llvm/test/DebugInfo/X86/implicit_value-float.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/implicit_value-float.ll @@ -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(""); +;; 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) diff --git a/llvm/test/DebugInfo/X86/implicit_value-ld.ll b/llvm/test/DebugInfo/X86/implicit_value-ld.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/implicit_value-ld.ll @@ -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(""); +;; 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)