[llvm] [LangRef] Clarify definition of fragments and debug intrinsics (PR #82019)

Scott Linder via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 28 16:04:46 PDT 2024


https://github.com/slinder1 updated https://github.com/llvm/llvm-project/pull/82019

>From b19c3452d574b86e66f251bf5510d002de634238 Mon Sep 17 00:00:00 2001
From: Scott Linder <Scott.Linder at amd.com>
Date: Fri, 16 Feb 2024 13:16:15 -0500
Subject: [PATCH 1/2] [LangRef] Clarify definition of fragments and debug
 intrinsics

Try to give a more complete description of what we call a "fragment",
and define "spatial overlap" between variables and fragments to make
the details of when one intrinsic ends the effects of another more
direct and complete.

Also change the description of the debug intrinsics to the
pseudo-grammar style from LangRef.
---
 llvm/docs/SourceLevelDebugging.rst | 66 ++++++++++++++++++++++--------
 1 file changed, 49 insertions(+), 17 deletions(-)

diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst
index e1df7c355ee092..ccd455a59f5a5b 100644
--- a/llvm/docs/SourceLevelDebugging.rst
+++ b/llvm/docs/SourceLevelDebugging.rst
@@ -130,6 +130,40 @@ debugging information influences optimization passes then it will be reported
 as a failure.  See :doc:`TestingGuide` for more information on LLVM test
 infrastructure and how to run various tests.
 
+.. _variables_and_variable_fragments:
+
+Variables and Variable Fragments
+================================
+
+Source language variables (or just "variables") are represented by `local
+variable <LangRef.html#dilocalvariable>`_ and `global variable
+<LangRef.html#diglobalvariable>`_ metadata nodes.
+
+When variables are not allocated to contiguous memory or to a single LLVM value
+the metadata must record enough information to describe each "piece" or
+"fragment" of the source variable. Each fragment is a contiguous span of bits
+of the variable it is a part of.
+
+This is achieved by encoding fragment information at the end of the
+``DIExpression`` with the ``DW_OP_LLVM_fragment`` operation, whose operands are
+the bit offset of the fragment relative to the start of the variable, and the
+fragment size in bits.
+
+.. note::
+
+   The ``DW_OP_LLVM_fragment`` operation acts only to encode the fragment
+   information, and does not have an effect on the semantics of the expression.
+
+A debug intrinsic which refers to a ``DIExpression`` ending with a fragment
+operation provides information about the fragment of the variable it refers to,
+rather than the whole variable.
+
+An equivalence relation over the set of all variables and variable fragments
+called "spatially overlapping" is defined in order to describe when intrinsics
+terminate the effects of other intrinsics. A variable spatially overlaps with
+itself and all fragments of itself. Fragments additionally spatially overlap
+with other fragments sharing one common bit of the same variable.
+
 .. _format:
 
 Debugging information format
@@ -180,7 +214,9 @@ track source local variables through optimization and code generation.
 
 .. code-block:: llvm
 
-  void @llvm.dbg.declare(metadata, metadata, metadata)
+  void @llvm.dbg.declare(metadata <type> <value>,
+                         metadata <!DILocalVariable>,
+                         metadata <!DIExpression>)
 
 This intrinsic provides information about a local element (e.g., variable).
 The first argument is metadata holding the address of variable, typically a
@@ -221,7 +257,9 @@ agree on the memory location.
 
 .. code-block:: llvm
 
-  void @llvm.dbg.value(metadata, metadata, metadata)
+  void @llvm.dbg.value(metadata <<type> <value>|!DIArgList>,
+                       metadata <!DILocalVariable>,
+                       metadata <!DIExpression>)
 
 This intrinsic provides information when a user source variable is set to a new
 value.  The first argument is the new value (wrapped as metadata).  The second
@@ -243,12 +281,12 @@ the complex expression derives the direct value.
 
 .. code-block:: llvm
 
-  void @llvm.dbg.assign(Value *Value,
-                        DIExpression *ValueExpression,
-                        DILocalVariable *Variable,
-                        DIAssignID *ID,
-                        Value *Address,
-                        DIExpression *AddressExpression)
+  void @llvm.dbg.assign(metadata <<type> <value>|!DIArgList>,
+                        metadata <!DIExpression>,
+                        metadata <!DILocalVariable>,
+                        metadata <!DIAssignID>,
+                        metadata <type> <value>,
+                        metadata <!DIExpression>)
 
 This intrinsic marks the position in IR where a source assignment occurred. It
 encodes the value of the variable. It references the store, if any, that
@@ -259,13 +297,6 @@ argument is a ``DIAssignID`` used to reference a store. The fifth is the
 destination of the store (wrapped as metadata), and the sixth is a `complex
 expression <LangRef.html#diexpression>`_ that modifies it.
 
-The formal LLVM-IR signature is:
-
-.. code-block:: llvm
-
-  void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)
-
-
 See :doc:`AssignmentTracking` for more info.
 
 Object lifetimes and scoping
@@ -417,8 +448,9 @@ values through compilation, when objects are promoted to SSA values an
 ``llvm.dbg.value`` intrinsic is created for each assignment, recording the
 variable's new location. Compared with the ``llvm.dbg.declare`` intrinsic:
 
