@@ -247,29 +247,62 @@ class CapturedCharacterScalars
247
247
}
248
248
};
249
249
250
- // / Class defining how polymorphic entities are captured in internal procedures.
251
- // / Polymorphic entities are always boxed as a fir.class box.
252
- class CapturedPolymorphic : public CapturedSymbols <CapturedPolymorphic> {
250
+ // / Class defining how polymorphic scalar entities are captured in internal
251
+ // / procedures. Polymorphic entities are always boxed as a fir.class box.
252
+ // / Polymorphic array can be handled in CapturedArrays directly
253
+ class CapturedPolymorphicScalar
254
+ : public CapturedSymbols<CapturedPolymorphicScalar> {
253
255
public:
254
256
static mlir::Type getType (Fortran::lower::AbstractConverter &converter,
255
257
const Fortran::semantics::Symbol &sym) {
256
258
return converter.genType (sym);
257
259
}
258
260
static void instantiateHostTuple (const InstantiateHostTuple &args,
259
261
Fortran::lower::AbstractConverter &converter,
260
- const Fortran::semantics::Symbol &) {
262
+ const Fortran::semantics::Symbol &sym ) {
261
263
fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
264
+ mlir::Location loc = args.loc ;
262
265
mlir::Type typeInTuple = fir::dyn_cast_ptrEleTy (args.addrInTuple .getType ());
263
266
assert (typeInTuple && " addrInTuple must be an address" );
264
267
mlir::Value castBox = builder.createConvert (args.loc , typeInTuple,
265
268
fir::getBase (args.hostValue ));
266
- builder.create <fir::StoreOp>(args.loc , castBox, args.addrInTuple );
269
+ if (Fortran::semantics::IsOptional (sym)) {
270
+ auto isPresent =
271
+ builder.create <fir::IsPresentOp>(loc, builder.getI1Type (), castBox);
272
+ builder.genIfThenElse (loc, isPresent)
273
+ .genThen ([&]() {
274
+ builder.create <fir::StoreOp>(loc, castBox, args.addrInTuple );
275
+ })
276
+ .genElse ([&]() {
277
+ mlir::Value null = fir::factory::createUnallocatedBox (
278
+ builder, loc, typeInTuple,
279
+ /* nonDeferredParams=*/ mlir::ValueRange{});
280
+ builder.create <fir::StoreOp>(loc, null, args.addrInTuple );
281
+ })
282
+ .end ();
283
+ } else {
284
+ builder.create <fir::StoreOp>(loc, castBox, args.addrInTuple );
285
+ }
267
286
}
268
287
static void getFromTuple (const GetFromTuple &args,
269
288
Fortran::lower::AbstractConverter &converter,
270
289
const Fortran::semantics::Symbol &sym,
271
290
const Fortran::lower::BoxAnalyzer &ba) {
272
- bindCapturedSymbol (sym, args.valueInTuple , converter, args.symMap );
291
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
292
+ mlir::Location loc = args.loc ;
293
+ mlir::Value box = args.valueInTuple ;
294
+ if (Fortran::semantics::IsOptional (sym)) {
295
+ auto boxTy = box.getType ().cast <fir::BaseBoxType>();
296
+ auto eleTy = boxTy.getEleTy ();
297
+ if (!fir::isa_ref_type (eleTy))
298
+ eleTy = builder.getRefType (eleTy);
299
+ auto addr = builder.create <fir::BoxAddrOp>(loc, eleTy, box);
300
+ mlir::Value isPresent = builder.genIsNotNullAddr (loc, addr);
301
+ auto absentBox = builder.create <fir::AbsentOp>(loc, boxTy);
302
+ box =
303
+ builder.create <mlir::arith::SelectOp>(loc, isPresent, box, absentBox);
304
+ }
305
+ bindCapturedSymbol (sym, box, converter, args.symMap );
273
306
}
274
307
};
275
308
@@ -342,7 +375,12 @@ class CapturedArrays : public CapturedSymbols<CapturedArrays> {
342
375
static mlir::Type getType (Fortran::lower::AbstractConverter &converter,
343
376
const Fortran::semantics::Symbol &sym) {
344
377
mlir::Type type = converter.genType (sym);
345
- assert (type.isa <fir::SequenceType>() && " must be a sequence type" );
378
+ bool isPolymorphic = Fortran::semantics::IsPolymorphic (sym);
379
+ assert (type.isa <fir::SequenceType>() ||
380
+ (isPolymorphic && type.isa <fir::ClassType>()) &&
381
+ " must be a sequence type" );
382
+ if (isPolymorphic)
383
+ return type;
346
384
return fir::BoxType::get (type);
347
385
}
348
386
@@ -410,13 +448,13 @@ class CapturedArrays : public CapturedSymbols<CapturedArrays> {
410
448
fir::factory::readBoxValue (builder, loc, boxValue),
411
449
converter, args.symMap );
412
450
} else {
413
- // Keep variable as a fir.box.
451
+ // Keep variable as a fir.box/fir.class .
414
452
// If this is an optional that is absent, the fir.box needs to be an
415
453
// AbsentOp result, otherwise it will not work properly with IsPresentOp
416
454
// (absent boxes are null descriptor addresses, not descriptors containing
417
455
// a null base address).
418
456
if (Fortran::semantics::IsOptional (sym)) {
419
- auto boxTy = box.getType ().cast <fir::BoxType >();
457
+ auto boxTy = box.getType ().cast <fir::BaseBoxType >();
420
458
auto eleTy = boxTy.getEleTy ();
421
459
if (!fir::isa_ref_type (eleTy))
422
460
eleTy = builder.getRefType (eleTy);
@@ -470,14 +508,10 @@ walkCaptureCategories(T visitor, Fortran::lower::AbstractConverter &converter,
470
508
ba.analyze (sym);
471
509
if (Fortran::semantics::IsAllocatableOrPointer (sym))
472
510
return CapturedAllocatableAndPointer::visit (visitor, converter, sym, ba);
473
- if (Fortran::semantics::IsPolymorphic (sym)) {
474
- if (ba.isArray () && !ba.lboundIsAllOnes ())
475
- TODO (converter.genLocation (sym.name ()),
476
- " polymorphic array with non default lower bound" );
477
- return CapturedPolymorphic::visit (visitor, converter, sym, ba);
478
- }
479
511
if (ba.isArray ())
480
512
return CapturedArrays::visit (visitor, converter, sym, ba);
513
+ if (Fortran::semantics::IsPolymorphic (sym))
514
+ return CapturedPolymorphicScalar::visit (visitor, converter, sym, ba);
481
515
if (ba.isChar ())
482
516
return CapturedCharacterScalars::visit (visitor, converter, sym, ba);
483
517
assert (ba.isTrivial () && " must be trivial scalar" );
0 commit comments