@@ -310,21 +310,22 @@ bool Fortran::lower::CallerInterface::verifyActualInputs() const {
310
310
return true ;
311
311
}
312
312
313
- void Fortran::lower::CallerInterface::walkResultLengths (
314
- ExprVisitor visitor) const {
315
- assert (characteristic && " characteristic was not computed" );
316
- const Fortran::evaluate::characteristics::FunctionResult &result =
317
- characteristic->functionResult .value ();
318
- const Fortran::evaluate::characteristics::TypeAndShape *typeAndShape =
319
- result.GetTypeAndShape ();
320
- assert (typeAndShape && " no result type" );
321
- Fortran::evaluate::DynamicType dynamicType = typeAndShape->type ();
322
- // Visit result length specification expressions that are explicit.
313
+ mlir::Value
314
+ Fortran::lower::CallerInterface::getInput (const PassedEntity &passedEntity) {
315
+ return actualInputs[passedEntity.firArgument ];
316
+ }
317
+
318
+ static void walkLengths (
319
+ const Fortran::evaluate::characteristics::TypeAndShape &typeAndShape,
320
+ const Fortran::lower::CallerInterface::ExprVisitor &visitor,
321
+ Fortran::lower::AbstractConverter &converter) {
322
+ Fortran::evaluate::DynamicType dynamicType = typeAndShape.type ();
323
+ // Visit length specification expressions that are explicit.
323
324
if (dynamicType.category () == Fortran::common::TypeCategory::Character) {
324
325
if (std::optional<Fortran::evaluate::ExtentExpr> length =
325
326
dynamicType.GetCharLength ())
326
- visitor (toEvExpr (*length));
327
- } else if (dynamicType.category () == common::TypeCategory::Derived &&
327
+ visitor (toEvExpr (*length), /* assumedSize= */ false );
328
+ } else if (dynamicType.category () == Fortran:: common::TypeCategory::Derived &&
328
329
!dynamicType.IsUnlimitedPolymorphic ()) {
329
330
const Fortran::semantics::DerivedTypeSpec &derivedTypeSpec =
330
331
dynamicType.GetDerivedTypeSpec ();
@@ -334,32 +335,61 @@ void Fortran::lower::CallerInterface::walkResultLengths(
334
335
}
335
336
}
336
337
338
+ void Fortran::lower::CallerInterface::walkResultLengths (
339
+ const ExprVisitor &visitor) const {
340
+ assert (characteristic && " characteristic was not computed" );
341
+ const Fortran::evaluate::characteristics::FunctionResult &result =
342
+ characteristic->functionResult .value ();
343
+ const Fortran::evaluate::characteristics::TypeAndShape *typeAndShape =
344
+ result.GetTypeAndShape ();
345
+ assert (typeAndShape && " no result type" );
346
+ return walkLengths (*typeAndShape, visitor, converter);
347
+ }
348
+
349
+ void Fortran::lower::CallerInterface::walkDummyArgumentLengths (
350
+ const PassedEntity &passedEntity, const ExprVisitor &visitor) const {
351
+ if (!passedEntity.characteristics )
352
+ return ;
353
+ if (const auto *dummy =
354
+ std::get_if<Fortran::evaluate::characteristics::DummyDataObject>(
355
+ &passedEntity.characteristics ->u ))
356
+ walkLengths (dummy->type , visitor, converter);
357
+ }
358
+
337
359
// Compute extent expr from shapeSpec of an explicit shape.
338
- // TODO: Allow evaluate shape analysis to work in a mode where it disregards
339
- // the non-constant aspects when building the shape to avoid having this here.
340
360
static Fortran::evaluate::ExtentExpr
341
361
getExtentExpr (const Fortran::semantics::ShapeSpec &shapeSpec) {
362
+ if (shapeSpec.ubound ().isStar ())
363
+ // F'2023 18.5.3 point 5.
364
+ return Fortran::evaluate::ExtentExpr{-1 };
342
365
const auto &ubound = shapeSpec.ubound ().GetExplicit ();
343
366
const auto &lbound = shapeSpec.lbound ().GetExplicit ();
344
367
assert (lbound && ubound && " shape must be explicit" );
345
368
return Fortran::common::Clone (*ubound) - Fortran::common::Clone (*lbound) +
346
369
Fortran::evaluate::ExtentExpr{1 };
347
370
}
348
371
372
+ static void
373
+ walkExtents (const Fortran::semantics::Symbol &symbol,
374
+ const Fortran::lower::CallerInterface::ExprVisitor &visitor) {
375
+ if (const auto *objectDetails =
376
+ symbol.detailsIf <Fortran::semantics::ObjectEntityDetails>())
377
+ if (objectDetails->shape ().IsExplicitShape () ||
378
+ Fortran::semantics::IsAssumedSizeArray (symbol))
379
+ for (const Fortran::semantics::ShapeSpec &shapeSpec :
380
+ objectDetails->shape ())
381
+ visitor (Fortran::evaluate::AsGenericExpr (getExtentExpr (shapeSpec)),
382
+ /* assumedSize=*/ shapeSpec.ubound ().isStar ());
383
+ }
384
+
349
385
void Fortran::lower::CallerInterface::walkResultExtents (
350
- ExprVisitor visitor) const {
386
+ const ExprVisitor & visitor) const {
351
387
// Walk directly the result symbol shape (the characteristic shape may contain
352
388
// descriptor inquiries to it that would fail to lower on the caller side).
353
389
const Fortran::semantics::SubprogramDetails *interfaceDetails =
354
390
getInterfaceDetails ();
355
391
if (interfaceDetails) {
356
- const Fortran::semantics::Symbol &result = interfaceDetails->result ();
357
- if (const auto *objectDetails =
358
- result.detailsIf <Fortran::semantics::ObjectEntityDetails>())
359
- if (objectDetails->shape ().IsExplicitShape ())
360
- for (const Fortran::semantics::ShapeSpec &shapeSpec :
361
- objectDetails->shape ())
362
- visitor (Fortran::evaluate::AsGenericExpr (getExtentExpr (shapeSpec)));
392
+ walkExtents (interfaceDetails->result (), visitor);
363
393
} else {
364
394
if (procRef.Rank () != 0 )
365
395
fir::emitFatalError (
@@ -368,22 +398,44 @@ void Fortran::lower::CallerInterface::walkResultExtents(
368
398
}
369
399
}
370
400
371
- bool Fortran::lower::CallerInterface::mustMapInterfaceSymbols () const {
401
+ void Fortran::lower::CallerInterface::walkDummyArgumentExtents (
402
+ const PassedEntity &passedEntity, const ExprVisitor &visitor) const {
403
+ const Fortran::semantics::SubprogramDetails *interfaceDetails =
404
+ getInterfaceDetails ();
405
+ if (!interfaceDetails)
406
+ return ;
407
+ const Fortran::semantics::Symbol *dummy = getDummySymbol (passedEntity);
408
+ assert (dummy && " dummy symbol was not set" );
409
+ walkExtents (*dummy, visitor);
410
+ }
411
+
412
+ bool Fortran::lower::CallerInterface::mustMapInterfaceSymbolsForResult () const {
372
413
assert (characteristic && " characteristic was not computed" );
373
414
const std::optional<Fortran::evaluate::characteristics::FunctionResult>
374
415
&result = characteristic->functionResult ;
375
416
if (!result || result->CanBeReturnedViaImplicitInterface () ||
376
417
!getInterfaceDetails () || result->IsProcedurePointer ())
377
418
return false ;
378
419
bool allResultSpecExprConstant = true ;
379
- auto visitor = [&](const Fortran::lower::SomeExpr &e) {
420
+ auto visitor = [&](const Fortran::lower::SomeExpr &e, bool ) {
380
421
allResultSpecExprConstant &= Fortran::evaluate::IsConstantExpr (e);
381
422
};
382
423
walkResultLengths (visitor);
383
424
walkResultExtents (visitor);
384
425
return !allResultSpecExprConstant;
385
426
}
386
427
428
+ bool Fortran::lower::CallerInterface::mustMapInterfaceSymbolsForDummyArgument (
429
+ const PassedEntity &arg) const {
430
+ bool allResultSpecExprConstant = true ;
431
+ auto visitor = [&](const Fortran::lower::SomeExpr &e, bool ) {
432
+ allResultSpecExprConstant &= Fortran::evaluate::IsConstantExpr (e);
433
+ };
434
+ walkDummyArgumentLengths (arg, visitor);
435
+ walkDummyArgumentExtents (arg, visitor);
436
+ return !allResultSpecExprConstant;
437
+ }
438
+
387
439
mlir::Value Fortran::lower::CallerInterface::getArgumentValue (
388
440
const semantics::Symbol &sym) const {
389
441
mlir::Location loc = converter.getCurrentLocation ();
@@ -401,13 +453,36 @@ mlir::Value Fortran::lower::CallerInterface::getArgumentValue(
401
453
return actualInputs[mlirArgIndex];
402
454
}
403
455
456
+ const Fortran::semantics::Symbol *
457
+ Fortran::lower::CallerInterface::getDummySymbol (
458
+ const PassedEntity &passedEntity) const {
459
+ const Fortran::semantics::SubprogramDetails *ifaceDetails =
460
+ getInterfaceDetails ();
461
+ if (!ifaceDetails)
462
+ return nullptr ;
463
+ std::size_t argPosition = 0 ;
464
+ for (const auto &arg : getPassedArguments ()) {
465
+ if (&arg == &passedEntity)
466
+ break ;
467
+ ++argPosition;
468
+ }
469
+ if (argPosition >= ifaceDetails->dummyArgs ().size ())
470
+ return nullptr ;
471
+ return ifaceDetails->dummyArgs ()[argPosition];
472
+ }
473
+
404
474
mlir::Type Fortran::lower::CallerInterface::getResultStorageType () const {
405
475
if (passedResult)
406
476
return fir::dyn_cast_ptrEleTy (inputs[passedResult->firArgument ].type );
407
477
assert (saveResult && !outputs.empty ());
408
478
return outputs[0 ].type ;
409
479
}
410
480
481
+ mlir::Type Fortran::lower::CallerInterface::getDummyArgumentType (
482
+ const PassedEntity &passedEntity) const {
483
+ return inputs[passedEntity.firArgument ].type ;
484
+ }
485
+
411
486
const Fortran::semantics::Symbol &
412
487
Fortran::lower::CallerInterface::getResultSymbol () const {
413
488
mlir::Location loc = converter.getCurrentLocation ();
@@ -1387,6 +1462,17 @@ bool Fortran::lower::CallInterface<
1387
1462
return Fortran::semantics::IsFinalizable (*derived);
1388
1463
}
1389
1464
1465
+ template <typename T>
1466
+ bool Fortran::lower::CallInterface<
1467
+ T>::PassedEntity::isSequenceAssociatedDescriptor() const {
1468
+ if (!characteristics || passBy != PassEntityBy::Box)
1469
+ return false ;
1470
+ const auto *dummy =
1471
+ std::get_if<Fortran::evaluate::characteristics::DummyDataObject>(
1472
+ &characteristics->u );
1473
+ return dummy && dummy->type .CanBeSequenceAssociated ();
1474
+ }
1475
+
1390
1476
template <typename T>
1391
1477
void Fortran::lower::CallInterface<T>::determineInterface(
1392
1478
bool isImplicit,
0 commit comments