[flang-commits] [flang] [flang][debug] Support assumed-rank arrays. (PR #114404)

via flang-commits flang-commits at lists.llvm.org
Thu Oct 31 06:52:44 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Abid Qadeer (abidh)

<details>
<summary>Changes</summary>

The assumed-rank array are represented by DIGenericSubrange in debug metadata. We have to provide 2 things.

1. Expression to get rank value at the runtime from descriptor.

2. Assuming the dimension number for which we want the array information has been put on the DWARF expression stack, expressions which will extract the lowerBound, count and stride information from the descriptor for the said dimension.

With this patch in place, this is how I see an assumed_rank variable being evaluated by GDB. 

```
function mean(x) result(y)
integer, intent(in) :: x(..)
...
end

program main
use mod
implicit none
integer :: x1,xvec(3),xmat(3,3),xtens(3,3,3)
x1 = 5
xvec = 6
xmat = 7
xtens = 8
print *,mean(xvec), mean(xmat), mean(xtens), mean(x1)
end program main

(gdb) p x
$1 = (6, 6, 6)

(gdb) p x
$2 = ((7, 7, 7) (7, 7, 7) (7, 7, 7))

(gdb) p x
$3 = (((8, 8, 8) (8, 8, 8) (8, 8, 8)) ((8, 8, 8) (8, 8, 8) (8, 8, 8)) ((8, 8, 8) (8, 8, 8) (8, 8, 8)))

(gdb) p x
$4 = 5
```


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


3 Files Affected:

- (modified) flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp (+58-7) 
- (modified) flang/lib/Optimizer/Transforms/DebugTypeGenerator.h (+2) 
- (added) flang/test/Transforms/debug-assumed-rank-array.fir (+14) 


``````````diff
diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
index a070c87137fa16..0187524d76cdd5 100644
--- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
+++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
@@ -58,12 +58,17 @@ DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m,
   mlir::Type llvmDimsType = getDescFieldTypeModel<kDimsPosInBox>()(context);
   mlir::Type llvmPtrType = getDescFieldTypeModel<kAddrPosInBox>()(context);
   mlir::Type llvmLenType = getDescFieldTypeModel<kElemLenPosInBox>()(context);
+  mlir::Type llvmRankType = getDescFieldTypeModel<kRankPosInBox>()(context);
+
   dimsOffset =
       getComponentOffset<kDimsPosInBox>(*dataLayout, context, llvmDimsType);
   dimsSize = dataLayout->getTypeSize(llvmDimsType);
   ptrSize = dataLayout->getTypeSize(llvmPtrType);
+  rankSize = dataLayout->getTypeSize(llvmRankType);
   lenOffset =
       getComponentOffset<kElemLenPosInBox>(*dataLayout, context, llvmLenType);
+  rankOffset =
+      getComponentOffset<kRankPosInBox>(*dataLayout, context, llvmRankType);
 }
 
 static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context,
