[flang-commits] [flang] [flang][debug] Spill a call-defined address for dbg_declare (PR #235169)

via flang-commits flang-commits at lists.llvm.org
Fri Oct 23 18:00:20 PDT 2026


https://github.com/jiel-nv updated https://github.com/llvm/llvm-project/pull/235169

>From aeb46b141c27780bde6e84faedf0e74f9c88a0bd Mon Sep 17 00:00:00 2001
From: jiel-nv <jiel at nvidia.com>
Date: Fri, 23 Oct 2026 17:05:50 -0700
Subject: [PATCH 1/2] [flang][debug] Spill a call-defined address for
 dbg_declare

---
 flang/lib/Optimizer/CodeGen/CodeGen.cpp       | 20 ++++++++-
 flang/test/Fir/declare-codegen-debug-call.fir | 42 +++++++++++++++++++
 2 files changed, 60 insertions(+), 2 deletions(-)
 create mode 100644 flang/test/Fir/declare-codegen-debug-call.fir

diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 21b433bf49387..74662060d2764 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -72,6 +72,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/TypeSwitch.h"
+#include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/Support/CommandLine.h"
 
 namespace fir {
@@ -370,8 +371,23 @@ struct DeclareOpConversion : public fir::FIROpConversion<fir::cg::XDeclareOp> {
       if (auto varAttr =
               mlir::dyn_cast_or_null<mlir::LLVM::DILocalVariableAttr>(
                   fusedLoc.getMetadata())) {
-        mlir::LLVM::DbgDeclareOp::create(rewriter, fusedLoc, memRef, varAttr,
-                                         nullptr);
+        mlir::Value addr = memRef;
+        mlir::LLVM::DIExpressionAttr expr;
+        // A variable whose storage address is returned by a call has no stack
+        // slot to point at, and a declare on an SSA value only describes it
+        // where that value is live. Spill the address to a slot and deref it.
+        if (addr.getDefiningOp<mlir::LLVM::CallOp>()) {
+          mlir::Value slot = this->genAllocaAndAddrCastWithType(
+              fusedLoc, addr.getType(), defaultAlign, rewriter);
+          mlir::LLVM::StoreOp::create(rewriter, fusedLoc, addr, slot);
+          addr = slot;
+          expr = mlir::LLVM::DIExpressionAttr::get(
+              rewriter.getContext(), {mlir::LLVM::DIExpressionElemAttr::get(
+                                         rewriter.getContext(),
+                                         llvm::dwarf::DW_OP_deref, {})});
+        }
+        mlir::LLVM::DbgDeclareOp::create(rewriter, fusedLoc, addr, varAttr,
+                                         expr);
       }
     }
     rewriter.replaceOp(declareOp, memRef);
diff --git a/flang/test/Fir/declare-codegen-debug-call.fir b/flang/test/Fir/declare-codegen-debug-call.fir
new file mode 100644
index 0000000000000..f0e990b03754c
--- /dev/null
+++ b/flang/test/Fir/declare-codegen-debug-call.fir
@@ -0,0 +1,42 @@
+// Test the debug intrinsic for a variable whose storage address is returned by
+// a call. Such a variable has no alloca to point at, so the declare must be
+// given a home slot holding the address and dereference it.
+// RUN: fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" --mlir-print-debuginfo %s | FileCheck %s
+
+module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
+  func.func private @alloc() -> !fir.ref<!fir.array<100xf32>>
+  func.func @test_address_from_call() {
+    %0 = fir.call @alloc() : () -> !fir.ref<!fir.array<100xf32>>
+    %1 = fircg.ext_declare %0 uniq_name("m") : (!fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<100xf32>> loc(#loc_m)
+    return
+  }
+
+  func.func @test_address_from_allocmem() {
+    %0 = fir.allocmem !fir.array<100xf32>
+    %1 = fircg.ext_declare %0 uniq_name("h") : (!fir.heap<!fir.array<100xf32>>) -> !fir.heap<!fir.array<100xf32>> loc(#loc_h)
+    fir.freemem %1 : !fir.heap<!fir.array<100xf32>>
+    return
+  }
+}
+
+#di_file = #llvm.di_file<"test.cuf" in "">
+#di_compile_unit = #llvm.di_compile_unit<id = distinct[0]<>, sourceLanguage = DW_LANG_Fortran95, file = #di_file, producer = "Flang", isOptimized = false, emissionKind = Full>
+#di_subprogram = #llvm.di_subprogram<compileUnit = #di_compile_unit, scope = #di_file, name = "test_address_from_call", file = #di_file, subprogramFlags = Definition>
+#di_subprogram_heap = #llvm.di_subprogram<compileUnit = #di_compile_unit, scope = #di_file, name = "test_address_from_allocmem", file = #di_file, subprogramFlags = Definition>
+#di_real = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real(kind=4)", sizeInBits = 32, encoding = DW_ATE_float>
+#di_m = #llvm.di_local_variable<scope = #di_subprogram, name = "m", file = #di_file, line = 4, type = #di_real>
+#di_h = #llvm.di_local_variable<scope = #di_subprogram_heap, name = "h", file = #di_file, line = 9, type = #di_real>
+#loc_m = loc(fused<#di_m>["test.cuf":4:11])
+#loc_h = loc(fused<#di_h>["test.cuf":9:11])
+
+// CHECK-LABEL: llvm.func @test_address_from_call
+// CHECK:         %[[SLOT:[^ ]+]] = llvm.alloca %{{[^ ]+}} x !llvm.ptr
+// CHECK:         %[[ADDR:[^ ]+]] = llvm.call @alloc()
+// CHECK:         llvm.store %[[ADDR]], %[[SLOT]]
+// CHECK:         llvm.intr.dbg.declare #[[M:[^ ]+]] #llvm.di_expression<[DW_OP_deref]> = %[[SLOT]] : !llvm.ptr
+
+// CHECK-LABEL: llvm.func @test_address_from_allocmem
+// CHECK:         %[[HSLOT:[^ ]+]] = llvm.alloca %{{[^ ]+}} x !llvm.ptr
+// CHECK:         %[[HADDR:[^ ]+]] = llvm.call @malloc
+// CHECK:         llvm.store %[[HADDR]], %[[HSLOT]]
+// CHECK:         llvm.intr.dbg.declare #[[H:[^ ]+]] #llvm.di_expression<[DW_OP_deref]> = %[[HSLOT]] : !llvm.ptr

>From 1c1d9a8d3ef59c48708b68fd1818b727e5e9d0b8 Mon Sep 17 00:00:00 2001
From: jiel-nv <37816794+jiel-nv at users.noreply.github.com>
Date: Fri, 23 Oct 2026 18:00:10 -0700
Subject: [PATCH 2/2] Fix format

---
 flang/lib/Optimizer/CodeGen/CodeGen.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 74662060d2764..9b41c2f850716 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -382,9 +382,9 @@ struct DeclareOpConversion : public fir::FIROpConversion<fir::cg::XDeclareOp> {
           mlir::LLVM::StoreOp::create(rewriter, fusedLoc, addr, slot);
           addr = slot;
           expr = mlir::LLVM::DIExpressionAttr::get(
-              rewriter.getContext(), {mlir::LLVM::DIExpressionElemAttr::get(
-                                         rewriter.getContext(),
-                                         llvm::dwarf::DW_OP_deref, {})});
+              rewriter.getContext(),
+              {mlir::LLVM::DIExpressionElemAttr::get(
+                  rewriter.getContext(), llvm::dwarf::DW_OP_deref, {})});
         }
         mlir::LLVM::DbgDeclareOp::create(rewriter, fusedLoc, addr, varAttr,
                                          expr);



More information about the flang-commits mailing list