Skip to content

[flang][debug] Support allocatables. #95557

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 2 commits into from
Jun 17, 2024
Merged

[flang][debug] Support allocatables. #95557

merged 2 commits into from
Jun 17, 2024

Conversation

abidh
Copy link
Contributor

@abidh abidh commented Jun 14, 2024

This PR adds debug support for allocatable. The allocatable arrays use the existing functionality to read the array information from descriptor. The allocatable for the scalar shows up as pointer to the scalar.

While testing this, I notices that values of allocated and associated flags were swapped. This is also fixed in this PR.

Here is how the debugging of the allocatable looks like with this patch in place.

integer, allocatable :: ar1(:, :)
real, allocatable :: sc

allocate(sc)
allocate(ar1(3, 4))

(gdb) ptype ar1
type = integer, allocatable (3,4)
(gdb) p ar1
$1 = ((5, 6, 7) (9, 10, 11) (13, 14, 15) (17, 18, 19)) (gdb) p sc
$2 = (PTR TO -> ( real )) 0x205300
(gdb) p *sc
$3 = 3.1400001

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir labels Jun 14, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 14, 2024

@llvm/pr-subscribers-flang-fir-hlfir

Author: Abid Qadeer (abidh)

Changes

This PR adds debug support for allocatable. The allocatable arrays use the existing functionality to read the array information from descriptor. The allocatable for the scalar shows up as pointer to the scalar.

While testing this, I notices that values of allocated and associated flags were swapped. This is also fixed in this PR.

Here is how the debugging of the allocatable looks like with this patch in place.

integer, allocatable :: ar1(:, :)
real, allocatable :: sc

allocate(sc)
allocate(ar1(3, 4))

(gdb) ptype ar1
type = integer, allocatable (3,4)
(gdb) p ar1
$1 = ((5, 6, 7) (9, 10, 11) (13, 14, 15) (17, 18, 19)) (gdb) p sc
$2 = (PTR TO -> ( real )) 0x205300
(gdb) p *sc
$3 = 3.1400001


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

4 Files Affected:

  • (modified) flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp (+29-2)
  • (modified) flang/lib/Optimizer/Transforms/DebugTypeGenerator.h (+7)
  • (added) flang/test/Integration/debug-allocatable-1.f90 (+24)
  • (added) flang/test/Transforms/debug-allocatable-1.fir (+26)
diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
index 53745d10fe9e4..e0cea83f5c4c6 100644
--- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
+++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
@@ -60,8 +60,10 @@ DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m)
   // The debug information requires the offset of certain fields in the
   // descriptors like lower_bound and extent for each dimension.
   mlir::Type llvmDimsType = getDescFieldTypeModel<kDimsPosInBox>()(context);
+  mlir::Type llvmPtrType = getDescFieldTypeModel<kAddrPosInBox>()(context);
   dimsOffset = getComponentOffset<kDimsPosInBox>(*dl, context, llvmDimsType);
   dimsSize = dl->getTypeSize(llvmDimsType);
+  ptrSize = dl->getTypeSize(llvmPtrType);
 }
 
 static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context,
@@ -104,8 +106,8 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
   // allocated = associated = (*base_addr != 0)
   mlir::LLVM::DIExpressionAttr valid =
       mlir::LLVM::DIExpressionAttr::get(context, ops);
-  mlir::LLVM::DIExpressionAttr associated = genAllocated ? valid : nullptr;
-  mlir::LLVM::DIExpressionAttr allocated = genAssociated ? valid : nullptr;
+  mlir::LLVM::DIExpressionAttr allocated = genAllocated ? valid : nullptr;
+  mlir::LLVM::DIExpressionAttr associated = genAssociated ? valid : nullptr;
   ops.clear();
 
   llvm::SmallVector<mlir::LLVM::DINodeAttr> elements;
@@ -190,6 +192,28 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType(
       /* associated */ nullptr);
 }
 
