@@ -78,6 +78,35 @@ static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) {
78
78
/* bitSize=*/ 32 , llvm::dwarf::DW_ATE_signed);
79
79
}
80
80
81
+ // Helper function to create DILocalVariableAttr and DbgValueOp when information
82
+ // about the size or dimension of a variable etc lives in an mlir::Value.
83
+ mlir::LLVM::DILocalVariableAttr DebugTypeGenerator::generateArtificialVariable (
84
+ mlir::MLIRContext *context, mlir::Value val,
85
+ mlir::LLVM::DIFileAttr fileAttr, mlir::LLVM::DIScopeAttr scope,
86
+ fir::cg::XDeclareOp declOp) {
87
+ // There can be multiple artificial variable for a single declOp. To help
88
+ // distinguish them, we pad the name with a counter. The counter is the
89
+ // position of 'val' in the operands of declOp.
90
+ auto varID = std::distance (
91
+ declOp.getOperands ().begin (),
92
+ std::find (declOp.getOperands ().begin (), declOp.getOperands ().end (), val));
93
+ mlir::OpBuilder builder (context);
94
+ auto name = mlir::StringAttr::get (context, " ." + declOp.getUniqName ().str () +
95
+ std::to_string (varID));
96
+ builder.setInsertionPoint (declOp);
97
+ mlir::Type type = val.getType ();
98
+ if (!mlir::isa<mlir::IntegerType>(type) || !type.isSignlessInteger ()) {
99
+ type = builder.getIntegerType (64 );
100
+ val = builder.create <fir::ConvertOp>(declOp.getLoc (), type, val);
101
+ }
102
+ mlir::LLVM::DITypeAttr Ty = convertType (type, fileAttr, scope, declOp);
103
+ auto lvAttr = mlir::LLVM::DILocalVariableAttr::get (
104
+ context, scope, name, fileAttr, /* line=*/ 0 , /* argNo=*/ 0 ,
105
+ /* alignInBits=*/ 0 , Ty, mlir::LLVM::DIFlags::Artificial);
106
+ builder.create <mlir::LLVM::DbgValueOp>(declOp.getLoc (), val, lvAttr, nullptr );
107
+ return lvAttr;
108
+ }
109
+
81
110
mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType (
82
111
fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
83
112
mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp,
@@ -122,11 +151,12 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
122
151
mlir::Attribute lowerAttr = nullptr ;
123
152
// If declaration has a lower bound, use it.
124
153
if (declOp && declOp.getShift ().size () > index) {
125
- // TODO: Handle case where lower bound is a variable (instead of a
126
- // constant as handled here)
127
154
if (std::optional<std::int64_t > optint =
128
155
getIntIfConstant (declOp.getShift ()[index]))
129
156
lowerAttr = mlir::IntegerAttr::get (intTy, llvm::APInt (64 , *optint));
157
+ else
158
+ lowerAttr = generateArtificialVariable (
159
+ context, declOp.getShift ()[index], fileAttr, scope, declOp);
130
160
}
131
161
// FIXME: If `indexSize` happens to be bigger than address size on the
132
162
// system then we may have to change 'DW_OP_deref' here.
@@ -320,31 +350,43 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType(
320
350
unsigned index = 0 ;
321
351
auto intTy = mlir::IntegerType::get (context, 64 );
322
352
for (fir::SequenceType::Extent dim : seqTy.getShape ()) {
323
- int64_t shift = 1 ;
353
+ mlir::Attribute lowerAttr = nullptr ;
354
+ mlir::Attribute countAttr = nullptr ;
355
+ // If declOp is present, we use the shift in it to get the lower bound of
356
+ // the array. If it is constant, that is used. If it is not constant, we
357
+ // create a variable that represents its location and use that as lower
358
+ // bound. As an optimization, we don't create a lower bound when shift is a
359
+ // constant 1 as that is the default.
324
360
if (declOp && declOp.getShift ().size () > index) {
325
361
if (std::optional<std::int64_t > optint =
326
- getIntIfConstant (declOp.getShift ()[index]))
327
- shift = *optint;
362
+ getIntIfConstant (declOp.getShift ()[index])) {
363
+ if (*optint != 1 )
364
+ lowerAttr = mlir::IntegerAttr::get (intTy, llvm::APInt (64 , *optint));
365
+ } else
366
+ lowerAttr = generateArtificialVariable (
367
+ context, declOp.getShift ()[index], fileAttr, scope, declOp);
328
368
}
369
+
329
370
if (dim == seqTy.getUnknownExtent ()) {
330
- mlir::IntegerAttr lowerAttr = nullptr ;
331
- if (declOp && declOp.getShift ().size () > index)
332
- lowerAttr = mlir::IntegerAttr::get (intTy, llvm::APInt (64 , shift));
333
- // FIXME: This path is taken for assumed size arrays but also for arrays
334
- // with non constant extent. For the latter case, the DISubrangeAttr
335
- // should point to a variable which will have the extent at runtime.
336
- auto subrangeTy = mlir::LLVM::DISubrangeAttr::get (
337
- context, /* count=*/ nullptr , lowerAttr, /* upperBound*/ nullptr ,
338
- /* stride*/ nullptr );
339
- elements.push_back (subrangeTy);
340
- } else {
341
- auto countAttr = mlir::IntegerAttr::get (intTy, llvm::APInt (64 , dim));
342
- auto lowerAttr = mlir::IntegerAttr::get (intTy, llvm::APInt (64 , shift));
343
- auto subrangeTy = mlir::LLVM::DISubrangeAttr::get (
344
- context, countAttr, lowerAttr, /* upperBound=*/ nullptr ,
345
- /* stride=*/ nullptr );
346
- elements.push_back (subrangeTy);
347
- }
371
+ // This path is taken for both assumed size array or when the size of the
372
+ // array is variable. In the case of variable size, we create a variable
373
+ // to use as countAttr. Note that fir has a constant size of -1 for
374
+ // assumed size array. So !optint check makes sure we don't generate
375
+ // variable in that case.
376
+ if (declOp && declOp.getShape ().size () > index) {
377
+ std::optional<std::int64_t > optint =
378
+ getIntIfConstant (declOp.getShape ()[index]);
379
+ if (!optint)
380
+ countAttr = generateArtificialVariable (
381
+ context, declOp.getShape ()[index], fileAttr, scope, declOp);
382
+ }
383
+ } else
384
+ countAttr = mlir::IntegerAttr::get (intTy, llvm::APInt (64 , dim));
385
+
386
+ auto subrangeTy = mlir::LLVM::DISubrangeAttr::get (
387
+ context, countAttr, lowerAttr, /* upperBound=*/ nullptr ,
388
+ /* stride=*/ nullptr );
389
+ elements.push_back (subrangeTy);
348
390
++index;
349
391
}
350
392
// Apart from arrays, the `DICompositeTypeAttr` is used for other things like
@@ -400,23 +442,8 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertCharacterType(
400
442
// variable that will contain that length. This variable is used as
401
443
// 'stringLength' in DIStringTypeAttr.
402
444
if (declOp && !declOp.getTypeparams ().empty ()) {
403
- auto name =
404
- mlir::StringAttr::get (context, " ." + declOp.getUniqName ().str ());
405
- mlir::OpBuilder builder (context);
406
- builder.setInsertionPoint (declOp);
407
- mlir::Value sizeVal = declOp.getTypeparams ()[0 ];
408
- mlir::Type type = sizeVal.getType ();
409
- if (!mlir::isa<mlir::IntegerType>(type) || !type.isSignlessInteger ()) {
410
- type = builder.getIntegerType (64 );
411
- sizeVal =
412
- builder.create <fir::ConvertOp>(declOp.getLoc (), type, sizeVal);
413
- }
414
- mlir::LLVM::DITypeAttr Ty = convertType (type, fileAttr, scope, declOp);
415
- auto lvAttr = mlir::LLVM::DILocalVariableAttr::get (
416
- context, scope, name, fileAttr, /* line=*/ 0 , /* argNo=*/ 0 ,
417
- /* alignInBits=*/ 0 , Ty, mlir::LLVM::DIFlags::Artificial);
418
- builder.create <mlir::LLVM::DbgValueOp>(declOp.getLoc (), sizeVal, lvAttr,
419
- nullptr );
445
+ mlir::LLVM::DILocalVariableAttr lvAttr = generateArtificialVariable (
446
+ context, declOp.getTypeparams ()[0 ], fileAttr, scope, declOp);
420
447
varAttr = mlir::cast<mlir::LLVM::DIVariableAttr>(lvAttr);
421
448
}
422
449
}
0 commit comments