Skip to content

[DLCov 1/5] Add CMake option to enable enhanced line number coverage tracking #107278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 8, 2024

Conversation

SLTozer
Copy link
Contributor

@SLTozer SLTozer commented Sep 4, 2024

This is part of a series of patches that tries to improve DILocation bug detection in Debugify; see below for more details. This first patch adds the necessary CMake flag to LLVM and a variable defined by that flag to LLVM's config header, allowing the next patch to track information without affecting normal builds.


This series of patches adds a "DebugLoc coverage tracking" feature, that inserts conditionally-compiled tracking information into DebugLocs (and by extension, to Instructions), which is used by Debugify to provide more accurate and detailed coverage reports. When enabled, this features tracks whether and why we have intentionally dropped a DebugLoc, allowing Debugify to ignore false positives. An optional additional feature allows also storing a stack trace of the point where a DebugLoc was unintentionally dropped/not generated, which is used to make fixing detected errors significantly easier. The goal of these features is to provide useful tools for developers to fix existing DebugLoc errors and allow reliable detection of regressions by either manual inspection or an automated script.

Next: #107279

@SLTozer SLTozer self-assigned this Sep 4, 2024
@llvmbot llvmbot added the cmake Build system in general and CMake in particular label Sep 4, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 4, 2024

@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-debuginfo

Author: Stephen Tozer (SLTozer)

Changes

This is part of a series of patches that tries to improve DILocation bug detection in Debugify; see below for more details. This first patch adds the necessary CMake flag to LLVM and a variable defined by that flag to LLVM's config header, allowing the next patch to track information without affecting normal builds.


This series of patches adds a "DebugLoc coverage tracking" feature, that inserts conditionally-compiled tracking information into DebugLocs (and by extension, to Instructions), which is used by Debugify to provide more accurate and detailed coverage reports. When enabled, this features tracks whether and why we have intentionally dropped a DebugLoc, allowing Debugify to ignore false positives. An optional additional feature allows also storing a stack trace of the point where a DebugLoc was unintentionally dropped/not generated, which is used to make fixing detected errors significantly easier. The goal of these features is to provide useful tools for developers to fix existing DebugLoc errors and allow reliable detection of regressions by either manual inspection or an automated script.


Full diff: https://github.com/llvm/llvm-project/pull/107278.diff

4 Files Affected:

  • (modified) llvm/CMakeLists.txt (+4)
  • (modified) llvm/cmake/modules/HandleLLVMOptions.cmake (+12)
  • (modified) llvm/docs/CMake.rst (+11)
  • (modified) llvm/include/llvm/Config/config.h.cmake (+4)
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 12618966c4adfd..3e2e90f5adad2e 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -524,6 +524,10 @@ endif()
 
 option(LLVM_ENABLE_CRASH_DUMPS "Turn on memory dumps on crashes. Currently only implemented on Windows." OFF)
 
+set(LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING "DISABLED" CACHE STRING
+  "Enhance debugify's line number coverage tracking; enabling this is abi-breaking. Can be DISABLED, COVERAGE, or COVERAGE_AND_ORIGIN.")
+set_property(CACHE LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING PROPERTY STRINGS DISABLED COVERAGE COVERAGE_AND_ORIGIN)
+
 set(WINDOWS_PREFER_FORWARD_SLASH_DEFAULT OFF)
 if (MINGW)
   # Cygwin doesn't identify itself as Windows, and thus gets path::Style::posix
diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake
index 5ca580fbb59c59..a4b11c149da9de 100644
--- a/llvm/cmake/modules/HandleLLVMOptions.cmake
+++ b/llvm/cmake/modules/HandleLLVMOptions.cmake
@@ -196,6 +196,18 @@ else()
   message(FATAL_ERROR "Unknown value for LLVM_ABI_BREAKING_CHECKS: \"${LLVM_ABI_BREAKING_CHECKS}\"!")
 endif()
 
