1313#define DEBUG_TYPE " flang-debug-type-generator"
1414
1515#include " DebugTypeGenerator.h"
16+ #include " flang/Optimizer/CodeGen/DescriptorModel.h"
17+ #include " flang/Optimizer/CodeGen/TypeConverter.h"
18+ #include " flang/Optimizer/Support/DataLayout.h"
19+ #include " mlir/Pass/Pass.h"
1620#include " llvm/ADT/ScopeExit.h"
1721#include " llvm/BinaryFormat/Dwarf.h"
1822#include " llvm/Support/Debug.h"
@@ -22,6 +26,60 @@ namespace fir {
2226DebugTypeGenerator::DebugTypeGenerator (mlir::ModuleOp m)
2327 : module (m), kindMapping(getKindMapping(m)) {
2428 LLVM_DEBUG (llvm::dbgs () << " DITypeAttr generator\n " );
29+
30+ std::optional<mlir::DataLayout> dl =
31+ fir::support::getOrSetDataLayout (module , /* allowDefaultLayout=*/ true );
32+ if (!dl)
33+ mlir::emitError (module .getLoc (), " Missing data layout attribute in module" );
34+
35+ mlir::MLIRContext *context = module .getContext ();
36+
37+ // The debug information requires the offset of certain fields in the
38+ // descriptors like lower_bound and extent for each dimension. The code
39+ // below uses getDescFieldTypeModel to get the type representing each field
40+ // and then use data layout to get its size. It adds the size to get the
41+ // offset.
42+ // As has been mentioned in DescriptorModel.h that code may be confusing
43+ // host for the target in calculating the type of the descriptor fields. But
44+ // debug info is using similar logic to what codegen is doing so it will
45+ // atleast be representing the generated code correctly.
46+ // My testing for a 32-bit shows that base_addr* is correctly given as a
47+ // 32-bit entity. The index types are 64-bit so I am a bit uncertain how
48+ // the alignment will effect the calculation of offsets in that case.
49+
50+ // base_addr*
51+ dimsOffset =
52+ dl->getTypeSizeInBits (getDescFieldTypeModel<kAddrPosInBox >()(context));
53+
54+ // elem_len
55+ dimsOffset +=
56+ dl->getTypeSizeInBits (getDescFieldTypeModel<kElemLenPosInBox >()(context));
57+
58+ // version
59+ dimsOffset +=
60+ dl->getTypeSizeInBits (getDescFieldTypeModel<kVersionPosInBox >()(context));
61+
62+ // rank
63+ dimsOffset +=
64+ dl->getTypeSizeInBits (getDescFieldTypeModel<kRankPosInBox >()(context));
65+
66+ // type
67+ dimsOffset +=
68+ dl->getTypeSizeInBits (getDescFieldTypeModel<kTypePosInBox >()(context));
69+
70+ // attribute
71+ dimsOffset += dl->getTypeSizeInBits (
72+ getDescFieldTypeModel<kAttributePosInBox >()(context));
73+
74+ // f18Addendum
75+ dimsOffset += dl->getTypeSizeInBits (
76+ getDescFieldTypeModel<kF18AddendumPosInBox >()(context));
77+
78+ // dims
79+ dimsSize =
80+ dl->getTypeSizeInBits (getDescFieldTypeModel<kDimsPosInBox >()(context));
81+ dimsOffset /= 8 ;
82+ dimsSize /= 8 ;
2583}
2684
2785static mlir::LLVM::DITypeAttr genBasicType (mlir::MLIRContext *context,
@@ -37,10 +95,82 @@ static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) {
3795 llvm::dwarf::DW_ATE_signed);
3896}
3997
98+ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType (
99+ fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
100+ mlir::LLVM::DIScopeAttr scope, mlir::Location loc, bool genAllocated,
101+ bool genAssociated) {
102+
103+ mlir::MLIRContext *context = module .getContext ();
104+ // FIXME: Assumed rank arrays not supported yet
105+ if (seqTy.hasUnknownShape ())
106+ return genPlaceholderType (context);
107+
108+ llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops;
109+ auto addOp = [&](unsigned opc, llvm::ArrayRef<uint64_t > vals) {
110+ ops.push_back (mlir::LLVM::DIExpressionElemAttr::get (context, opc, vals));
111+ };
112+
113+ addOp (llvm::dwarf::DW_OP_push_object_address, {});
114+ addOp (llvm::dwarf::DW_OP_deref, {});
115+
116+ // dataLocation = *base_addr
117+ mlir::LLVM::DIExpressionAttr dataLocation =
118+ mlir::LLVM::DIExpressionAttr::get (context, ops);
119+ addOp (llvm::dwarf::DW_OP_lit0, {});
120+ addOp (llvm::dwarf::DW_OP_ne, {});
121+
122+ // allocated = associated = (*base_addr != 0)
123+ mlir::LLVM::DIExpressionAttr valid =
124+ mlir::LLVM::DIExpressionAttr::get (context, ops);
125+ mlir::LLVM::DIExpressionAttr associated = genAllocated ? valid : nullptr ;
126+ mlir::LLVM::DIExpressionAttr allocated = genAssociated ? valid : nullptr ;
127+ ops.clear ();
128+
129+ llvm::SmallVector<mlir::LLVM::DINodeAttr> elements;
130+ mlir::LLVM::DITypeAttr elemTy =
131+ convertType (seqTy.getEleTy (), fileAttr, scope, loc);
132+ unsigned offset = dimsOffset;
133+ const unsigned indexSize = dimsSize / 3 ;
134+ for ([[maybe_unused]] auto _ : seqTy.getShape ()) {
135+ // For each dimension, find the offset of count and lower bound in the
136+ // descriptor and generate the dwarf expression to extract it.
137+ // FIXME: If `indexSize` happens to be bigger than address size on the
138+ // system then we may have to change 'DW_OP_deref' here.
139+ addOp (llvm::dwarf::DW_OP_push_object_address, {});
140+ addOp (llvm::dwarf::DW_OP_plus_uconst,
141+ {offset + (indexSize * kDimExtentPos )});
142+ addOp (llvm::dwarf::DW_OP_deref, {});
143+ // count[i] = *(base_addr + offset + (indexSize * kDimExtentPos))
144+ // where 'offset' is dimsOffset + (i * dimsSize)
145+ mlir::LLVM::DIExpressionAttr countAttr =
146+ mlir::LLVM::DIExpressionAttr::get (context, ops);
147+ ops.clear ();
148+
149+ addOp (llvm::dwarf::DW_OP_push_object_address, {});
150+ addOp (llvm::dwarf::DW_OP_plus_uconst,
151+ {offset + (indexSize * kDimLowerBoundPos )});
152+ addOp (llvm::dwarf::DW_OP_deref, {});
153+ // lower_bound[i] = *(base_addr + offset + (indexSize * kDimLowerBoundPos))
154+ mlir::LLVM::DIExpressionAttr lowerAttr =
155+ mlir::LLVM::DIExpressionAttr::get (context, ops);
156+ ops.clear ();
157+
158+ offset += dimsSize;
159+ mlir::LLVM::DISubrangeAttr subrangeTy = mlir::LLVM::DISubrangeAttr::get (
160+ context, nullptr , lowerAttr, countAttr, nullptr );
161+ elements.push_back (subrangeTy);
162+ }
163+ return mlir::LLVM::DICompositeTypeAttr::get (
164+ context, llvm::dwarf::DW_TAG_array_type, /* recursive id*/ {},
165+ /* name */ nullptr , /* file */ nullptr , /* line */ 0 ,
166+ /* scope */ nullptr , elemTy, mlir::LLVM::DIFlags::Zero,
167+ /* sizeInBits */ 0 , /* alignInBits*/ 0 , elements, dataLocation,
168+ /* rank */ nullptr , allocated, associated);
169+ }
170+
40171mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType (
41172 fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
42173 mlir::LLVM::DIScopeAttr scope, mlir::Location loc) {
43-
44174 mlir::MLIRContext *context = module .getContext ();
45175 // FIXME: Only fixed sizes arrays handled at the moment.
46176 if (seqTy.hasDynamicExtents ())
@@ -112,6 +242,12 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
112242 bitWidth * 2 , llvm::dwarf::DW_ATE_complex_float);
113243 } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(Ty)) {
114244 return convertSequenceType (seqTy, fileAttr, scope, loc);
245+ } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BoxType>(Ty)) {
246+ auto elTy = boxTy.getElementType ();
247+ if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(elTy))
248+ return convertBoxedSequenceType (seqTy, fileAttr, scope, loc, false ,
249+ false );
250+ return genPlaceholderType (context);
115251 } else {
116252 // FIXME: These types are currently unhandled. We are generating a
117253 // placeholder type to allow us to test supported bits.
0 commit comments