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"
19
23
20
24
namespace fir {
21
25
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
+
22
47
DebugTypeGenerator::DebugTypeGenerator (mlir::ModuleOp m)
23
48
: module (m), kindMapping(getKindMapping(m)) {
24
49
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);
25
65
}
26
66
27
67
static mlir::LLVM::DITypeAttr genBasicType (mlir::MLIRContext *context,
@@ -37,10 +77,82 @@ static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) {
37
77
llvm::dwarf::DW_ATE_signed);
38
78
}
39
79
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
+
40
153
mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType (
41
154
fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
42
155
mlir::LLVM::DIScopeAttr scope, mlir::Location loc) {
43
-
44
156
mlir::MLIRContext *context = module .getContext ();
45
157
// FIXME: Only fixed sizes arrays handled at the moment.
46
158
if (seqTy.hasDynamicExtents ())
@@ -112,6 +224,12 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
112
224
bitWidth * 2 , llvm::dwarf::DW_ATE_complex_float);
113
225
} else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(Ty)) {
114
226
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);
115
233
} else {
116
234
// FIXME: These types are currently unhandled. We are generating a
117
235
// placeholder type to allow us to test supported bits.
0 commit comments