Skip to content

Commit

Permalink
[Debuginfo][DW_OP_implicit_pointer] (1/7) Support for DW_OP_LLVM_impl…
Browse files Browse the repository at this point in the history
…icit_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
  • Loading branch information
alokkrsharma committed Jan 15, 2021
1 parent 7803636 commit 104a9f9
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 4 deletions.
27 changes: 27 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5284,6 +5284,33 @@ The current supported opcode vocabulary is limited:
of the stack. This opcode can be used to calculate bounds of fortran assumed
rank array which has rank known at run time and current dimension number is
implicitly first element of the stack.
- ``DW_OP_LLVM_implicit_pointer`` It specifies the dereferenced value. It can
be used to represent pointer variables which are optimized out but the value
it points to is known. 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.

.. code-block:: text

IR for "*ptr = 4;"
--------------
call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !20)
!17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5,
type: !18)
!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!20 = !DIExpression(DW_OP_LLVM_implicit_pointer))

IR for "**ptr = 4;"
--------------
call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !21)
!17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5,
type: !18)
!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)
!20 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!21 = !DIExpression(DW_OP_LLVM_implicit_pointer,
DW_OP_LLVM_implicit_pointer))

DWARF specifies three kinds of simple location descriptions: Register, memory,
and implicit location descriptions. Note that a location description is
Expand Down
9 changes: 5 additions & 4 deletions llvm/include/llvm/BinaryFormat/Dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,11 @@ enum LocationAtom {
#include "llvm/BinaryFormat/Dwarf.def"
DW_OP_lo_user = 0xe0,
DW_OP_hi_user = 0xff,
DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata.
DW_OP_LLVM_convert = 0x1001, ///< Only used in LLVM metadata.
DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata.
DW_OP_LLVM_entry_value = 0x1003, ///< Only used in LLVM metadata.
DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata.
DW_OP_LLVM_convert = 0x1001, ///< Only used in LLVM metadata.
DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata.
DW_OP_LLVM_entry_value = 0x1003, ///< Only used in LLVM metadata.
DW_OP_LLVM_implicit_pointer = 0x1004, ///< Only used in LLVM metadata.
};

enum TypeKind : uint8_t {
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/BinaryFormat/Dwarf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ StringRef llvm::dwarf::OperationEncodingString(unsigned Encoding) {
return "DW_OP_LLVM_tag_offset";
case DW_OP_LLVM_entry_value:
return "DW_OP_LLVM_entry_value";
case DW_OP_LLVM_implicit_pointer:
return "DW_OP_LLVM_implicit_pointer";
}
}

Expand All @@ -163,6 +165,7 @@ unsigned llvm::dwarf::getOperationEncoding(StringRef OperationEncodingString) {
.Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment)
.Case("DW_OP_LLVM_tag_offset", DW_OP_LLVM_tag_offset)
.Case("DW_OP_LLVM_entry_value", DW_OP_LLVM_entry_value)
.Case("DW_OP_LLVM_implicit_pointer", DW_OP_LLVM_implicit_pointer)
.Default(0);
}

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/DebugInfoMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,7 @@ bool DIExpression::isValid() const {
return I->get() == expr_op_begin()->get() && I->getArg(0) == 1 &&
getNumElements() == 2;
}
case dwarf::DW_OP_LLVM_implicit_pointer:
case dwarf::DW_OP_LLVM_convert:
case dwarf::DW_OP_LLVM_tag_offset:
case dwarf::DW_OP_constu:
Expand Down
87 changes: 87 additions & 0 deletions llvm/test/DebugInfo/X86/LLVM_implicit_pointer.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
; Round trip test for DW_OP_LLVM_implicit_pointer metadata

; RUN: llvm-as < %s | llvm-dis | FileCheck %s

;---------------------------
;static const char *b = "opq";
;volatile int v;
;int main() {
; int var = 4;
; int *ptr1;
; int **ptr2;
;
; v++;
; ptr1 = &var;
; ptr2 = &ptr1;
; v++;
;
; return *ptr1 - 5 + **ptr2;
;}
;---------------------------

; ModuleID = 'LLVM_implicit_pointer.c'
source_filename = "LLVM_implicit_pointer.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"

@v = dso_local global i32 0, align 4, !dbg !0

; Function Attrs: nofree norecurse nounwind uwtable
define dso_local i32 @main() local_unnamed_addr !dbg !12 {
entry:
; CHECK: call void @llvm.dbg.value(metadata i32 4, metadata [[VAR:![0-9]+]], metadata !DIExpression())
call void @llvm.dbg.value(metadata i32 4, metadata !16, metadata !DIExpression()), !dbg !21
%0 = load volatile i32, i32* @v, align 4, !dbg !22, !tbaa !23
%inc = add nsw i32 %0, 1, !dbg !22
store volatile i32 %inc, i32* @v, align 4, !dbg !22, !tbaa !23

; CHECK: call void @llvm.dbg.value(metadata i32 4, metadata [[PTR1:![0-9]+]], metadata !DIExpression(DW_OP_LLVM_implicit_pointer))
call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !DIExpression(DW_OP_LLVM_implicit_pointer)), !dbg !21

; 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))
call void @llvm.dbg.value(metadata i32 4, metadata !19, metadata !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_implicit_pointer)), !dbg !21
%1 = load volatile i32, i32* @v, align 4, !dbg !27, !tbaa !23
%inc1 = add nsw i32 %1, 1, !dbg !27
store volatile i32 %inc1, i32* @v, align 4, !dbg !27, !tbaa !23
ret i32 3, !dbg !28
}

; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare void @llvm.dbg.value(metadata, metadata, metadata) #1

!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!8, !9, !10}
!llvm.ident = !{!11}

!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "v", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true)
!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)
!3 = !DIFile(filename: "LLVM_implicit_pointer.c", directory: "/dir", checksumkind: CSK_MD5, checksum: "218aaa8dc9f04b056b56d944d06383dd")
!4 = !{}
!5 = !{!0}
!6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!8 = !{i32 7, !"Dwarf Version", i32 5}
!9 = !{i32 2, !"Debug Info Version", i32 3}
!10 = !{i32 1, !"wchar_size", i32 4}
!11 = !{!"clang version 12.0.0"}
!12 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 3, type: !13, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !15)
!13 = !DISubroutineType(types: !14)
!14 = !{!7}
!15 = !{!16, !17, !19}
; CHECK: [[VAR]] = !DILocalVariable(name: "var"
!16 = !DILocalVariable(name: "var", scope: !12, file: !3, line: 4, type: !7)
; CHECK: [[PTR1]] = !DILocalVariable(name: "ptr1"
!17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5, type: !18)
!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
; CHECK: [[PTR2]] = !DILocalVariable(name: "ptr2"
!19 = !DILocalVariable(name: "ptr2", scope: !12, file: !3, line: 6, type: !20)
!20 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64)
!21 = !DILocation(line: 0, scope: !12)
!22 = !DILocation(line: 8, column: 4, scope: !12)
!23 = !{!24, !24, i64 0}
!24 = !{!"int", !25, i64 0}
!25 = !{!"omnipotent char", !26, i64 0}
!26 = !{!"Simple C/C++ TBAA"}
!27 = !DILocation(line: 11, column: 4, scope: !12)
!28 = !DILocation(line: 13, column: 3, scope: !12)

0 comments on commit 104a9f9

Please sign in to comment.