@@ -114,10 +119,7 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
     bool genAllocated, bool genAssociated) {
 
   mlir::MLIRContext *context = module.getContext();
-  // FIXME: Assumed rank arrays not supported yet
-  if (seqTy.hasUnknownShape())
-    return genPlaceholderType(context);
-
+  llvm::SmallVector<mlir::LLVM::DINodeAttr> elements;
   llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops;
   auto addOp = [&](unsigned opc, llvm::ArrayRef<uint64_t> vals) {
     ops.push_back(mlir::LLVM::DIExpressionElemAttr::get(context, opc, vals));
@@ -129,6 +131,58 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
   // dataLocation = *base_addr
   mlir::LLVM::DIExpressionAttr dataLocation =
       mlir::LLVM::DIExpressionAttr::get(context, ops);
+  ops.clear();
+
+  mlir::LLVM::DITypeAttr elemTy =
+      convertType(seqTy.getEleTy(), fileAttr, scope, declOp);
+
+  // Assumed-rank arrays
+  if (seqTy.hasUnknownShape()) {
+    addOp(llvm::dwarf::DW_OP_push_object_address, {});
+    addOp(llvm::dwarf::DW_OP_plus_uconst, {rankOffset});
+    addOp(llvm::dwarf::DW_OP_deref_size, {rankSize});
+    mlir::LLVM::DIExpressionAttr rank =
+        mlir::LLVM::DIExpressionAttr::get(context, ops);
+    ops.clear();
+
+    auto genSubrangeOp = [&](unsigned field) -> mlir::LLVM::DIExpressionAttr {
+      // The dwarf expression for generic subrange assumes that dimension for
+      // which it is being generated is already pushed on the stack. Here is the
+      // formula we will use to calculate count for example.
+      // *(base_addr + offset_count_0 + (dimsSize x dimension_number)).
+      // where offset_count_0 is offset of the count field for the 0th dimension
+      addOp(llvm::dwarf::DW_OP_push_object_address, {});
+      addOp(llvm::dwarf::DW_OP_over, {});
+      addOp(llvm::dwarf::DW_OP_constu, {dimsSize});
+      addOp(llvm::dwarf::DW_OP_mul, {});
+      addOp(llvm::dwarf::DW_OP_plus_uconst,
+            {dimsOffset + ((dimsSize / 3) * field)});
+      addOp(llvm::dwarf::DW_OP_plus, {});
+      addOp(llvm::dwarf::DW_OP_deref, {});
+      mlir::LLVM::DIExpressionAttr attr =
+          mlir::LLVM::DIExpressionAttr::get(context, ops);
+      ops.clear();
+      return attr;
+    };
+
+    mlir::LLVM::DIExpressionAttr lowerAttr = genSubrangeOp(kDimLowerBoundPos);
+    mlir::LLVM::DIExpressionAttr countAttr = genSubrangeOp(kDimExtentPos);
+    mlir::LLVM::DIExpressionAttr strideAttr = genSubrangeOp(kDimStridePos);
+
+    auto subrangeTy = mlir::LLVM::DIGenericSubrangeAttr::get(
+        context, countAttr, lowerAttr, /*upperBound=*/nullptr, strideAttr);
+    elements.push_back(subrangeTy);
+
+    return mlir::LLVM::DICompositeTypeAttr::get(
+        context, llvm::dwarf::DW_TAG_array_type, /*name=*/nullptr,
+        /*file=*/nullptr, /*line=*/0, /*scope=*/nullptr, elemTy,
+        mlir::LLVM::DIFlags::Zero, /*sizeInBits=*/0, /*alignInBits=*/0,
+        elements, dataLocation, rank, /*allocated=*/nullptr,
+        /*associated=*/nullptr);
+  }
+
+  addOp(llvm::dwarf::DW_OP_push_object_address, {});
+  addOp(llvm::dwarf::DW_OP_deref, {});
   addOp(llvm::dwarf::DW_OP_lit0, {});
   addOp(llvm::dwarf::DW_OP_ne, {});
 
@@ -139,9 +193,6 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
   mlir::LLVM::DIExpressionAttr associated = genAssociated ? valid : nullptr;
   ops.clear();
 
-  llvm::SmallVector<mlir::LLVM::DINodeAttr> elements;
-  mlir::LLVM::DITypeAttr elemTy =
-      convertType(seqTy.getEleTy(), fileAttr, scope, declOp);
   unsigned offset = dimsOffset;
   unsigned index = 0;
   mlir::IntegerType intTy = mlir::IntegerType::get(context, 64);
diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h
index c1fce4bdae5ce5..7daa0af166e697 100644
--- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h
+++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h
@@ -89,6 +89,8 @@ class DebugTypeGenerator {
   std::uint64_t dimsOffset;
   std::uint64_t ptrSize;
   std::uint64_t lenOffset;
+  std::uint64_t rankOffset;
+  std::uint64_t rankSize;
   llvm::DenseMap<mlir::Type, mlir::LLVM::DITypeAttr> typeCache;
 };
 
diff --git a/flang/test/Transforms/debug-assumed-rank-array.fir b/flang/test/Transforms/debug-assumed-rank-array.fir
new file mode 100644
index 00000000000000..ce474cd259619b
--- /dev/null
+++ b/flang/test/Transforms/debug-assumed-rank-array.fir
@@ -0,0 +1,14 @@
+// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s
+
+module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
+  func.func @_QFPfn(%arg0: !fir.box<!fir.array<*:i32>> )  {
+    %1 = fir.undefined !fir.dscope
+    %2 = fircg.ext_declare %arg0 dummy_scope %1 {uniq_name = "_QFFfnEx"} : (!fir.box<!fir.array<*:i32>>, !fir.dscope) -> !fir.box<!fir.array<*:i32>> loc(#loc2)
+    return
+  } loc(#loc1)
+}
+#loc1 = loc("test1.f90":1:1)
+#loc2 = loc("test1.f90":3:16)
+
+// CHECK: #[[TY:.*]] = #llvm.di_composite_type<tag = DW_TAG_array_type{{.*}}elements = #llvm.di_generic_subrange<count = #llvm.di_expression<[DW_OP_push_object_address, DW_OP_over, DW_OP_constu(24), DW_OP_mul, DW_OP_plus_uconst(32), DW_OP_plus, DW_OP_deref]>, lowerBound = #llvm.di_expression<[DW_OP_push_object_address, DW_OP_over, DW_OP_constu(24), DW_OP_mul, DW_OP_plus_uconst(24), DW_OP_plus, DW_OP_deref]>, stride = #llvm.di_expression<[DW_OP_push_object_address, DW_OP_over, DW_OP_constu(24), DW_OP_mul, DW_OP_plus_uconst(40), DW_OP_plus, DW_OP_deref]>>, dataLocation = <[DW_OP_push_object_address, DW_OP_deref]>, rank = <[DW_OP_push_object_address, DW_OP_plus_uconst(20), DW_OP_deref_size(1)]>>
+// CHECK: #llvm.di_local_variable<{{.*}}name = "x"{{.*}}type = #[[TY]]{{.*}}>

``````````

</details>


https://github.com/llvm/llvm-project/pull/114404


More information about the flang-commits mailing list