@@ -78,6 +78,35 @@ static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) {
7878 /* bitSize=*/ 32 , llvm::dwarf::DW_ATE_signed);
7979}
8080
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+
81110mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType (
82111 fir::SequenceType seqTy, mlir::LLVM::DIFileAttr fileAttr,
83112 mlir::LLVM::DIScopeAttr scope, fir::cg::XDeclareOp declOp,
@@ -122,11 +151,12 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
122151 mlir::Attribute lowerAttr = nullptr ;
123152 // If declaration has a lower bound, use it.
124153 if (declOp && declOp.getShift ().size () > index) {
125- // TODO: Handle case where lower bound is a variable (instead of a
126- // constant as handled here)
127154 if (std::optional<std::int64_t > optint =
128155 getIntIfConstant (declOp.getShift ()[index]))
129156 lowerAttr = mlir::IntegerAttr::get (intTy, llvm::APInt (64 , *optint));
157+ else
158+ lowerAttr = generateArtificialVariable (
159+ context, declOp.getShift ()[index], fileAttr, scope, declOp);
130160 }
131161 // FIXME: If `indexSize` happens to be bigger than address size on the
132162 // system then we may have to change 'DW_OP_deref' here.
@@ -320,31 +350,43 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType(
320350 unsigned index = 0 ;
321351 auto intTy = mlir::IntegerType::get (context, 64 );
322352 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.
324360 if (declOp && declOp.getShift ().size () > index) {
325361 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);
328368 }
369+
329370 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);
348390 ++index;
349391 }
350392 // Apart from arrays, the `DICompositeTypeAttr` is used for other things like
@@ -400,23 +442,8 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertCharacterType(
400442 // variable that will contain that length. This variable is used as
401443 // 'stringLength' in DIStringTypeAttr.
402444 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);
420447 varAttr = mlir::cast<mlir::LLVM::DIVariableAttr>(lvAttr);
421448 }
422449 }
0 commit comments