+string(TOUPPER "${LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING}" uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING)
+
+if( uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING STREQUAL "COVERAGE" )
+  set( ENABLE_DEBUGLOC_COVERAGE_TRACKING 1 )
+elseif( uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING STREQUAL "COVERAGE_AND_ORIGIN" )
+  message(FATAL_ERROR "\"COVERAGE_AND_ORIGIN\" setting for LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING currently unimplemented.")
+elseif( uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING STREQUAL "DISABLED" OR NOT DEFINED LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING )
+  # The DISABLED setting is default and requires no additional defines.
+else()
+  message(FATAL_ERROR "Unknown value for LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING: \"${LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING}\"!")
+endif()
+
 if( LLVM_REVERSE_ITERATION )
   set( LLVM_ENABLE_REVERSE_ITERATION 1 )
 endif()
diff --git a/llvm/docs/CMake.rst b/llvm/docs/CMake.rst
index 2a80813999ea1e..304e22759770d9 100644
--- a/llvm/docs/CMake.rst
+++ b/llvm/docs/CMake.rst
@@ -475,6 +475,17 @@ enabled sub-projects. Nearly all of these variable names begin with
 **LLVM_ENABLE_BINDINGS**:BOOL
   If disabled, do not try to build the OCaml bindings.
 
+**LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING**:STRING
+  Enhances Debugify's ability to detect line number errors by storing extra
+  information inside Instructions, removing false positives from Debugify's
+  results at the cost of performance. Allowed values are `DISABLED` (default),
+  `COVERAGE`, and `COVERAGE_AND_ORIGIN`. `COVERAGE` tracks whether and why a
+  line number was intentionally dropped or not generated for an instruction,
+  allowing Debugify to avoid reporting these as errors. `COVERAGE_AND_ORIGIN`
+  additionally stores a stacktrace of the point where each DebugLoc is
+  unintentionally dropped, allowing for much easier bug triaging at the cost of
+  a ~10x performance slowdown.
+
 **LLVM_ENABLE_DIA_SDK**:BOOL
   Enable building with MSVC DIA SDK for PDB debugging support. Available
   only with MSVC. Defaults to ON.
diff --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake
index ff30741c8f360a..388ce1e8f74e3e 100644
--- a/llvm/include/llvm/Config/config.h.cmake
+++ b/llvm/include/llvm/Config/config.h.cmake
@@ -19,6 +19,10 @@
 /* Define to 1 to enable crash memory dumps, and to 0 otherwise. */
 #cmakedefine01 LLVM_ENABLE_CRASH_DUMPS
 
+/* Define to 1 to enable expensive checks for debug location coverage checking,
+   and to 0 otherwise. */
+#cmakedefine01 ENABLE_DEBUGLOC_COVERAGE_TRACKING
+
 /* Define to 1 to prefer forward slashes on Windows, and to 0 prefer
    backslashes. */
 #cmakedefine01 LLVM_WINDOWS_PREFER_FORWARD_SLASH

@djtodoro
Copy link
Collaborator

@SLTozer Thanks a lot for this! Very interesting.

I will review the implementation, but I am curious whether we only modified the metadata/DebugLoc. To be more precise, my main concern is memory usage increase, and whether we have affected llvm::Instruction in any way other than metadata.

@SLTozer
Copy link
Contributor Author

SLTozer commented Sep 11, 2024

I will review the implementation, but I am curious whether we only modified the metadata/DebugLoc. To be more precise, my main concern is memory usage increase, and whether we have affected llvm::Instruction in any way other than metadata.

There will be increased memory usage - more exactly, we increase the size of DebugLoc, not !DILocation, which means the extra storage is part of the Instruction class. The intent here is that we conditionally compile this extra information in for a specific build configuration designed to test the compiler itself with debugify; in ordinary builds, including debug builds, the extra information is not stored, so run time and memory usage should be unaffected.

Copy link
Member

@jryans jryans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part looks good so far, just a few editorial notes. 😄

@@ -0,0 +1,69 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
;; Tests that we do not always overwrite
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, did you mean to add this test here...? It seems unrelated to this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not, my fault for git adding a folder without checking my tree is clean...

@SLTozer
Copy link
Contributor Author

