Skip to content

Commit a993dfc

Browse files
authored
[flang][debug] Support assumed-rank arrays. (#114404)
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 ```
1 parent 7c3fdcc commit a993dfc

File tree

3 files changed

+74
-7
lines changed

3 files changed

+74
-7
lines changed

flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,17 @@ DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m,
5858
mlir::Type llvmDimsType = getDescFieldTypeModel<kDimsPosInBox>()(context);
5959
mlir::Type llvmPtrType = getDescFieldTypeModel<kAddrPosInBox>()(context);
6060
mlir::Type llvmLenType = getDescFieldTypeModel<kElemLenPosInBox>()(context);
61+
mlir::Type llvmRankType = getDescFieldTypeModel<kRankPosInBox>()(context);
62+
6163
dimsOffset =
6264
getComponentOffset<kDimsPosInBox>(*dataLayout, context, llvmDimsType);
6365
dimsSize = dataLayout->getTypeSize(llvmDimsType);
6466
ptrSize = dataLayout->getTypeSize(llvmPtrType);
67+
rankSize = dataLayout->getTypeSize(llvmRankType);
6568
lenOffset =
6669
getComponentOffset<kElemLenPosInBox>(*dataLayout, context, llvmLenType);
70+
rankOffset =
71+
getComponentOffset<kRankPosInBox>(*dataLayout, context, llvmRankType);
6772
}
6873

6974
static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context,
@@ -114,10 +119,7 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
114119
bool genAllocated, bool genAssociated) {
115120

116121
mlir::MLIRContext *context = module.getContext();
117-
// FIXME: Assumed rank arrays not supported yet
118-
if (seqTy.hasUnknownShape())
119-
return genPlaceholderType(context);
120-
122+
llvm::SmallVector<mlir::LLVM::DINodeAttr> elements;
121123
llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops;
122124
auto addOp = [&](unsigned opc, llvm::ArrayRef<uint64_t> vals) {
123125
ops.push_back(mlir::LLVM::DIExpressionElemAttr::get(context, opc, vals));
@@ -129,6 +131,58 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
129131
// dataLocation = *base_addr
130132
mlir::LLVM::DIExpressionAttr dataLocation =
131133
mlir::LLVM::DIExpressionAttr::get(context, ops);
134+
ops.clear();
135+
136+
mlir::LLVM::DITypeAttr elemTy =
137+
convertType(seqTy.getEleTy(), fileAttr, scope, declOp);
138+
139+
// Assumed-rank arrays
140+
if (seqTy.hasUnknownShape()) {
141+
addOp(llvm::dwarf::DW_OP_push_object_address, {});
142+
addOp(llvm::dwarf::DW_OP_plus_uconst, {rankOffset});
143+
addOp(llvm::dwarf::DW_OP_deref_size, {rankSize});
144+
mlir::LLVM::DIExpressionAttr rank =
145+
mlir::LLVM::DIExpressionAttr::get(context, ops);
146+
ops.clear();
147+
148+
auto genSubrangeOp = [&](unsigned field) -> mlir::LLVM::DIExpressionAttr {
149+
// The dwarf expression for generic subrange assumes that dimension for
150+
// which it is being generated is already pushed on the stack. Here is the
151+
// formula we will use to calculate count for example.
152+
// *(base_addr + offset_count_0 + (dimsSize x dimension_number)).
153+
// where offset_count_0 is offset of the count field for the 0th dimension
154+
addOp(llvm::dwarf::DW_OP_push_object_address, {});
155+
addOp(llvm::dwarf::DW_OP_over, {});
156+
addOp(llvm::dwarf::DW_OP_constu, {dimsSize});
157+
addOp(llvm::dwarf::DW_OP_mul, {});
158+
addOp(llvm::dwarf::DW_OP_plus_uconst,
159+
{dimsOffset + ((dimsSize / 3) * field)});
160+
addOp(llvm::dwarf::DW_OP_plus, {});
161+
addOp(llvm::dwarf::DW_OP_deref, {});
162+
mlir::LLVM::DIExpressionAttr attr =
163+
mlir::LLVM::DIExpressionAttr::get(context, ops);
164+
ops.clear();
165+
return attr;
166+
};
167+
168+
mlir::LLVM::DIExpressionAttr lowerAttr = genSubrangeOp(kDimLowerBoundPos);
169+
mlir::LLVM::DIExpressionAttr countAttr = genSubrangeOp(kDimExtentPos);
170+
mlir::LLVM::DIExpressionAttr strideAttr = genSubrangeOp(kDimStridePos);
171+
172+
auto subrangeTy = mlir::LLVM::DIGenericSubrangeAttr::get(
173+
context, countAttr, lowerAttr, /*upperBound=*/nullptr, strideAttr);
174+
elements.push_back(subrangeTy);
175+
176+
return mlir::LLVM::DICompositeTypeAttr::get(
177+
context, llvm::dwarf::DW_TAG_array_type, /*name=*/nullptr,
178+
/*file=*/nullptr, /*line=*/0, /*scope=*/nullptr, elemTy,
179+
mlir::LLVM::DIFlags::Zero, /*sizeInBits=*/0, /*alignInBits=*/0,
180+
elements, dataLocation, rank, /*allocated=*/nullptr,
181+
/*associated=*/nullptr);
182+
}
183+
184+
addOp(llvm::dwarf::DW_OP_push_object_address, {});
185+
addOp(llvm::dwarf::DW_OP_deref, {});
132186
addOp(llvm::dwarf::DW_OP_lit0, {});
133187
addOp(llvm::dwarf::DW_OP_ne, {});
134188

@@ -139,9 +193,6 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
139193
mlir::LLVM::DIExpressionAttr associated = genAssociated ? valid : nullptr;
140194
ops.clear();
141195

142-
llvm::SmallVector<mlir::LLVM::DINodeAttr> elements;
143-
mlir::LLVM::DITypeAttr elemTy =
144-
convertType(seqTy.getEleTy(), fileAttr, scope, declOp);
145196
unsigned offset = dimsOffset;
146197
unsigned index = 0;
147198
mlir::IntegerType intTy = mlir::IntegerType::get(context, 64);

flang/lib/Optimizer/Transforms/DebugTypeGenerator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ class DebugTypeGenerator {
8989
std::uint64_t dimsOffset;
9090
std::uint64_t ptrSize;
9191
std::uint64_t lenOffset;
92+
std::uint64_t rankOffset;
93+
std::uint64_t rankSize;
9294
llvm::DenseMap<mlir::Type, mlir::LLVM::DITypeAttr> typeCache;
9395
};
9496

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s
2+
3+
module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
4+
func.func @_QFPfn(%arg0: !fir.box<!fir.array<*:i32>> ) {
5+
%1 = fir.undefined !fir.dscope
6+
%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)
7+
return
8+
} loc(#loc1)
9+
}
10+
#loc1 = loc("test1.f90":1:1)
11+
#loc2 = loc("test1.f90":3:16)
12+
13+
// 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)]>>
14+
// CHECK: #llvm.di_local_variable<{{.*}}name = "x"{{.*}}type = #[[TY]]{{.*}}>

0 commit comments

Comments
 (0)