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"
1923
2024namespace fir {
2125
26+ // / Calculate offset of any field in the descriptor.
27+ template <int DescriptorField>
28+ std::uint64_t getComponentOffset (const mlir::DataLayout &dl,
29+ mlir::MLIRContext *context,
30+ mlir::Type llvmFieldType) {
31+ static_assert (DescriptorField > 0 && DescriptorField < 10 );
32+ mlir::Type previousFieldType =
33+ getDescFieldTypeModel<DescriptorField - 1 >()(context);
34+ std::uint64_t previousOffset =
35+ getComponentOffset<DescriptorField - 1 >(dl, context, previousFieldType);
36+ std::uint64_t offset = previousOffset + dl.getTypeSize (previousFieldType);
37+ std::uint64_t fieldAlignment = dl.getTypeABIAlignment (llvmFieldType);
38+ return llvm::alignTo (offset, fieldAlignment);
39+ }
40+ template <>
41+ std::uint64_t getComponentOffset<0 >(const mlir::DataLayout &dl,
42+ mlir::MLIRContext *context,
43+ mlir::Type llvmFieldType) {
44+ return 0 ;
45+ }
46+
2247DebugTypeGenerator::DebugTypeGenerator (mlir::ModuleOp m)
2348 : module (m), kindMapping(getKindMapping(m)) {
2449 LLVM_DEBUG (llvm::dbgs () << " DITypeAttr generator\n " );
50+
51+ std::optional<mlir::DataLayout> dl =
52+ fir::support::getOrSetDataLayout (module , /* allowDefaultLayout=*/ true );
53+ if (!dl) {
54+ mlir::emitError (module .getLoc (), " Missing data layout attribute in module" );
55+ return ;
56+ }
57+
58+ mlir::MLIRContext *context = module .getContext ();
59+
60+ // The debug information requires the offset of certain fields in the
61+ // descriptors like lower_bound and extent for each dimension.
62+ mlir::Type llvmDimsType = getDescFieldTypeModel<kDimsPosInBox >()(context);
63+ dimsOffset = getComponentOffset<kDimsPosInBox >(*dl, context, llvmDimsType);
64+ dimsSize = dl->getTypeSize (llvmDimsType);
2565}
2666
2767static mlir::LLVM::DITypeAttr genBasicType (mlir::MLIRContext *context,
@@ -37,10 +77,82 @@ static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) {
3777 llvm::dwarf::DW_ATE_signed);
3878}
3979
80+ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType (
81+ fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
82+ mlir::LLVM::DIScopeAttr scope, mlir::Location loc, bool genAllocated,
83+ bool genAssociated) {
84+
85+ mlir::MLIRContext *context = module .getContext ();
86+ // FIXME: Assumed rank arrays not supported yet
87+ if (seqTy.hasUnknownShape ())
88+ return genPlaceholderType (context);
89+
90+ llvm::SmallVector<mlir::LLVM::DIExpressionElemAttr> ops;
91+ auto addOp = [&](unsigned opc, llvm::ArrayRef<uint64_t > vals) {
92+ ops.push_back (mlir::LLVM::DIExpressionElemAttr::get (context, opc, vals));
93+ };
94+
95+ addOp (llvm::dwarf::DW_OP_push_object_address, {});
96+ addOp (llvm::dwarf::DW_OP_deref, {});
97+
98+ // dataLocation = *base_addr
99+ mlir::LLVM::DIExpressionAttr dataLocation =
100+ mlir::LLVM::DIExpressionAttr::get (context, ops);
101+ addOp (llvm::dwarf::DW_OP_lit0, {});
102+ addOp (llvm::dwarf::DW_OP_ne, {});
103+
104+ // allocated = associated = (*base_addr != 0)
105+ mlir::LLVM::DIExpressionAttr valid =
106+ mlir::LLVM::DIExpressionAttr::get (context, ops);
107+ mlir::LLVM::DIExpressionAttr associated = genAllocated ? valid : nullptr ;
108+ mlir::LLVM::DIExpressionAttr allocated = genAssociated ? valid : nullptr ;
109+ ops.clear ();
110+
111+ llvm::SmallVector<mlir::LLVM::DINodeAttr> elements;
112+ mlir::LLVM::DITypeAttr elemTy =
113+ convertType (seqTy.getEleTy (), fileAttr, scope, loc);
114+ unsigned offset = dimsOffset;
115+ const unsigned indexSize = dimsSize / 3 ;
116+ for ([[maybe_unused]] auto _ : seqTy.getShape ()) {
117+ // For each dimension, find the offset of count and lower bound in the
118+ // descriptor and generate the dwarf expression to extract it.
119+ // FIXME: If `indexSize` happens to be bigger than address size on the
120+ // system then we may have to change 'DW_OP_deref' here.
121+ addOp (llvm::dwarf::DW_OP_push_object_address, {});
122+ addOp (llvm::dwarf::DW_OP_plus_uconst,
123+ {offset + (indexSize * kDimExtentPos )});
124+ addOp (llvm::dwarf::DW_OP_deref, {});
125+ // count[i] = *(base_addr + offset + (indexSize * kDimExtentPos))
126+ // where 'offset' is dimsOffset + (i * dimsSize)
127+ mlir::LLVM::DIExpressionAttr countAttr =
128+ mlir::LLVM::DIExpressionAttr::get (context, ops);
129+ ops.clear ();
130+
131+ addOp (llvm::dwarf::DW_OP_push_object_address, {});
132+ addOp (llvm::dwarf::DW_OP_plus_uconst,
133+ {offset + (indexSize * kDimLowerBoundPos )});
134+ addOp (llvm::dwarf::DW_OP_deref, {});
135+ // lower_bound[i] = *(base_addr + offset + (indexSize * kDimLowerBoundPos))
136+ mlir::LLVM::DIExpressionAttr lowerAttr =
137+ mlir::LLVM::DIExpressionAttr::get (context, ops);
138+ ops.clear ();
139+
140+ offset += dimsSize;
141+ mlir::LLVM::DISubrangeAttr subrangeTy = mlir::LLVM::DISubrangeAttr::get (
142+ context, nullptr , lowerAttr, countAttr, nullptr );
143+ elements.push_back (subrangeTy);
144+ }
145+ return mlir::LLVM::DICompositeTypeAttr::get (
146+ context, llvm::dwarf::DW_TAG_array_type, /* recursive id*/ {},
147+ /* name */ nullptr , /* file */ nullptr , /* line */ 0 ,
148+ /* scope */ nullptr , elemTy, mlir::LLVM::DIFlags::Zero,
149+ /* sizeInBits */ 0 , /* alignInBits*/ 0 , elements, dataLocation,
150+ /* rank */ nullptr , allocated, associated);
151+ }
152+
40153mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType (
41154 fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
42155 mlir::LLVM::DIScopeAttr scope, mlir::Location loc) {
43-
44156 mlir::MLIRContext *context = module .getContext ();
45157 // FIXME: Only fixed sizes arrays handled at the moment.
46158 if (seqTy.hasDynamicExtents ())
@@ -112,6 +224,12 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
112224 bitWidth * 2 , llvm::dwarf::DW_ATE_complex_float);
113225 } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(Ty)) {
114226 return convertSequenceType (seqTy, fileAttr, scope, loc);
227+ } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BoxType>(Ty)) {
228+ auto elTy = boxTy.getElementType ();
229+ if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(elTy))
230+ return convertBoxedSequenceType (seqTy, fileAttr, scope, loc, false ,
231+ false );
232+ return genPlaceholderType (context);
115233 } else {
116234 // FIXME: These types are currently unhandled. We are generating a
117235 // placeholder type to allow us to test supported bits.
0 commit comments