SLTozer commented Oct 1, 2024

@jryans Does this part look good to you now?

Copy link
Member

@jryans jryans left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part looks good to me. Thanks for working on this! 😄

@SLTozer SLTozer force-pushed the dl-coverage-1-cmake branch from 2928f48 to 7380c0d Compare October 4, 2024 19:48
@SLTozer SLTozer merged commit 84088d3 into llvm:main Oct 8, 2024
10 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Oct 9, 2024

LLVM Buildbot has detected a new failure on builder lld-x86_64-win running on as-worker-93 while building llvm at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/146/builds/1339

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM-Unit :: Support/./SupportTests.exe/35/87' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe-LLVM-Unit-15828-35-87.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=87 GTEST_SHARD_INDEX=35 C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe
--

Script:
--
C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe --gtest_filter=ProgramEnvTest.CreateProcessLongPath
--
C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(160): error: Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(163): error: fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied



C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:160
Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:163
fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied




********************


chapuni added a commit that referenced this pull request Jun 14, 2025
It has been introduced in #107278 but it was passing
"DISABLED" of LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING to cmakedefine01.

cmakadefine01 treats non-false-like strings as 1.
"DISABLED" is replaced with 1.
Copy link
Contributor

@chapuni chapuni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like ENABLE_DEBUGLOC_COVERAGE_TRACKING in llvm-config.h is always 1. Fixed in 1bc0b08.

string(TOUPPER "${LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING}" uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING)

if( uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING STREQUAL "COVERAGE" )
set( ENABLE_DEBUGLOC_COVERAGE_TRACKING 1 )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it is not a good practice to override a cached variable with a non-cached variable that has different semantics.

if( uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING STREQUAL "COVERAGE" )
set( ENABLE_DEBUGLOC_COVERAGE_TRACKING 1 )
elseif( uppercase_LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING STREQUAL "DISABLED" OR NOT DEFINED LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING )
# The DISABLED setting is default and requires no additional defines.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It leaves LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING as "DISABLED".

@@ -19,6 +19,10 @@
/* Define to 1 to enable crash memory dumps, and to 0 otherwise. */
#cmakedefine01 LLVM_ENABLE_CRASH_DUMPS

/* Define to 1 to enable expensive checks for debug location coverage checking,
and to 0 otherwise. */
#cmakedefine01 ENABLE_DEBUGLOC_COVERAGE_TRACKING
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#cmakedefine01 handles "DISABLED" as 1 since it is not false-like string.

tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
It has been introduced in llvm#107278 but it was passing
"DISABLED" of LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING to cmakedefine01.

cmakadefine01 treats non-false-like strings as 1.
"DISABLED" is replaced with 1.
@jmorse
Copy link
Member

jmorse commented Jun 16, 2025

/me squints -- it looks like these issues were latent and then we exposed them with #143590. Thanks @chapuni for clearing this up!

vzakhari added a commit that referenced this pull request Jun 16, 2025
Change in #107278 modified the CMake CACHE variable with values
that are not supported for it as documented. This patch renames the
derived vars so that they do not conflict with the CACHE variable.
fschlimb pushed a commit to fschlimb/llvm-project that referenced this pull request Jun 18, 2025
…144391)

Change in llvm#107278 modified the CMake CACHE variable with values
that are not supported for it as documented. This patch renames the
derived vars so that they do not conflict with the CACHE variable.
akuhlens pushed a commit to akuhlens/llvm-project that referenced this pull request Jun 24, 2025
It has been introduced in llvm#107278 but it was passing
"DISABLED" of LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING to cmakedefine01.

cmakadefine01 treats non-false-like strings as 1.
"DISABLED" is replaced with 1.
akuhlens pushed a commit to akuhlens/llvm-project that referenced this pull request Jun 24, 2025
…144391)

Change in llvm#107278 modified the CMake CACHE variable with values
that are not supported for it as documented. This patch renames the
derived vars so that they do not conflict with the CACHE variable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cmake Build system in general and CMake in particular debuginfo llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants