Skip to content

Conversation

@laxmansole
Copy link
Contributor

@laxmansole laxmansole commented Jul 29, 2025

Previously, sign-extending a 1-bit boolean operand in #DBG_VALUE would convert true to -1 (i.e., 0xffffffffffffffff). However, DWARF treats booleans as unsigned values, so this resulted in the attribute DW_AT_const_value(0xffffffffffffffff) being emitted. As a result, the debugger would display the value as 255 instead of true.

This change modifies the behavior to use zero-extension for 1-bit values instead, ensuring that true is represented as 1. Consequently, the DWARF attribute emitted is now DW_AT_const_value(1), which allows the debugger to correctly display the boolean as true.

@github-actions
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented Jul 29, 2025

@llvm/pr-subscribers-llvm-selectiondag
@llvm/pr-subscribers-llvm-globalisel

@llvm/pr-subscribers-backend-nvptx

Author: Laxman (laxmansole)

Changes

For boolean values, -1 is assigned to indicate True and 0 to indicate False.
However, during the DWARF generation, booleans are treated as unsigned variables, and the debug_loc expression, like DW_OP_lit0; DW_OP_not or the attribute DW_AT_const_value(0xffffffffffffffff) is emitted for the True value.

This leads to the debugger printing 255 instead of "true" for boolean variables.

This change emits DW_OP_lit1 instead of DW_OP_lot0;DW_OP_not and the attribute DW_AT_const_value(1) instead of DW_AT_const_value(0xffffffffffffffff).


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