+mlir::LLVM::DITypeAttr DebugTypeGenerator::convertPointerLikeType(
+    mlir::Type elTy, mlir::LLVM::DIFileAttr fileAttr,
+    mlir::LLVM::DIScopeAttr scope, mlir::Location loc, bool genAllocated,
+    bool genAssociated) {
+  mlir::MLIRContext *context = module.getContext();
+
+  // Arrays and character need different treatment because DWARF have special
+  // constructs for them to get the location from the descriptor. Rest of
+  // types are handled like pointer to underlying type.
+  if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(elTy))
+    return convertBoxedSequenceType(seqTy, fileAttr, scope, loc, genAllocated,
+                                    genAssociated);
+
+  mlir::LLVM::DITypeAttr elTyAttr = convertType(elTy, fileAttr, scope, loc);
+
+  return mlir::LLVM::DIDerivedTypeAttr::get(
+      context, llvm::dwarf::DW_TAG_pointer_type,
+      mlir::StringAttr::get(context, ""), elTyAttr, ptrSize,
+      /*alignInBits*/ 0, /* offset */ 0,
+      /* optional<address space> */ std::nullopt, /* extra data */ nullptr);
+}
+
 mlir::LLVM::DITypeAttr
 DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
                                 mlir::LLVM::DIScopeAttr scope,
@@ -229,6 +253,9 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
     if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(elTy))
       return convertBoxedSequenceType(seqTy, fileAttr, scope, loc, false,
                                       false);
+    if (auto heapTy = mlir::dyn_cast_or_null<fir::HeapType>(elTy))
+      return convertPointerLikeType(heapTy.getElementType(), fileAttr, scope,
+                                    loc, true, false);
     return genPlaceholderType(context);
   } else {
     // FIXME: These types are currently unhandled. We are generating a
diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h
index 11515d11dfed6..0ced989414d86 100644
--- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h
+++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h
@@ -45,10 +45,17 @@ class DebugTypeGenerator {
                            mlir::LLVM::DIFileAttr fileAttr,
                            mlir::LLVM::DIScopeAttr scope, mlir::Location loc,
                            bool genAllocated, bool genAssociated);
+
+  mlir::LLVM::DITypeAttr
+  convertPointerLikeType(mlir::Type elTy, mlir::LLVM::DIFileAttr fileAttr,
+                         mlir::LLVM::DIScopeAttr scope, mlir::Location loc,
+                         bool genAllocated, bool genAssociated);
+
   mlir::ModuleOp module;
   KindMapping kindMapping;
   std::uint64_t dimsSize;
   std::uint64_t dimsOffset;
+  std::uint64_t ptrSize;
 };
 
 } // namespace fir
