Skip to content

Commit c18ab8b

Browse files
SouraVXmedismailben
authored andcommitted
Re-apply "[DebugInfo] Emit DW_OP_implicit_value for Floating point constants"
This patch was reverted in 7c18266 due to some failures observed on PCC based machines. Failures were due to Endianness issue and long double representation issues. Patch is revised to address Endianness issue. Furthermore, support for emission of `DW_OP_implicit_value` for `long double` has been removed (since it was unclean at the moment). Planning to handle this in a clean way soon! For more context, please refer to following review link. Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D83560
1 parent a03e563 commit c18ab8b

File tree

6 files changed

+178
-5
lines changed

6 files changed

+178
-5
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,8 +2513,21 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
25132513
// encoding is supported.
25142514
DwarfExpr.addWasmLocation(Loc.Index, static_cast<uint64_t>(Loc.Offset));
25152515
} else if (Value.isConstantFP()) {
2516-
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
2517-
DwarfExpr.addUnsignedConstant(RawBytes);
2516+
if (AP.getDwarfVersion() >= 4 && AP.getDwarfDebug()->tuneForGDB()) {
2517+
DwarfExpr.addConstantFP(Value.getConstantFP()->getValueAPF(), AP);
2518+
return;
2519+
} else if (Value.getConstantFP()
2520+
->getValueAPF()
2521+
.bitcastToAPInt()
2522+
.getBitWidth() <= 64 /*bits*/)
2523+
DwarfExpr.addUnsignedConstant(
2524+
Value.getConstantFP()->getValueAPF().bitcastToAPInt());
2525+
else
2526+
LLVM_DEBUG(
2527+
dbgs()
2528+
<< "Skipped DwarfExpression creation for ConstantFP of size"
2529+
<< Value.getConstantFP()->getValueAPF().bitcastToAPInt().getBitWidth()
2530+
<< " bits\n");
25182531
}
25192532
DwarfExpr.addExpression(std::move(ExprCursor));
25202533
}

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/BinaryFormat/Dwarf.h"
1818
#include "llvm/CodeGen/Register.h"
1919
#include "llvm/CodeGen/TargetRegisterInfo.h"
20+
#include "llvm/IR/DataLayout.h"
2021
#include "llvm/IR/DebugInfoMetadata.h"
2122
#include "llvm/Support/ErrorHandling.h"
2223
#include <algorithm>
@@ -25,6 +26,8 @@
2526

2627
using namespace llvm;
2728

29+
#define DEBUG_TYPE "dwarfdebug"
30+
2831
void DwarfExpression::emitConstu(uint64_t Value) {
2932
if (Value < 32)
3033
emitOp(dwarf::DW_OP_lit0 + Value);
@@ -219,6 +222,31 @@ void DwarfExpression::addUnsignedConstant(const APInt &Value) {
219222
}
220223
}
221224