6 Files Affected:

  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (+32-2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (+4-2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (+9)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h (+3)
  • (added) llvm/test/DebugInfo/NVPTX/debug-bool-const-location.ll (+51)
  • (added) llvm/test/DebugInfo/NVPTX/debug-bool-const-value.ll (+37)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 5577a7d298177..f1be286c0a746 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -247,6 +247,13 @@ void DwarfCompileUnit::addLocationAttribute(
   DIELoc *Loc = nullptr;
   std::optional<unsigned> NVPTXAddressSpace;
   std::unique_ptr<DIEDwarfExpression> DwarfExpr;
+
+  // Check if this variable is of boolean type
+  bool isBoolean = false;
+  if (GV && GV->getType())
+    if (auto *BasicType = dyn_cast<DIBasicType>(GV->getType()))
+      isBoolean = BasicType->getEncoding() == dwarf::DW_ATE_boolean;
+
   for (const auto &GE : GlobalExprs) {
     const GlobalVariable *Global = GE.Var;
     const DIExpression *Expr = GE.Expr;
@@ -257,11 +264,17 @@ void DwarfCompileUnit::addLocationAttribute(
     // DW_AT_const_value(X).
     if (GlobalExprs.size() == 1 && Expr && Expr->isConstant()) {
       addToAccelTable = true;
+
+      // Determine the value to use, normalizing booleans to 0 or 1
+      int64_t valueToUse = Expr->getElement(1);
+      if (isBoolean)
+        valueToUse = valueToUse ? 1 : 0;
+
       addConstantValue(
           *VariableDIE,
           DIExpression::SignedOrUnsignedConstant::UnsignedConstant ==
               *Expr->isConstant(),
-          Expr->getElement(1));
+          valueToUse);
       break;
     }
 
@@ -820,6 +833,22 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes(
   }
   if (!DVal->isVariadic()) {
     const DbgValueLocEntry *Entry = DVal->getLocEntries().begin();
+
+    // Helper function to handle boolean constant values with type safety
+    auto addConstantValueWithBooleanNormalization =
+        [&](DIE &VariableDie, uint64_t intValue, const DIType *Type) {
+          if (auto *BasicType = dyn_cast_or_null<DIBasicType>(Type)) {
+            if (BasicType->getEncoding() == dwarf::DW_ATE_boolean) {
+              // Normalize boolean values: any non-zero becomes 1, zero stays 0
+              uint64_t normalizedBoolValue = (intValue) ? 1 : 0;
+              addConstantValue(VariableDie, normalizedBoolValue, Type);
+              return;
+            }
+          }
+          // For non-boolean types, use the original constant value
+          addConstantValue(VariableDie, intValue, Type);
+        };
+
     if (Entry->isLocation()) {
       addVariableAddress(DV, VariableDie, Entry->getLoc());
     } else if (Entry->isInt()) {
@@ -836,7 +865,8 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes(
           addUInt(VariableDie, dwarf::DW_AT_LLVM_tag_offset,
                   dwarf::DW_FORM_data1, *DwarfExpr.TagOffset);
       } else
-        addConstantValue(VariableDie, Entry->getInt(), DV.getType());
+        addConstantValueWithBooleanNormalization(VariableDie, Entry->getInt(),
+                                                 DV.getType());
     } else if (Entry->isConstantFP()) {
       addConstantFPValue(VariableDie, Entry->getConstantFP());
     } else if (Entry->isConstantInt()) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 71888332a6620..6d4c9c05e3aba 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -3100,8 +3100,10 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
                             &AP](const DbgValueLocEntry &Entry,
                                  DIExpressionCursor &Cursor) -> bool {
     if (Entry.isInt()) {
-      if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
-                 BT->getEncoding() == dwarf::DW_ATE_signed_char))
+      if (BT && (BT->getEncoding() == dwarf::DW_ATE_boolean))
+        DwarfExpr.addBooleanConstant(Entry.getInt());
+      else if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
+                      BT->getEncoding() == dwarf::DW_ATE_signed_char))
         DwarfExpr.addSignedConstant(Entry.getInt());
       else
         DwarfExpr.addUnsignedConstant(Entry.getInt());
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index e684054ffa3e4..8a30714db2fdf 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -194,6 +194,15 @@ void DwarfExpression::addStackValue() {
     emitOp(dwarf::DW_OP_stack_value);
 }
 
+void DwarfExpression::addBooleanConstant(int64_t Value) {
+  assert(isImplicitLocation() || isUnknownLocation());
+  LocationKind = Implicit;
+  if (Value == 0)
+    emitOp(dwarf::DW_OP_lit0);
+  else
+    emitOp(dwarf::DW_OP_lit1);
+}
+
 void DwarfExpression::addSignedConstant(int64_t Value) {
   assert(isImplicitLocation() || isUnknownLocation());
   LocationKind = Implicit;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index 06809ab263875..700e0ec5813ee 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -229,6 +229,9 @@ class DwarfExpression {
   /// This needs to be called last to commit any pending changes.
   void finalize();
 
+  /// Emit a boolean constant.
+  void addBooleanConstant(int64_t Value);
+
   /// Emit a signed constant.
   void addSignedConstant(int64_t Value);
 
diff --git a/llvm/test/DebugInfo/NVPTX/debug-bool-const-location.ll b/llvm/test/DebugInfo/NVPTX/debug-bool-const-location.ll
new file mode 100644
index 0000000000000..f073d51e7ef99
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/debug-bool-const-location.ll
@@ -0,0 +1,51 @@
+; RUN: llc < %s -asm-verbose -mattr=+ptx76  -O0| FileCheck %s
+; RUN: %if ptxas %{ llc < %s -asm-verbose -mattr=+ptx76  -O0 | %ptxas-verify %}
+
+target triple = "nvptx64-nvidia-cuda"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"
+
+; CHECK: {{.*}}section {{.*}}debug_loc
+; CHECK: .b8 48{{.*}} DW_OP_lit0
+; CHECK: .b8 49{{.*}} DW_OP_lit1
+; CHECK: .b8 144{{.*}} DW_OP_regx
+
+define void @foo(i8 %"arg.arg") !dbg !5
+{
+entry:
+  %".4" = alloca i1
+  %".5" = icmp eq i8 %"arg.arg", 0
+  %arg = alloca i1
+  br i1 %".5", label %"entry.if", label %"entry.else"
+entry.if:
+  store i1 false, i1* %arg
+  call void @"llvm.dbg.value"(metadata i1 false , metadata !9, metadata !10), !dbg !6
+  br label %"entry.endif"
+entry.else:
+  store i1 true, i1* %arg
+  call void @"llvm.dbg.value"(metadata i1 true , metadata !9, metadata !10), !dbg !7
+  br label %"entry.endif"
+entry.endif:
+  %".11" = load i1, i1* %arg
+  store i1 %".11", i1* %".4", !dbg !8
+  call void @"llvm.dbg.value"(metadata i1 %".11" , metadata !9, metadata !10), !dbg !8
+  ret void, !dbg !8
+}
+
+declare void @"llvm.dbg.value"(metadata %".1", metadata %".2", metadata %".3")
+
+!llvm.dbg.cu = !{ !2 }
+!llvm.module.flags = !{ !11, !12 }
+!nvvm.annotations = !{}
+
+!1 = !DIFile(directory: "/source/dir", filename: "test.cu")
+!2 = distinct !DICompileUnit(emissionKind: FullDebug, file: !1, isOptimized: false, language: DW_LANG_C_plus_plus, runtimeVersion: 0)
+!3 = !DIBasicType(encoding: DW_ATE_boolean, name: "bool", size: 8)
+!4 = !DISubroutineType(types: !{null})
+!5 = distinct !DISubprogram(file: !1, isDefinition: true, isLocal: false, isOptimized: false, line: 5, linkageName: "foo", name: "foo", scope: !1, scopeLine: 5, type: !4, unit: !2)
+!6 = !DILocation(column: 1, line: 5, scope: !5)
+!7 = !DILocation(column: 1, line: 7, scope: !5)
+!8 = !DILocation(column: 1, line: 8, scope: !5)
+!9 = !DILocalVariable(arg: 0, file: !1, line: 5, name: "arg", scope: !5, type: !3)
+!10 = !DIExpression()
+!11 = !{ i32 2, !"Dwarf Version", i32 4 }
+!12 = !{ i32 2, !"Debug Info Version", i32 3 }
\ No newline at end of file
diff --git a/llvm/test/DebugInfo/NVPTX/debug-bool-const-value.ll b/llvm/test/DebugInfo/NVPTX/debug-bool-const-value.ll
new file mode 100644
index 0000000000000..002a7a801c746
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/debug-bool-const-value.ll
@@ -0,0 +1,37 @@
+; RUN: llc < %s -asm-verbose -mattr=+ptx76 | FileCheck %s
+; RUN: %if ptxas %{ llc < %s -asm-verbose -mattr=+ptx76 | %ptxas-verify %}
+
+target triple = "nvptx64-nvidia-cuda"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"
+
+; CHECK: {{.*}}section {{.*}}debug_info
+; CHECK: {{.*}}DW_TAG_variable
+; CHECK-NEXT: {{.*}} DW_AT_address_class
+; CHECK-NEXT: .b8 1{{.*}} DW_AT_const_value
+; CHECK-NEXT: {{.*}} DW_AT_name
+
+define void @test() !dbg !5
+{
+entry:
+  %arg = alloca i1
+  store i1 true, i1* %arg, !dbg !6
+  call void @"llvm.dbg.value"(metadata i1 true, metadata !7, metadata !8), !dbg !6
+  ret void, !dbg !6
+}
+
+declare void @"llvm.dbg.value"(metadata %".1", metadata %".2", metadata %".3")
+
+!llvm.dbg.cu = !{ !2 }
+!llvm.module.flags = !{ !9, !10 }
+!nvvm.annotations = !{}
+
+!1 = !DIFile(directory: "/source/dir", filename: "test.cu")
+!2 = distinct !DICompileUnit(emissionKind: FullDebug, file: !1, isOptimized: false, language: DW_LANG_C_plus_plus, runtimeVersion: 0)
+!3 = !DIBasicType(encoding: DW_ATE_boolean, name: "bool", size: 8)
+!4 = !DISubroutineType(types: !{null})
+!5 = distinct !DISubprogram(file: !1, isDefinition: true, isLocal: false, isOptimized: false, line: 5, linkageName: "test", name: "test", scope: !1, scopeLine: 5, type: !4, unit: !2)
+!6 = !DILocation(column: 1, line: 5, scope: !5)
+!7 = !DILocalVariable(arg: 0, file: !1, line: 5, name: "arg", scope: !5, type: !3)
+!8 = !DIExpression()
+!9 = !{ i32 2, !"Dwarf Version", i32 4 }
+!10 = !{ i32 2, !"Debug Info Version", i32 3 }
\ No newline at end of file

@llvmbot
Copy link
Member

llvmbot commented Jul 29, 2025

@llvm/pr-subscribers-debuginfo

Author: Laxman (laxmansole)

Changes

For boolean values, -1 is assigned to indicate True and 0 to indicate False.
However, during the DWARF generation, booleans are treated as unsigned variables, and the debug_loc expression, like DW_OP_lit0; DW_OP_not or the attribute DW_AT_const_value(0xffffffffffffffff) is emitted for the True value.

This leads to the debugger printing 255 instead of "true" for boolean variables.

This change emits DW_OP_lit1 instead of DW_OP_lot0;DW_OP_not and the attribute DW_AT_const_value(1) instead of DW_AT_const_value(0xffffffffffffffff).


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

6 Files Affected:

  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (+32-2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (+4-2)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (+9)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h (+3)
  • (added) llvm/test/DebugInfo/NVPTX/debug-bool-const-location.ll (+51)
  • (added) llvm/test/DebugInfo/NVPTX/debug-bool-const-value.ll (+37)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 5577a7d298177..f1be286c0a746 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -247,6 +247,13 @@ void DwarfCompileUnit::addLocationAttribute(
   DIELoc *Loc = nullptr;
   std::optional<unsigned> NVPTXAddressSpace;
   std::unique_ptr<DIEDwarfExpression> DwarfExpr;
+
+  // Check if this variable is of boolean type
+  bool isBoolean = false;
+  if (GV && GV->getType())
+    if (auto *BasicType = dyn_cast<DIBasicType>(GV->getType()))
+      isBoolean = BasicType->getEncoding() == dwarf::DW_ATE_boolean;
+
   for (const auto &GE : GlobalExprs) {
     const GlobalVariable *Global = GE.Var;
     const DIExpression *Expr = GE.Expr;
@@ -257,11 +264,17 @@ void DwarfCompileUnit::addLocationAttribute(
     // DW_AT_const_value(X).
     if (GlobalExprs.size() == 1 && Expr && Expr->isConstant()) {
       addToAccelTable = true;
+
+      // Determine the value to use, normalizing booleans to 0 or 1
+      int64_t valueToUse = Expr->getElement(1);
+      if (isBoolean)
+        valueToUse = valueToUse ? 1 : 0;
+
       addConstantValue(
           *VariableDIE,
           DIExpression::SignedOrUnsignedConstant::UnsignedConstant ==
               *Expr->isConstant(),
-          Expr->getElement(1));
+          valueToUse);
       break;
     }
 
@@ -820,6 +833,22 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes(
   }
   if (!DVal->isVariadic()) {
     const DbgValueLocEntry *Entry = DVal->getLocEntries().begin();
+
+    // Helper function to handle boolean constant values with type safety
+    auto addConstantValueWithBooleanNormalization =
+        [&](DIE &VariableDie, uint64_t intValue, const DIType *Type) {
+          if (auto *BasicType = dyn_cast_or_null<DIBasicType>(Type)) {
+            if (BasicType->getEncoding() == dwarf::DW_ATE_boolean) {
+              // Normalize boolean values: any non-zero becomes 1, zero stays 0
+              uint64_t normalizedBoolValue = (intValue) ? 1 : 0;
+              addConstantValue(VariableDie, normalizedBoolValue, Type);
+              return;
+            }
+          }
+          // For non-boolean types, use the original constant value
+          addConstantValue(VariableDie, intValue, Type);
+        };
+
     if (Entry->isLocation()) {
       addVariableAddress(DV, VariableDie, Entry->getLoc());
     } else if (Entry->isInt()) {
@@ -836,7 +865,8 @@ void DwarfCompileUnit::applyConcreteDbgVariableAttributes(
           addUInt(VariableDie, dwarf::DW_AT_LLVM_tag_offset,
                   dwarf::DW_FORM_data1, *DwarfExpr.TagOffset);
       } else
-        addConstantValue(VariableDie, Entry->getInt(), DV.getType());
+        addConstantValueWithBooleanNormalization(VariableDie, Entry->getInt(),
+                                                 DV.getType());
     } else if (Entry->isConstantFP()) {
       addConstantFPValue(VariableDie, Entry->getConstantFP());
     } else if (Entry->isConstantInt()) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 71888332a6620..6d4c9c05e3aba 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -3100,8 +3100,10 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
                             &AP](const DbgValueLocEntry &Entry,
                                  DIExpressionCursor &Cursor) -> bool {
     if (Entry.isInt()) {
-      if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
-                 BT->getEncoding() == dwarf::DW_ATE_signed_char))
+      if (BT && (BT->getEncoding() == dwarf::DW_ATE_boolean))
+        DwarfExpr.addBooleanConstant(Entry.getInt());
+      else if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
+                      BT->getEncoding() == dwarf::DW_ATE_signed_char))
         DwarfExpr.addSignedConstant(Entry.getInt());
       else
         DwarfExpr.addUnsignedConstant(Entry.getInt());
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index e684054ffa3e4..8a30714db2fdf 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -194,6 +194,15 @@ void DwarfExpression::addStackValue() {
     emitOp(dwarf::DW_OP_stack_value);
 }
 
+void DwarfExpression::addBooleanConstant(int64_t Value) {
+  assert(isImplicitLocation() || isUnknownLocation());
+  LocationKind = Implicit;
+  if (Value == 0)
+    emitOp(dwarf::DW_OP_lit0);
+  else
+    emitOp(dwarf::DW_OP_lit1);
+}
+
 void DwarfExpression::addSignedConstant(int64_t Value) {
   assert(isImplicitLocation() || isUnknownLocation());
   LocationKind = Implicit;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index 06809ab263875..700e0ec5813ee 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -229,6 +229,9 @@ class DwarfExpression {
   /// This needs to be called last to commit any pending changes.
   void finalize();
 
+  /// Emit a boolean constant.
+  void addBooleanConstant(int64_t Value);
+
   /// Emit a signed constant.
   void addSignedConstant(int64_t Value);
 
diff --git a/llvm/test/DebugInfo/NVPTX/debug-bool-const-location.ll b/llvm/test/DebugInfo/NVPTX/debug-bool-const-location.ll
new file mode 100644
index 0000000000000..f073d51e7ef99
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/debug-bool-const-location.ll
@@ -0,0 +1,51 @@
+; RUN: llc < %s -asm-verbose -mattr=+ptx76  -O0| FileCheck %s
+; RUN: %if ptxas %{ llc < %s -asm-verbose -mattr=+ptx76  -O0 | %ptxas-verify %}
+
+target triple = "nvptx64-nvidia-cuda"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"
+
+; CHECK: {{.*}}section {{.*}}debug_loc
+; CHECK: .b8 48{{.*}} DW_OP_lit0
+; CHECK: .b8 49{{.*}} DW_OP_lit1
+; CHECK: .b8 144{{.*}} DW_OP_regx
+
+define void @foo(i8 %"arg.arg") !dbg !5
+{
+entry:
+  %".4" = alloca i1
+  %".5" = icmp eq i8 %"arg.arg", 0
+  %arg = alloca i1
+  br i1 %".5", label %"entry.if", label %"entry.else"
+entry.if:
+  store i1 false, i1* %arg
+  call void @"llvm.dbg.value"(metadata i1 false , metadata !9, metadata !10), !dbg !6
+  br label %"entry.endif"
+entry.else:
+  store i1 true, i1* %arg
+  call void @"llvm.dbg.value"(metadata i1 true , metadata !9, metadata !10), !dbg !7
+  br label %"entry.endif"
+entry.endif:
+  %".11" = load i1, i1* %arg
+  store i1 %".11", i1* %".4", !dbg !8
+  call void @"llvm.dbg.value"(metadata i1 %".11" , metadata !9, metadata !10), !dbg !8
+  ret void, !dbg !8
+}
+
+declare void @"llvm.dbg.value"(metadata %".1", metadata %".2", metadata %".3")
+
+!llvm.dbg.cu = !{ !2 }
+!llvm.module.flags = !{ !11, !12 }
+!nvvm.annotations = !{}
+
+!1 = !DIFile(directory: "/source/dir", filename: "test.cu")
+!2 = distinct !DICompileUnit(emissionKind: FullDebug, file: !1, isOptimized: false, language: DW_LANG_C_plus_plus, runtimeVersion: 0)
+!3 = !DIBasicType(encoding: DW_ATE_boolean, name: "bool", size: 8)
+!4 = !DISubroutineType(types: !{null})
+!5 = distinct !DISubprogram(file: !1, isDefinition: true, isLocal: false, isOptimized: false, line: 5, linkageName: "foo", name: "foo", scope: !1, scopeLine: 5, type: !4, unit: !2)
+!6 = !DILocation(column: 1, line: 5, scope: !5)
+!7 = !DILocation(column: 1, line: 7, scope: !5)
+!8 = !DILocation(column: 1, line: 8, scope: !5)
+!9 = !DILocalVariable(arg: 0, file: !1, line: 5, name: "arg", scope: !5, type: !3)
+!10 = !DIExpression()
+!11 = !{ i32 2, !"Dwarf Version", i32 4 }
+!12 = !{ i32 2, !"Debug Info Version", i32 3 }
\ No newline at end of file
diff --git a/llvm/test/DebugInfo/NVPTX/debug-bool-const-value.ll b/llvm/test/DebugInfo/NVPTX/debug-bool-const-value.ll
new file mode 100644
index 0000000000000..002a7a801c746
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/debug-bool-const-value.ll
@@ -0,0 +1,37 @@
+; RUN: llc < %s -asm-verbose -mattr=+ptx76 | FileCheck %s
+; RUN: %if ptxas %{ llc < %s -asm-verbose -mattr=+ptx76 | %ptxas-verify %}
+
+target triple = "nvptx64-nvidia-cuda"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"
+
+; CHECK: {{.*}}section {{.*}}debug_info
+; CHECK: {{.*}}DW_TAG_variable
+; CHECK-NEXT: {{.*}} DW_AT_address_class
+; CHECK-NEXT: .b8 1{{.*}} DW_AT_const_value
+; CHECK-NEXT: {{.*}} DW_AT_name
+
+define void @test() !dbg !5
+{
+entry:
+  %arg = alloca i1
+  store i1 true, i1* %arg, !dbg !6
+  call void @"llvm.dbg.value"(metadata i1 true, metadata !7, metadata !8), !dbg !6
+  ret void, !dbg !6
+}
+
+declare void @"llvm.dbg.value"(metadata %".1", metadata %".2", metadata %".3")
+
+!llvm.dbg.cu = !{ !2 }
+!llvm.module.flags = !{ !9, !10 }
+!nvvm.annotations = !{}
+
+!1 = !DIFile(directory: "/source/dir", filename: "test.cu")
+!2 = distinct !DICompileUnit(emissionKind: FullDebug, file: !1, isOptimized: false, language: DW_LANG_C_plus_plus, runtimeVersion: 0)
+!3 = !DIBasicType(encoding: DW_ATE_boolean, name: "bool", size: 8)
+!4 = !DISubroutineType(types: !{null})
+!5 = distinct !DISubprogram(file: !1, isDefinition: true, isLocal: false, isOptimized: false, line: 5, linkageName: "test", name: "test", scope: !1, scopeLine: 5, type: !4, unit: !2)
+!6 = !DILocation(column: 1, line: 5, scope: !5)
+!7 = !DILocalVariable(arg: 0, file: !1, line: 5, name: "arg", scope: !5, type: !3)
+!8 = !DIExpression()
+!9 = !{ i32 2, !"Dwarf Version", i32 4 }
+!10 = !{ i32 2, !"Debug Info Version", i32 3 }
\ No newline at end of file

@laxmansole
Copy link
Contributor Author

CC: @enferex

@laxmansole
Copy link
Contributor Author

CC: @jmorse

@Michael137 Michael137 requested a review from dwblaikie August 6, 2025 08:46
@Michael137
Copy link
Member

Michael137 commented Aug 6, 2025

This leads to the debugger printing 255 instead of "true" for boolean variables.

Do you have an example/Github issue of this? Shouldn't the debugger know how to present booleans in a particular language, regardless of which non-zero value was used to indicate truthness?

@dwblaikie
Copy link
Collaborator

This leads to the debugger printing 255 instead of "true" for boolean variables.

Do you have an example/Github issue of this? Shouldn't the debugger know how to present booleans in a particular language, regardless of which non-zero value was used to indicate truthness?

Arguable - it's UB to have a bool that isn't 0 or 1 (-fsanitize=bool catches this, for instance - there's some neat term for these sort of "corrupted" bools, but I forget what it is) so I'd expect a debugger to show the actual value and say something about the value being invalid. This'd help the developer understand why boolean tests (if (x) or if (!x)) don't work necessarily work as expected.

So, yeah, I think it is important we describe the value as 0 or 1 if it is 0 or 1, conceptually, at least.

@dwblaikie
Copy link
Collaborator

(but yeah, still would be good to see a bug/etc)

@laxmansole
Copy link
Contributor Author

(but yeah, still would be good to see a bug/etc)

We encountered this issue with cuda-gdb. I won't be able to share the high-level source, but I have added shorter LLVM IR lit tests that generate this DWARF.

@laxmansole laxmansole requested a review from Michael137 August 11, 2025 18:40
@laxmansole
Copy link
Contributor Author

ping

Copy link
Member

@Michael137 Michael137 Aug 19, 2025

Choose a reason for hiding this comment

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

Have you considered putting this boolean normalization into addConstantValue? That way, any other place where we emit booleans with out-of-range constants would benefit from this. Some of the overloads don't take a DIType though, so might not be as simple as I imagine?

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 wasn't sure if adding boolean normalization for the APInt or ConstantInt versions made sense, so I only modified the affected call sites.

Copy link
Member

Choose a reason for hiding this comment

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

I guess what's confusing me is:

  1. Who is assigning -1 to indicate true?
  2. There seem to be two independent changes in this PR:
  • emit DW_OP_lit for boolean constants when computing debug values. This seems very reasonable since it makes the DWARF expression simpler (and works regardless of how the true/false values are represented?)
  • Don't emit DW_OP_constu (-1) values for booleans. That also seems reasonable, but what I'm curious about where this -1 comes from? And then, if you do this kind of normalization for booleans here, why not any other place where DW_AT_const_value is emitted for booleans? You don't strictly have to but I think we can split these two changes into separate PRs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Who is assigning -1 to indicate true?

/// Enum that describes how the target represents true/false values.
enum BooleanContent {
UndefinedBooleanContent, // Only bit 0 counts, the rest can hold garbage.
ZeroOrOneBooleanContent, // All bits zero except for bit 0.
ZeroOrNegativeOneBooleanContent // All bits equal to bit 0.
};

There is a target-dependent setBooleanContents.

While creating #DBG_VALUE, the true/1 gets signed extednded to 0xffffffffffffffff i.e. -1(Line 736 below)

MachineOperand GetMOForConstDbgOp(const SDDbgOperand &Op) {
const Value *V = Op.getConst();
if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
if (CI->getBitWidth() > 64)
return MachineOperand::CreateCImm(CI);
return MachineOperand::CreateImm(CI->getSExtValue());
}
if (const ConstantFP *CF = dyn_cast<ConstantFP>(V))
return MachineOperand::CreateFPImm(CF);
// Note: This assumes that all nullptr constants are zero-valued.
if (isa<ConstantPointerNull>(V))
return MachineOperand::CreateImm(0);
// Undef or unhandled value type, so return an undef operand.
return MachineOperand::CreateReg(
/* Reg */ 0U, /* isDef */ false, /* isImp */ false,
/* isKill */ false, /* isDead */ false,
/* isUndef */ false, /* isEarlyClobber */ false,
/* SubReg */ 0, /* isDebug */ true);
}

And then, if you do this kind of normalization for booleans here, why not any other place where DW_AT_const_value is emitted for booleans?

I checked all the call sites for addConstantValue and found that this is the most relevant one. Alternatively, as you suggested, I could add this normalization to addConstantValue, but we don't have DIType in all overloaded functions.

I think we can split these two changes into separate PRs

Sure. Let me spilt these into two separate PRs- current one for the changes in DwarfCompileUnit.cpp and another one for the changes to emit DW_OP_lit0/1 for booleans.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

emit DW_OP_lit for boolean constants when computing debug values.

Created a separate PR #155539 for these changes

Copy link
Member

Choose a reason for hiding this comment

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

Hmmm should we address this in instruction selection perhaps then, when we create the debug MachineOperand? I see that SelectionDAG sign extends the constant:

return MachineOperand::CreateImm(CI->getSExtValue());

Whereas GlobalISel zero extends it:

MIB.addImm(CI->getZExtValue());

So GlobalISel turns the i1 true constant into 1.

My main worry with the normalization you're doing in this patch is that we silently lose information about whether the boolean representation has exhibits the UB that David mentioned. It also feels a bit strange to do the normalization in one place, but not other places where we may emit constants.

@dwblaikie @jmorse This is a bit out of my wheelhouse. Do you have an opinion at which level to do the normalization?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, bit outside my wheelhouse too - hopefully @jmorse or other Sony folks who've been working on debug locations lately have some experience to add here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It also feels a bit strange to do the normalization in one place, but not other places where we may emit constants.

@Michael137 Adding normalization to addConstantValue will ensure we don't miss anything. We'll also have to change a few call sites that use addConstantValue without DIType. Shall I make this change?

@laxmansole laxmansole force-pushed the user/lsole/boolean_constants_as_literals branch from 5810b2f to f9104e6 Compare August 21, 2025 02:01
@laxmansole laxmansole force-pushed the user/lsole/boolean_constants_as_literals branch from f9104e6 to a3fbfa6 Compare August 25, 2025 20:26
@laxmansole laxmansole force-pushed the user/lsole/boolean_constants_as_literals branch from a3fbfa6 to 859a086 Compare August 27, 2025 02:36
@laxmansole
Copy link
Contributor Author

Ping

Copy link
Member

Choose a reason for hiding this comment

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

Hmmm should we address this in instruction selection perhaps then, when we create the debug MachineOperand? I see that SelectionDAG sign extends the constant:

return MachineOperand::CreateImm(CI->getSExtValue());

Whereas GlobalISel zero extends it:

MIB.addImm(CI->getZExtValue());

So GlobalISel turns the i1 true constant into 1.

My main worry with the normalization you're doing in this patch is that we silently lose information about whether the boolean representation has exhibits the UB that David mentioned. It also feels a bit strange to do the normalization in one place, but not other places where we may emit constants.

@dwblaikie @jmorse This is a bit out of my wheelhouse. Do you have an opinion at which level to do the normalization?

@laxmansole laxmansole changed the title [DWARF] Emit 0/1 for constant boolean values [llvm][DebugInfo] Emit 0/1 for constant boolean values Sep 9, 2025
@jmorse
Copy link
Member

jmorse commented Sep 10, 2025

Breaking out from the inline thread into the main one -- sorry for the silence, I've been sunk by other stuff over the holidays,

I'm leaning towards agreeing with @Michael137, while this patch is good I think the problem is better solved in instruction-selection. Looking at the history of the highlighted code, the sign extension appeared in 563fe3c (svn r99469), where there isn't any indication that sign-extending to all-ones is the intended behaviour of the patch.

Stepping back further, a lot of this variation comes from the fact that type-system for variable locations is non-existent (cc @slinder1 ). Booleans will take on the IR type of whatever the bool is stored-as or computed by: in this godbolt example https://godbolt.org/z/PWodh7qo1 in the "beans" function output, the inlined boolean variable "bar" is described by constants with both i8 and i1 type (see metadata node !22). This is because the first dbg.value is a constant promoted off the stack where it's stored as an i8, while the second dbg.value comes from an icmp instruction. I reckon with a bit more work we could create an example where the Boolean True value is represented as both 1 and -1 in the same function after isel, which is IMO undesirable.

I don't fully understand the context about NVPTX describing True with -1: I assume it's alright to always describe True with positive 1 in DWARF even if negative 1 is an option, and debuggers will "just know" how to fixup the two. IMHO (and there's a reasonable chance I'm wrong) the appearance of DBG_VALUE -1 in LLVM is unintentional and the correspondence with NVPTX a co-incidence.

@laxmansole
Copy link
Contributor Author

I'm leaning towards agreeing with @Michael137, while this patch is good I think the problem is better solved in instruction-selection. Looking at the history of the highlighted code, the sign extension appeared in 563fe3c (svn r99469), where there isn't any indication that sign-extending to all-ones is the intended behaviour of the patch.

Sign extension is required here, otherwise we'll generate an incorrect result for the following case, where the constant value is negative -
#dbg_value(i32 -10, !20, !DIExpression(), !23)

Constant boolean value 1 or true declared with i1 type becomes 0xffffffffffffffff when sign-extended.

We can check the bitWidth at both these places to selectively zero-extend booleans declared with i1 type like,

 if (CI->getBitWidth() > 64) 
   MIB.addCImm(CI); 
 else if(CI->getBitWidth() == 1) 
  MIB.addImm(CI->getZExtValue());
 else
   MIB.addImm(CI->getSExtValue());

at the place of

if (CI->getBitWidth() > 64)
MIB.addCImm(CI);
else
MIB.addImm(CI->getZExtValue());

and

 if (CI->getBitWidth() > 64) 
   return MachineOperand::CreateCImm(CI); 
 if (CI->getBitWidth() == 1)
  return MachineOperand::CreateImm(CI->getZExtValue()); 
 return MachineOperand::CreateImm(CI->getSExtValue()); 

at the place of

if (CI->getBitWidth() > 64)
return MachineOperand::CreateCImm(CI);
return MachineOperand::CreateImm(CI->getSExtValue());

@jmorse
Copy link
Member

jmorse commented Sep 17, 2025

That makes sense (to be selective about the bitwidths). A slight downside is that then this canonicalization happens in several places instead of one, however IMO that's worth it for test consistency.

(I wondered whether we could be more specific and check whether the variable encoding type is DW_ATE_boolean... however we might then have difficulty with variadic variable locations, where the variable type is different from the operands used to compute the variable value. So that's probably a no-go).

Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just handle this when emitting the debug info? Why does this need a special case in mir

Copy link
Member

Choose a reason for hiding this comment

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

There's a discussion on this in #151225 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

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

TLDR; this should not be special cased. CodeGen imm bool fields are firmly -1

Copy link
Member

Choose a reason for hiding this comment

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

Could you elaborate please -- is there an existing convention to that effect for instructions, and does that necessarily extend to debug instructions too? As illustrated in the main thread LLVM inconsistently types variable locations for constant Booleans during optimisation, which creates the need for special-casing. This canonicalization both solves a DWARF-output-flaw, but will also improve variable location coverage by avoiding inconsistent constant-values (variable locations can be spuriously dropped as a result).

(We can cannonicalise from Booleans up to integer-one as in this patch, but it's a lot more difficult to ensure the validity of converting non-false-non-i1 LLVM-IR values down to Boolean -1).

Copy link
Contributor

Choose a reason for hiding this comment

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

Pretty much everywhere in codegen sign extends constants. i.e., MachineOperand's MO_Immediate is int64_t not uint64_t.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sign-extension is effective for handling both signed and unsigned values. However, in the case of 1-bit values, it causes true to become -1, which isn't the desired result. Special case ensures that true remains 1.

Copy link
Member

Choose a reason for hiding this comment

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

@arsenm I agree it's best to keep the convention for codegen; however I'd argue that this behaviour in this function isn't codegen, it's generating a debug-instruction that will (should) be ignored by every pieces of code that does codegen. In an ideal world we would be able to peel these two concerns (operand consistency for codegen; normalisation for debug-info) apart, and we're working towards that [0], but it's currently imperfect and this specialisation for debug-info will improve things in the meantime.

[0] https://discourse.llvm.org/t/psa-ir-output-changing-from-debug-intrinsics-to-debug-records/79578/11

Copy link
Contributor

Choose a reason for hiding this comment

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

But how is this easier than just fixing up whatever emits the final object file / asm printing?

Copy link
Member

@Michael137 Michael137 Oct 10, 2025

Choose a reason for hiding this comment

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

This whole discussion started on a version of the patch where we tried to do this in debug-info. It wasn't clear which parts of debug-info emission should be responsible for this. And we don't want to fix-up legitimately corrupted booleans. We'd want this those cases to show up in the debugger. Instruction selection being the one to adjust it for debug ops seemed like the more appropriate place to do this at (though I'm by no means an instruction selection expert; just from stepping through this scenario, this is where the -1 booleans were being propagated to debug-info).

Copy link
Member

Choose a reason for hiding this comment

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

IMO isel is the right place to put this today (ideally in a year this would all be place in a non-instruction format). It can't be earlier because LLVM-IR transforms will continue to mutate the type of operands to dbg.values. If it's later than isel, it'd need to be in three places (LiveDebugValues, location-list builder, DWARF emitter) so that identical-booleans can be recognised as such and have location-ranges merged (or at least, not conflict and become "optimised out"), which is what we risk with a de-normalised boolean-true. Plus: isel is the natural place to normalise when we reach a non-instruction debug-info format in MIR.

Again, I'm not saying breaking convention here isn't a bad thing, IMO it's the least worst of several normalisation options.

@laxmansole laxmansole force-pushed the user/lsole/boolean_constants_as_literals branch from fca6d44 to 2896a07 Compare September 19, 2025 01:40
if (CI->getBitWidth() > 64)
MIB.addCImm(CI);
else
else if (CI->getBitWidth() == 1)
Copy link
Member

Choose a reason for hiding this comment

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

Why are we modifying GlobalISel? I think it was working correctly there already right?

Copy link
Contributor Author

@laxmansole laxmansole Sep 23, 2025

Choose a reason for hiding this comment

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

Immediate values need to be sign-extended for correctness. Consider a case where the immediate operand is a negative value.
An exception to this would be 1-bit values, as they don't have a notion of sign, and sign-extending them changes their value like 1 becomes -1.

@laxmansole
Copy link
Contributor Author

Ping

1 similar comment
@laxmansole
Copy link
Contributor Author

Ping

@dwblaikie dwblaikie removed their request for review October 6, 2025 21:16
Copy link
Member

@Michael137 Michael137 left a comment

Choose a reason for hiding this comment

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

Idea SGTM if @jmorse and @arsenm are happy

@laxmansole
Copy link
Contributor Author

Ping @jmorse , @arsenm

@laxmansole
Copy link
Contributor Author

Ping

@laxmansole
Copy link
Contributor Author

Ping @arsenm

Copy link
Member

@Michael137 Michael137 left a comment

Choose a reason for hiding this comment

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

Only affects debug records so approving in the absence of other reviewers (and based on the discussion with Jeremy). Please wait til the end of the week in case anyone else has comments, they might be busy with the dev meeting

Copy link
Member

@jmorse jmorse left a comment

Choose a reason for hiding this comment

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

I had a chat with @arsenm at the conference about this -- the summary of which is "yeah it sucks to have debug instructions", but no strong resistance to this particular patch. I'm happy to assert that Matts, if not happy, then broadly OK, with this patch landing.

(Someday soon we'll get rid of debug instructions post codegen, but it is not this day).

@Michael137
Copy link
Member

I had a chat with @arsenm at the conference about this -- the summary of which is "yeah it sucks to have debug instructions", but no strong resistance to this particular patch. I'm happy to assert that Matts, if not happy, then broadly OK, with this patch landing.

(Someday soon we'll get rid of debug instructions post codegen, but it is not this day).

Awesome, thanks for following up on this!

@jryans
Copy link
Member

jryans commented Oct 30, 2025

(Someday soon we'll get rid of debug instructions post codegen, but it is not this day).

@jmorse Is there a description of the imagined design for this somewhere? This is first I've heard of such a plan, so I am curious to hear more. (It feels like it would be too off-topic to spell out the details in this PR, but I'm curious if there's an RFC or similar you can link me to.)

@jmorse
Copy link
Member

jmorse commented Oct 30, 2025

(Someday soon we'll get rid of debug instructions post codegen, but it is not this day).

@jmorse Is there a description of the imagined design for this somewhere? This is first I've heard of such a plan, so I am curious to hear more. (It feels like it would be too off-topic to spell out the details in this PR, but I'm curious if there's an RFC or similar you can link me to.)

There's a bit of an outline here and a link to some extremely rough code: https://discourse.llvm.org/t/psa-ir-output-changing-from-debug-intrinsics-to-debug-records/79578/11

@laxmansole
Copy link
Contributor Author

I had a chat with @arsenm at the conference about this -- the summary of which is "yeah it sucks to have debug instructions", but no strong resistance to this particular patch. I'm happy to assert that Matts, if not happy, then broadly OK, with this patch landing.

(Someday soon we'll get rid of debug instructions post codegen, but it is not this day).

Thanks all for reviewing and sharing your perspectives — this was a great discussion!

@laxmansole laxmansole force-pushed the user/lsole/boolean_constants_as_literals branch from 2896a07 to 32d4b26 Compare November 3, 2025 18:55
@laxmansole laxmansole force-pushed the user/lsole/boolean_constants_as_literals branch from 32d4b26 to 0968b1f Compare November 3, 2025 20:22
@ayermolo ayermolo merged commit 6fe3ecc into llvm:main Nov 3, 2025
10 checks passed
@github-actions
Copy link

github-actions bot commented Nov 3, 2025

@laxmansole Congratulations on having your first Pull Request (PR) merged into the LLVM Project!

Your changes will be combined with recent changes from other authors, then tested by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR.

Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues.

How to do this, and the rest of the post-merge process, is covered in detail here.

If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again.

If you don't get any reports, no action is required from you. Your changes are working as expected, well done!

@laxmansole laxmansole deleted the user/lsole/boolean_constants_as_literals branch November 13, 2025 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants