Skip to content

Commit 104a9f9

Browse files
committed
[Debuginfo][DW_OP_implicit_pointer] (1/7) Support for DW_OP_LLVM_implicit_pointer
New dwarf operator DW_OP_LLVM_implicit_pointer is introduced (present only in LLVM IR) This operator is required as it is different than DWARF operator DW_OP_implicit_pointer in representation and specification (number and types of operands) and later can not be used as multiple level. Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D84113
1 parent 7803636 commit 104a9f9

File tree

5 files changed

+123
-4
lines changed

5 files changed

+123
-4
lines changed

llvm/docs/LangRef.rst

+27
Original file line numberDiff line numberDiff line change
@@ -5284,6 +5284,33 @@ The current supported opcode vocabulary is limited:
52845284
of the stack. This opcode can be used to calculate bounds of fortran assumed
52855285
rank array which has rank known at run time and current dimension number is
52865286
implicitly first element of the stack.
5287+
- ``DW_OP_LLVM_implicit_pointer`` It specifies the dereferenced value. It can
5288+
be used to represent pointer variables which are optimized out but the value
5289+
it points to is known. This operator is required as it is different than DWARF
5290+
operator DW_OP_implicit_pointer in representation and specification (number
5291+
and types of operands) and later can not be used as multiple level.
5292+
5293+
.. code-block:: text
5294+
5295+
IR for "*ptr = 4;"
5296+
--------------
5297+
call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !20)
5298+
!17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5,
5299+
type: !18)
5300+
!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
5301+
!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
5302+
!20 = !DIExpression(DW_OP_LLVM_implicit_pointer))
5303+
5304+
IR for "**ptr = 4;"
5305+
--------------
5306+
call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !21)
5307+
!17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5,
5308+
type: !18)
5309+
!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
5310+
!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)
5311+
!20 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
5312+
!21 = !DIExpression(DW_OP_LLVM_implicit_pointer,
5313+
DW_OP_LLVM_implicit_pointer))
52875314

52885315
DWARF specifies three kinds of simple location descriptions: Register, memory,
52895316
and implicit location descriptions. Note that a location description is

llvm/include/llvm/BinaryFormat/Dwarf.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,11 @@ enum LocationAtom {
120120
#include "llvm/BinaryFormat/Dwarf.def"
121121
DW_OP_lo_user = 0xe0,
122122
DW_OP_hi_user = 0xff,
123-
DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata.
124-
DW_OP_LLVM_convert = 0x1001, ///< Only used in LLVM metadata.
125-
DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata.
126-
DW_OP_LLVM_entry_value = 0x1003, ///< Only used in LLVM metadata.
123+
DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata.
124+
DW_OP_LLVM_convert = 0x1001, ///< Only used in LLVM metadata.
125+
DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata.
126+
DW_OP_LLVM_entry_value = 0x1003, ///< Only used in LLVM metadata.
127+
DW_OP_LLVM_implicit_pointer = 0x1004, ///< Only used in LLVM metadata.
127128
};
128129

129130
enum TypeKind : uint8_t {

llvm/lib/BinaryFormat/Dwarf.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
151151
return "DW_OP_LLVM_tag_offset";
152152
case DW_OP_LLVM_entry_value:
153153
return "DW_OP_LLVM_entry_value";
154+
case DW_OP_LLVM_implicit_pointer:
155+
return "DW_OP_LLVM_implicit_pointer";
154156
}
155157
}
156158

@@ -163,6 +165,7 @@ unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) {
163165
.Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment)
164166
.Case("DW_OP_LLVM_tag_offset", DW_OP_LLVM_tag_offset)
165167
.Case("DW_OP_LLVM_entry_value", DW_OP_LLVM_entry_value)
168+
.Case("DW_OP_LLVM_implicit_pointer", DW_OP_LLVM_implicit_pointer)
166169
.Default(0);
167170
}
168171

