Skip to content

Commit

Permalink
[flang][debug] Support assumed-rank arrays. (#114404)
Browse files Browse the repository at this point in the history
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
```
  • Loading branch information
abidh authored Nov 5, 2024
1 parent 7c3fdcc commit a993dfc
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 7 deletions.
65 changes: 58 additions & 7 deletions flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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));
Expand All @@ -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, {});

Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions flang/lib/Optimizer/Transforms/DebugTypeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down
14 changes: 14 additions & 0 deletions flang/test/Transforms/debug-assumed-rank-array.fir
Original file line number Diff line number Diff line change
@@ -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]]{{.*}}>

0 comments on commit a993dfc

Please sign in to comment.