225+
void DwarfExpression::addConstantFP(const APFloat &APF, const AsmPrinter &AP) {
226+
assert(isImplicitLocation() || isUnknownLocation());
227+
APInt API = APF.bitcastToAPInt();
228+
int NumBytes = API.getBitWidth() / 8;
229+
if (NumBytes == 4 /*float*/ || NumBytes == 8 /*double*/) {
230+
// FIXME: Add support for `long double`.
231+
emitOp(dwarf::DW_OP_implicit_value);
232+
emitUnsigned(NumBytes /*Size of the block in bytes*/);
233+
234+
const uint64_t *Value = API.getRawData();
235+
const bool IsLittleEndian = AP.getDataLayout().isLittleEndian();
236+
uint64_t Swapped = support::endian::byte_swap(
237+
*Value, IsLittleEndian ? support::little : support::big);
238+
239+
const char *SwappedBytes = reinterpret_cast<const char *>(&Swapped);
240+
for (int i = 0; i < NumBytes; ++i)
241+
emitData1(SwappedBytes[i]);
242+
243+
return;
244+
}
245+
LLVM_DEBUG(
246+
dbgs() << "Skipped DW_OP_implicit_value creation for ConstantFP of size: "
247+
<< API.getBitWidth() << " bits\n");
248+
}
249+
222250
bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
223251
DIExpressionCursor &ExprCursor,
224252
unsigned MachineReg,

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ class DwarfExpression {
299299
/// Emit an unsigned constant.
300300
void addUnsignedConstant(const APInt &Value);
301301

302+
/// Emit an floating point constant.
303+
void addConstantFP(const APFloat &Value, const AsmPrinter &AP);
304+
302305
/// Lock this down to become a memory location description.
303306
void setMemoryLocationKind() {
304307
assert(isUnknownLocation());

llvm/test/DebugInfo/X86/float_const_loclist.ll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,10 @@
2020
;
2121
; CHECK: .debug_info contents:
2222
; CHECK: DW_TAG_variable
23-
; CHECK-NEXT: DW_AT_location {{.*}} (
24-
; CHECK-NEXT: [0x[[START:.*]], 0x[[END:.*]]): DW_OP_constu 0xc8f5c28f5c28f800, DW_OP_piece 0x8, DW_OP_constu 0x4000, DW_OP_bit_piece 0x10 0x40)
2523
; CHECK-NEXT: DW_AT_name {{.*}}"ld"
2624
; CHECK: DW_TAG_variable
2725
; CHECK-NEXT: DW_AT_location {{.*}} (
28-
; CHECK-NEXT: [0x[[START]], 0x[[END]]): DW_OP_constu 0x4048f5c3)
26+
; CHECK-NEXT: [0x{{.*}}, 0x{{.*}}): DW_OP_constu 0x4048f5c3)
2927
; CHECK-NEXT: DW_AT_name {{.*}}"f"
3028

3129
source_filename = "test.c"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
;; This test checks for emission of DW_OP_implicit_value operation
2+
;; for double type.
3+
4+
; RUN: llc -debugger-tune=gdb -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s
5+
6+
; CHECK: .debug_info contents:
7+
; CHECK: DW_TAG_variable
8+
; CHECK-NEXT: DW_AT_location ({{.*}}
9+
; CHECK-NEXT: [{{.*}}): DW_OP_implicit_value 0x8 0x1f 0x85 0xeb 0x51 0xb8 0x1e 0x09 0x40)
10+
; CHECK-NEXT: DW_AT_name ("d")
11+
12+
;; Generated from: clang -ggdb -O1
13+
;;int main() {
14+
;; double d = 3.14;
15+
;; printf("dummy\n");
16+
;; d *= d;
17+
;; return 0;
18+
;;}
19+
20+
; ModuleID = 'implicit_value-double.c'
21+
source_filename = "implicit_value-double.c"
22+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
23+
target triple = "x86_64-unknown-linux-gnu"
24+
25+
@str = private unnamed_addr constant [6 x i8] c"dummy\00", align 1
26+
27+
; Function Attrs: nofree nounwind uwtable
28+
define dso_local i32 @main() local_unnamed_addr #0 !dbg !7 {
29+
entry:
30+
call void @llvm.dbg.value(metadata double 3.140000e+00, metadata !12, metadata !DIExpression()), !dbg !14
31+
%puts = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @str, i64 0, i64 0)), !dbg !15
32+
call void @llvm.dbg.value(metadata double undef, metadata !12, metadata !DIExpression()), !dbg !14
33+
ret i32 0, !dbg !16
34+
}
35+
36+
; Function Attrs: nounwind readnone speculatable willreturn
37+
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
38+
39+
; Function Attrs: nofree nounwind
40+
declare i32 @puts(i8* nocapture readonly) local_unnamed_addr #2
41+
42+
attributes #0 = { nofree nounwind uwtable }
43+
attributes #1 = { nounwind readnone speculatable willreturn }
44+
attributes #2 = { nofree nounwind }
45+
46+
!llvm.dbg.cu = !{!0}
47+
!llvm.module.flags = !{!3, !4, !5}
48+
!llvm.ident = !{!6}
49+
50+
!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)
51+
!1 = !DIFile(filename: "implicit_value-double.c", directory: "/home/")
52+
!2 = !{}
53+
!3 = !{i32 7, !"Dwarf Version", i32 4}
54+
!4 = !{i32 2, !"Debug Info Version", i32 3}
55+
!5 = !{i32 1, !"wchar_size", i32 4}
56+
!6 = !{!"clang version 11.0.0"}
57+
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
58+
!8 = !DISubroutineType(types: !9)
59+
!9 = !{!10}
60+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
61+
!11 = !{!12}
62+
!12 = !DILocalVariable(name: "d", scope: !7, file: !1, line: 2, type: !13)
63+
!13 = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)
64+
!14 = !DILocation(line: 0, scope: !7)
65+
!15 = !DILocation(line: 3, column: 2, scope: !7)
66+
!16 = !DILocation(line: 5, column: 2, scope: !7)
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
;; This test checks for emission of DW_OP_implicit_value operation
2+
;; for float type.
3+
4+
; RUN: llc -debugger-tune=gdb -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s
5+
6+
; CHECK: .debug_info contents:
7+
; CHECK: DW_TAG_variable
8+
; CHECK-NEXT: DW_AT_location ({{.*}}
9+
; CHECK-NEXT: [{{.*}}): DW_OP_implicit_value 0x4 0xc3 0xf5 0x48 0x40)
10+
; CHECK-NEXT: DW_AT_name ("f")
11+
12+
;; Generated from: clang -ggdb -O1
13+
;;int main() {
14+
;; float f = 3.14f;
15+
;; printf("dummy\n");
16+
;; f *= f;
17+
;; return 0;
18+
;;}
19+
; ModuleID = 'implicit_value-float.c'
20+
source_filename = "implicit_value-float.c"
21+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
22+
target triple = "x86_64-unknown-linux-gnu"
23+
24+
@str = private unnamed_addr constant [6 x i8] c"dummy\00", align 1
25+
26+
; Function Attrs: nofree nounwind uwtable
27+
define dso_local i32 @main() local_unnamed_addr #0 !dbg !7 {
28+
entry:
29+
call void @llvm.dbg.value(metadata float 0x40091EB860000000, metadata !12, metadata !DIExpression()), !dbg !14
30+
%puts = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([6 x i8], [6 x i8]* @str, i64 0, i64 0)), !dbg !15
31+
call void @llvm.dbg.value(metadata float undef, metadata !12, metadata !DIExpression()), !dbg !14
32+
ret i32 0, !dbg !16
33+
}
34+
35+
; Function Attrs: nounwind readnone speculatable willreturn
36+
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
37+
38+
; Function Attrs: nofree nounwind
39+
declare i32 @puts(i8* nocapture readonly) local_unnamed_addr #2
40+
41+
attributes #0 = { nofree nounwind uwtable }
42+
attributes #1 = { nounwind readnone speculatable willreturn }
43+
attributes #2 = { nofree nounwind }
44+
45+
!llvm.dbg.cu = !{!0}
46+
!llvm.module.flags = !{!3, !4, !5}
47+
!llvm.ident = !{!6}
48+
49+
!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)
50+
!1 = !DIFile(filename: "implicit_value-float.c", directory: "/home/")
51+
!2 = !{}
52+
!3 = !{i32 7, !"Dwarf Version", i32 4}
53+
!4 = !{i32 2, !"Debug Info Version", i32 3}
54+
!5 = !{i32 1, !"wchar_size", i32 4}
55+
!6 = !{!"clang version 11.0.0"}
56+
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
57+
!8 = !DISubroutineType(types: !9)
58+
!9 = !{!10}
59+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
60+
!11 = !{!12}
61+
!12 = !DILocalVariable(name: "f", scope: !7, file: !1, line: 2, type: !13)
62+
!13 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
63+
!14 = !DILocation(line: 0, scope: !7)
64+
!15 = !DILocation(line: 3, column: 2, scope: !7)
65+
!16 = !DILocation(line: 5, column: 2, scope: !7)

0 commit comments

Comments
 (0)