13
13
#define DEBUG_TYPE " flang-debug-type-generator"
14
14
15
15
#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"
16
20
#include " llvm/ADT/ScopeExit.h"
17
21
#include " llvm/BinaryFormat/Dwarf.h"
18
22
#include " llvm/Support/Debug.h"
@@ -22,6 +26,60 @@ namespace fir {
22
26
DebugTypeGenerator::DebugTypeGenerator (mlir::ModuleOp m)
23
27
: module (m), kindMapping(getKindMapping(m)) {
24
28
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 ;
25
83
}
26
84
27
85
static mlir::LLVM::DITypeAttr genBasicType (mlir::MLIRContext *context,
@@ -37,10 +95,82 @@ static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) {
37
95
llvm::dwarf::DW_ATE_signed);
38
96
}
39
97
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
+
40
171
mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType (
41
172
fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
42
173
mlir::LLVM::DIScopeAttr scope, mlir::Location loc) {
43
-
44
174
mlir::MLIRContext *context = module .getContext ();
45
175
// FIXME: Only fixed sizes arrays handled at the moment.
46
176
if (seqTy.hasDynamicExtents ())
@@ -112,6 +242,12 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
112
242
bitWidth * 2 , llvm::dwarf::DW_ATE_complex_float);
113
243
} else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(Ty)) {
114
244
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);
115
251
} else {
116
252
// FIXME: These types are currently unhandled. We are generating a
117
253
// placeholder type to allow us to test supported bits.
0 commit comments