@@ -3556,19 +3556,13 @@ class ArrayExprLowering {
3556
3556
case PassBy::Value: {
3557
3557
// True pass-by-value semantics.
3558
3558
PushSemantics (ConstituentSemantics::RefTransparent);
3559
- auto lambda = genarr (*expr);
3560
- operands[arg.firArgument ] = [=](IterSpace iters) {
3561
- return lambda (iters);
3562
- };
3559
+ operands[arg.firArgument ] = genarr (*expr);
3563
3560
} break ;
3564
3561
case PassBy::BaseAddressValueAttribute: {
3565
3562
// VALUE attribute or pass-by-reference to a copy semantics. (byval*)
3566
3563
if (isArray (*expr)) {
3567
3564
PushSemantics (ConstituentSemantics::ByValueArg);
3568
- auto lambda = genarr (*expr);
3569
- operands[arg.firArgument ] = [=](IterSpace iters) {
3570
- return lambda (iters);
3571
- };
3565
+ operands[arg.firArgument ] = genarr (*expr);
3572
3566
} else {
3573
3567
// Store scalar value in a temp to fulfill VALUE attribute.
3574
3568
auto val = fir::getBase (asScalar (*expr));
@@ -3582,25 +3576,39 @@ class ArrayExprLowering {
3582
3576
}
3583
3577
} break ;
3584
3578
case PassBy::BaseAddress: {
3579
+ if (isArray (*expr)) {
3580
+ PushSemantics (ConstituentSemantics::RefOpaque);
3581
+ operands[arg.firArgument ] = genarr (*expr);
3582
+ } else {
3583
+ auto exv = asScalarRef (*expr);
3584
+ operands[arg.firArgument ] = [=](IterSpace iters) { return exv; };
3585
+ }
3586
+ } break ;
3587
+ case PassBy::CharBoxValueAttribute: {
3585
3588
if (isArray (*expr)) {
3586
3589
PushSemantics (ConstituentSemantics::RefOpaque);
3587
3590
auto lambda = genarr (*expr);
3588
3591
operands[arg.firArgument ] = [=](IterSpace iters) {
3589
- return lambda (iters);
3592
+ return Fortran::lower::CharacterExprHelper{builder, loc}
3593
+ .createTempFrom (lambda (iters));
3590
3594
};
3591
3595
} else {
3592
- auto exv = asScalarRef (*expr);
3593
- operands[arg.firArgument ] = [=](IterSpace iters) { return exv; };
3596
+ Fortran::lower::CharacterExprHelper helper (builder, loc);
3597
+ auto argVal = helper.createTempFrom (asScalarRef (*expr));
3598
+ operands[arg.firArgument ] = [=](IterSpace iters) -> ExtValue {
3599
+ return argVal;
3600
+ };
3594
3601
}
3595
3602
} break ;
3596
- case PassBy::CharBoxValueAttribute:
3597
- TODO (loc, " CHARACTER, VALUE" );
3598
- break ;
3599
- case PassBy::BoxChar:
3600
- TODO (loc, " CHARACTER" );
3601
- break ;
3603
+ case PassBy::BoxChar: {
3604
+ PushSemantics (ConstituentSemantics::RefOpaque);
3605
+ operands[arg.firArgument ] = genarr (*expr);
3606
+ } break ;
3602
3607
case PassBy::AddressAndLength:
3603
- TODO (loc, " address and length argument" );
3608
+ // PassBy::AddressAndLength is only used for character results. Results
3609
+ // are not handled here.
3610
+ fir::emitFatalError (
3611
+ loc, " unexpected PassBy::AddressAndLength in elemental call" );
3604
3612
break ;
3605
3613
case PassBy::Box:
3606
3614
case PassBy::MutableBox:
@@ -3611,15 +3619,28 @@ class ArrayExprLowering {
3611
3619
3612
3620
if (caller.getIfIndirectCallSymbol ())
3613
3621
fir::emitFatalError (loc, " cannot be indirect call" );
3622
+
3623
+ // TODO: share logic with the scalar function calls when the result must be
3624
+ // allocated on the caller side.
3625
+ if (caller.callerAllocateResult ())
3626
+ TODO (loc, " elemental call requiring result allocation" );
3614
3627
auto funcSym = builder.getSymbolRefAttr (caller.getMangledName ());
3615
3628
auto resTys = caller.getFuncOp ().getType ().getResults ();
3616
3629
if (caller.getFuncOp ().getType ().getResults () !=
3617
3630
caller.genFunctionType ().getResults ())
3618
3631
fir::emitFatalError (loc, " type mismatch on declared function" );
3619
3632
return [=](IterSpace iters) -> ExtValue {
3620
3633
llvm::SmallVector<mlir::Value> args;
3621
- for (const auto &cc : operands)
3622
- args.push_back (fir::getBase (cc (iters)));
3634
+ for (const auto &cc : operands) {
3635
+ auto exv = cc (iters);
3636
+ auto arg = exv.match (
3637
+ [&](const fir::CharBoxValue &cb) -> mlir::Value {
3638
+ return Fortran::lower::CharacterExprHelper{builder, loc}
3639
+ .createEmbox (cb);
3640
+ },
3641
+ [&](const auto &) { return fir::getBase (exv); });
3642
+ args.push_back (arg);
3643
+ }
3623
3644
auto call = builder.create <fir::CallOp>(loc, resTys, funcSym, args);
3624
3645
return call.getResult (0 );
3625
3646
};
0 commit comments