llvm/lib/IR/DebugInfoMetadata.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,7 @@ bool DIExpression::isValid() const {
11141114
return I->get() == expr_op_begin()->get() && I->getArg(0) == 1 &&
11151115
getNumElements() == 2;
11161116
}
1117+
case dwarf::DW_OP_LLVM_implicit_pointer:
11171118
case dwarf::DW_OP_LLVM_convert:
11181119
case dwarf::DW_OP_LLVM_tag_offset:
11191120
case dwarf::DW_OP_constu:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
; Round trip test for DW_OP_LLVM_implicit_pointer metadata
2+
3+
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
4+
5+
;---------------------------
6+
;static const char *b = "opq";
7+
;volatile int v;
8+
;int main() {
9+
; int var = 4;
10+
; int *ptr1;
11+
; int **ptr2;
12+
;
13+
; v++;
14+
; ptr1 = &var;
15+
; ptr2 = &ptr1;
16+
; v++;
17+
;
18+
; return *ptr1 - 5 + **ptr2;
19+
;}
20+
;---------------------------
21+
22+
; ModuleID = 'LLVM_implicit_pointer.c'
23+
source_filename = "LLVM_implicit_pointer.c"
24+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
25+
target triple = "x86_64-unknown-linux-gnu"
26+
27+
@v = dso_local global i32 0, align 4, !dbg !0
28+
29+
; Function Attrs: nofree norecurse nounwind uwtable
30+
define dso_local i32 @main() local_unnamed_addr !dbg !12 {
31+
entry:
32+
; CHECK: call void @llvm.dbg.value(metadata i32 4, metadata [[VAR:![0-9]+]], metadata !DIExpression())
33+
call void @llvm.dbg.value(metadata i32 4, metadata !16, metadata !DIExpression()), !dbg !21
34+
%0 = load volatile i32, i32* @v, align 4, !dbg !22, !tbaa !23
35+
%inc = add nsw i32 %0, 1, !dbg !22
36+
store volatile i32 %inc, i32* @v, align 4, !dbg !22, !tbaa !23
37+
38+
; CHECK: call void @llvm.dbg.value(metadata i32 4, metadata [[PTR1:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_implicit_pointer))
39+
call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !DIExpression(DW_OP_LLVM_implicit_pointer)), !dbg !21
40+
41+
; CHECK: call void @llvm.dbg.value(metadata i32 4, metadata [[PTR2:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_implicit_pointer))
42+
call void @llvm.dbg.value(metadata i32 4, metadata !19, metadata !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_implicit_pointer)), !dbg !21
43+
%1 = load volatile i32, i32* @v, align 4, !dbg !27, !tbaa !23
44+
%inc1 = add nsw i32 %1, 1, !dbg !27
45+
store volatile i32 %inc1, i32* @v, align 4, !dbg !27, !tbaa !23
46+
ret i32 3, !dbg !28
47+
}
48+
49+
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
50+
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
51+
52+
!llvm.dbg.cu = !{!2}
53+
!llvm.module.flags = !{!8, !9, !10}
54+
!llvm.ident = !{!11}
55+
56+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
57+
!1 = distinct !DIGlobalVariable(name: "v", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true)
58+
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None)
59+
!3 = !DIFile(filename: "LLVM_implicit_pointer.c", directory: "/dir", checksumkind: CSK_MD5, checksum: "218aaa8dc9f04b056b56d944d06383dd")
60+
!4 = !{}
61+
!5 = !{!0}
62+
!6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
63+
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
64+
!8 = !{i32 7, !"Dwarf Version", i32 5}
65+
!9 = !{i32 2, !"Debug Info Version", i32 3}
66+
!10 = !{i32 1, !"wchar_size", i32 4}
67+
!11 = !{!"clang version 12.0.0"}
68+
!12 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 3, type: !13, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !15)
69+
!13 = !DISubroutineType(types: !14)
70+
!14 = !{!7}
71+
!15 = !{!16, !17, !19}
72+
; CHECK: [[VAR]] = !DILocalVariable(name: "var"
73+
!16 = !DILocalVariable(name: "var", scope: !12, file: !3, line: 4, type: !7)
74+
; CHECK: [[PTR1]] = !DILocalVariable(name: "ptr1"
75+
!17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5, type: !18)
76+
!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
77+
; CHECK: [[PTR2]] = !DILocalVariable(name: "ptr2"
78+
!19 = !DILocalVariable(name: "ptr2", scope: !12, file: !3, line: 6, type: !20)
79+
!20 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64)
80+
!21 = !DILocation(line: 0, scope: !12)
81+
!22 = !DILocation(line: 8, column: 4, scope: !12)
82+
!23 = !{!24, !24, i64 0}
83+
!24 = !{!"int", !25, i64 0}
84+
!25 = !{!"omnipotent char", !26, i64 0}
85+
!26 = !{!"Simple C/C++ TBAA"}
86+
!27 = !DILocation(line: 11, column: 4, scope: !12)
87+
!28 = !DILocation(line: 13, column: 3, scope: !12)

0 commit comments

Comments
 (0)