@@ -406,6 +406,82 @@ fir::ExtendedValue Fortran::lower::genCallOpAndResult(
406
406
return callResult;
407
407
}
408
408
409
+ static hlfir::EntityWithAttributes genStmtFunctionRef (
410
+ mlir::Location loc, Fortran::lower::AbstractConverter &converter,
411
+ Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
412
+ const Fortran::evaluate::ProcedureRef &procRef) {
413
+ const Fortran::semantics::Symbol *symbol = procRef.proc ().GetSymbol ();
414
+ assert (symbol && " expected symbol in ProcedureRef of statement functions" );
415
+ const auto &details = symbol->get <Fortran::semantics::SubprogramDetails>();
416
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
417
+
418
+ // Statement functions have their own scope, we just need to associate
419
+ // the dummy symbols to argument expressions. There are no
420
+ // optional/alternate return arguments. Statement functions cannot be
421
+ // recursive (directly or indirectly) so it is safe to add dummy symbols to
422
+ // the local map here.
423
+ symMap.pushScope ();
424
+ llvm::SmallVector<hlfir::AssociateOp> exprAssociations;
425
+ for (auto [arg, bind] : llvm::zip (details.dummyArgs (), procRef.arguments ())) {
426
+ assert (arg && " alternate return in statement function" );
427
+ assert (bind && " optional argument in statement function" );
428
+ const auto *expr = bind->UnwrapExpr ();
429
+ // TODO: assumed type in statement function, that surprisingly seems
430
+ // allowed, probably because nobody thought of restricting this usage.
431
+ // gfortran/ifort compiles this.
432
+ assert (expr && " assumed type used as statement function argument" );
433
+ // As per Fortran 2018 C1580, statement function arguments can only be
434
+ // scalars.
435
+ // The only care is to use the dummy character explicit length if any
436
+ // instead of the actual argument length (that can be bigger).
437
+ hlfir::EntityWithAttributes loweredArg = Fortran::lower::convertExprToHLFIR (
438
+ loc, converter, *expr, symMap, stmtCtx);
439
+ fir::FortranVariableOpInterface variableIface = loweredArg.getIfVariable ();
440
+ if (!variableIface) {
441
+ // So far only FortranVariableOpInterface can be mapped to symbols.
442
+ // Create an hlfir.associate to create a variable from a potential
443
+ // value argument.
444
+ mlir::Type argType = converter.genType (*arg);
445
+ auto associate = hlfir::genAssociateExpr (
446
+ loc, builder, loweredArg, argType, toStringRef (arg->name ()));
447
+ exprAssociations.push_back (associate);
448
+ variableIface = associate;
449
+ }
450
+ const Fortran::semantics::DeclTypeSpec *type = arg->GetType ();
451
+ if (type &&
452
+ type->category () == Fortran::semantics::DeclTypeSpec::Character) {
453
+ // Instantiate character as if it was a normal dummy argument so that the
454
+ // statement function dummy character length is applied and dealt with
455
+ // correctly.
456
+ symMap.addSymbol (*arg, variableIface.getBase ());
457
+ Fortran::lower::mapSymbolAttributes (converter, *arg, symMap, stmtCtx);
458
+ } else {
459
+ // No need to create an extra hlfir.declare otherwise for
460
+ // numerical and logical scalar dummies.
461
+ symMap.addVariableDefinition (*arg, variableIface);
462
+ }
463
+ }
464
+
465
+ // Explicitly map statement function host associated symbols to their
466
+ // parent scope lowered symbol box.
467
+ for (const Fortran::semantics::SymbolRef &sym :
468
+ Fortran::evaluate::CollectSymbols (*details.stmtFunction ()))
469
+ if (const auto *details =
470
+ sym->detailsIf <Fortran::semantics::HostAssocDetails>())
471
+ converter.copySymbolBinding (details->symbol (), sym);
472
+
473
+ hlfir::Entity result = Fortran::lower::convertExprToHLFIR (
474
+ loc, converter, details.stmtFunction ().value (), symMap, stmtCtx);
475
+ symMap.popScope ();
476
+ // The result must not be a variable.
477
+ result = hlfir::loadTrivialScalar (loc, builder, result);
478
+ if (result.isVariable ())
479
+ result = hlfir::Entity{builder.create <hlfir::AsExprOp>(loc, result)};
480
+ for (auto associate : exprAssociations)
481
+ builder.create <hlfir::EndAssociateOp>(loc, associate);
482
+ return hlfir::EntityWithAttributes{result};
483
+ }
484
+
409
485
// / Is this a call to an elemental procedure with at least one array argument?
410
486
static bool
411
487
isElementalProcWithArrayArgs (const Fortran::evaluate::ProcedureRef &procRef) {
@@ -454,7 +530,7 @@ class CallBuilder {
454
530
return genIntrinsicRef (procRef, resultType, *specific);
455
531
}
456
532
if (isStatementFunctionCall (procRef))
457
- TODO (loc, " lowering Statement function call to HLFIR " );
533
+ return genStmtFunctionRef (loc, converter, symMap, stmtCtx, procRef );
458
534
459
535
Fortran::lower::CallerInterface caller (procRef, converter);
460
536
mlir::FunctionType callSiteType = caller.genFunctionType ();
0 commit comments