-* A dbg.value terminates the effect of any preceding dbg.values for (any
-  overlapping fragments of) the specified variable.
+* A dbg.value terminates the effect of any preceding dbg.values for any
+  spatially overlapping variables or fragments of the specified variable or
+  fragment.
 * The dbg.value's position in the IR defines where in the instruction stream
   the variable's value changes.
 * Operands can be constants, indicating the variable is assigned a

>From 41e6d3ea9e84fc7bc1421c6e656a1c33c6cc5956 Mon Sep 17 00:00:00 2001
From: Scott Linder <Scott.Linder at amd.com>
Date: Thu, 28 Mar 2024 18:57:56 -0400
Subject: [PATCH 2/2] Reword and refine definitions

I tried to include more kinds of objects under the umbrella term
"variable", but I'm not particularly happy with how circular it sounds.
Any more thoughts on better approaches are appreciated.

I also didn't understand initially that the current behavior in the most
common cases of spatial overlap between fragments is not necessarily
the intended semantics. Instead it is just a legal shortcut
that balances the complexity of handling partial overlap with arbitrary
expressions with the utility to the debugger for these rarer occurences.

None of this is terribly exact, but I still think having something
written about these aspects is better than having nothing, and might
save future contributors a bit of the learning curve. Let me know what
you think!
---
 llvm/docs/SourceLevelDebugging.rst | 66 ++++++++++++++++++------------
 1 file changed, 40 insertions(+), 26 deletions(-)

diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst
index ccd455a59f5a5b..6b4c19fd1cec7b 100644
--- a/llvm/docs/SourceLevelDebugging.rst
+++ b/llvm/docs/SourceLevelDebugging.rst
@@ -135,35 +135,37 @@ infrastructure and how to run various tests.
 Variables and Variable Fragments
 ================================
 
-Source language variables (or just "variables") are represented by `local
-variable <LangRef.html#dilocalvariable>`_ and `global variable
-<LangRef.html#diglobalvariable>`_ metadata nodes.
+In the context of this document a "variable" refers generally to any source
+language object which can have a value, including at least:
 
-When variables are not allocated to contiguous memory or to a single LLVM value
-the metadata must record enough information to describe each "piece" or
-"fragment" of the source variable. Each fragment is a contiguous span of bits
-of the variable it is a part of.
+- Variables
+- Constants
+- Formal parameters
 
-This is achieved by encoding fragment information at the end of the
-``DIExpression`` with the ``DW_OP_LLVM_fragment`` operation, whose operands are
-the bit offset of the fragment relative to the start of the variable, and the
-fragment size in bits.
+.. note::
+
+   There is no special provision for "true" constants in LLVM today, and
+   they are instead treated as local or global variables.
+
+A variable is represented by a `local variable <LangRef.html#dilocalvariable>`_
+or `global variable <LangRef.html#diglobalvariable>`_ metadata node.
+
+A variable fragment (or just "fragment") is a contiguous span of bits of a
+variable.
+
+A debug intrinsic which refers to a ``DIExpression`` ending with a
+``DW_OP_LLVM_fragment`` operation describes a fragment of the variable it
+refers to.
+
+The operands of the ``DW_OP_LLVM_fragment`` operation encode the bit offset of
+the fragment relative to the start of the variable, and the size of the
+fragment in bits, respectively.
 
 .. note::
 
    The ``DW_OP_LLVM_fragment`` operation acts only to encode the fragment
    information, and does not have an effect on the semantics of the expression.
 
-A debug intrinsic which refers to a ``DIExpression`` ending with a fragment
-operation provides information about the fragment of the variable it refers to,
-rather than the whole variable.
-
-An equivalence relation over the set of all variables and variable fragments
-called "spatially overlapping" is defined in order to describe when intrinsics
-terminate the effects of other intrinsics. A variable spatially overlaps with
-itself and all fragments of itself. Fragments additionally spatially overlap
-with other fragments sharing one common bit of the same variable.
-
 .. _format:
 
 Debugging information format
@@ -448,11 +450,23 @@ values through compilation, when objects are promoted to SSA values an
 ``llvm.dbg.value`` intrinsic is created for each assignment, recording the
 variable's new location. Compared with the ``llvm.dbg.declare`` intrinsic:
 
-* A dbg.value terminates the effect of any preceding dbg.values for any
-  spatially overlapping variables or fragments of the specified variable or
-  fragment.
-* The dbg.value's position in the IR defines where in the instruction stream
-  the variable's value changes.
+* A ``llvm.dbg.value`` intrinsic terminates the effects that any preceding
+  ``llvm.dbg.value`` intrinsics have on any common bits of a common variable.
+
+  .. note::
+
+    The current implementation generally terminates the effect of every
+    intrinsic in its entirety if any of its effects would be terminated, rather
+    than carrying forward the effect of previous intrinsics for non-overlapping
+    bits as it would be permitted to do by this definition. This is allowed
+    just as dropping any debug information at any point in the compilation is
+    allowed.
+
+    One exception to this is :doc:`AssignmentTracking` where certain
+    memory-based locations are carried forward partially in some situations.
+
+* The ``llvm.dbg.value``'s position in the IR defines where in the instruction
+  stream the variable's value changes.
 * Operands can be constants, indicating the variable is assigned a
   constant value.
 



More information about the llvm-commits mailing list