diff --git a/flang/test/Integration/debug-allocatable-1.f90 b/flang/test/Integration/debug-allocatable-1.f90
new file mode 100644
index 0000000000000..471c8cdb7d54e
--- /dev/null
+++ b/flang/test/Integration/debug-allocatable-1.f90
@@ -0,0 +1,24 @@
+! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck  %s
+
+subroutine ff(n, m)
+  integer n, m, i, j
+  integer, allocatable :: ar1(:, :)
+  real, allocatable :: sc
+
+  allocate(ar1(n, m))
+  allocate(sc)
+  sc = 3.14
+
+  print *, sc
+  print *, ar1
+end subroutine ff
+
+
+! CHECK-DAG: !DILocalVariable(name: "ar1"{{.*}}type: ![[TY1:[0-9]+]])
+! CHECK-DAG: ![[TY1]] = !DICompositeType(tag: DW_TAG_array_type{{.*}}elements: ![[ELEMS2:[0-9]+]]{{.*}}dataLocation{{.*}}allocated: !DIExpression(DW_OP_push_object_address, DW_OP_deref, DW_OP_lit0, DW_OP_ne))
+! CHECK-DAG: ![[ELEMS2]] = !{![[ELEM1:[0-9]+]], ![[ELEM2:[0-9]+]]}
+! CHECK-DAG: ![[ELEM1]] = !DISubrange
+! CHECK-DAG: ![[ELEM2]] = !DISubrange
+! CHECK-DAG: !DILocalVariable(name: "sc"{{.*}}type: ![[TY2:[0-9]+]])
+! CHECK-DAG: ![[TY2]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[TY3:[0-9]+]]{{.*}})
+! CHECK-DAG: ![[TY3]] = !DIBasicType(name: "real"{{.*}})
diff --git a/flang/test/Transforms/debug-allocatable-1.fir b/flang/test/Transforms/debug-allocatable-1.fir
new file mode 100644
index 0000000000000..fd0beaddcdb70
--- /dev/null
+++ b/flang/test/Transforms/debug-allocatable-1.fir
@@ -0,0 +1,26 @@
+// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s
+
+
+module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
+  func.func private @_QFPff()  {
+    %c1 = arith.constant 1 : index
+    %c0 = arith.constant 0 : index
+    %0 = fir.undefined !fir.dscope
+    %1 = fir.alloca !fir.box<!fir.heap<!fir.array<?x?xi32>>> {bindc_name = "ar2", uniq_name = "_QFFffEar2"}
+    %4 = fircg.ext_declare %1 {uniq_name = "_QFFffEar2"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>  loc(#loc1)
+    %15 = fir.alloca !fir.box<!fir.heap<f32>> {bindc_name = "sc", uniq_name = "_QFFffEsc"}
+    %18 = fircg.ext_declare %15 {uniq_name = "_QFFffEsc"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> !fir.ref<!fir.box<!fir.heap<f32>>> loc(#loc2)
+    return
+  } loc(#loc3)
+}
+
+#loc1 = loc("test.f90":3:3)
+#loc2 = loc("test.f90":4:3)
+#loc3 = loc("test.f90":1:3)
+
+// CHECK-DAG: #[[TY1:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real"{{.*}}>
+// CHECK-DAG: #[[TY2:.*]] = #llvm.di_composite_type<tag = DW_TAG_array_type{{.*}}#llvm.di_subrange{{.*}}#llvm.di_subrange{{.*}}allocated = <[DW_OP_push_object_address, DW_OP_deref, DW_OP_lit0, DW_OP_ne]>>
+// CHECK-DAG: #[[TY3:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #[[TY1]]{{.*}}>
+
+// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "ar2"{{.*}}type = #[[TY2]]>
+// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "sc"{{.*}}type = #[[TY3]]>

Copy link
Contributor

@vzakhari vzakhari left a comment

Choose a reason for hiding this comment

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

LGTM, though, the literal arguments' comments may need to be cleaned up across the file.

@@ -229,6 +253,9 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(elTy))
return convertBoxedSequenceType(seqTy, fileAttr, scope, loc, false,
false);
if (auto heapTy = mlir::dyn_cast_or_null<fir::HeapType>(elTy))
return convertPointerLikeType(heapTy.getElementType(), fileAttr, scope,
loc, true, false);
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: please add comments with argument names for the literal arguments.

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 will fix this and will also open a separate PR to cleanup the comments throughout the file.

Copy link
Contributor

@tblah tblah left a comment

Choose a reason for hiding this comment

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

LGTM (with Slava's comment), thanks!

bool genAssociated) {
mlir::MLIRContext *context = module.getContext();

// Arrays and character need different treatment because DWARF have special
Copy link
Contributor

Choose a reason for hiding this comment

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

You mention character as a special case here, but the condition just below is only checking for arrays. How are characters handled?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The special handling of allocatable characters will come in the next PR. I only added arrays in this one as their handling was already present.

abidh added 2 commits June 17, 2024 11:59
This PR adds debug support for allocatable. The allocatable arrays use
the existing functionality to read the array information from
descriptor. The allocatable for the scalar shows up as pointer to the
scalar.

While testing this, I notices that values of allocated and
associated flags were swapped. This is also fixed in this PR.

Here is how the debugging of the allocatable looks like with this
patch in place.

integer, allocatable :: ar1(:, :)
real, allocatable :: sc

allocate(sc)
allocate(ar1(3, 4))

(gdb) ptype ar1
type = integer, allocatable (3,4)
(gdb) p ar1
$1 = ((5, 6, 7) (9, 10, 11) (13, 14, 15) (17, 18, 19))
(gdb) p sc
$2 = (PTR TO -> ( real )) 0x205300
(gdb) p *sc
$3 = 3.1400001
@abidh abidh merged commit 0432221 into llvm:main Jun 17, 2024
7 checks passed
@abidh abidh deleted the allocatable branch October 9, 2024 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants