@@ -423,9 +423,45 @@ pub(crate) fn lower_stmt(b: &mut FuncBuilder, ctx: &mut LowerCtx, stmt: &Spanned |
| 423 | 423 | } else { |
| 424 | 424 | false |
| 425 | 425 | }; |
| 426 | + // Scalar-returning call assigned to a whole array is a |
| 427 | + // broadcast: `x = ieee_value(...)`, `x = sin(scalar_y)`, |
| 428 | + // user `x = scalar_func()`. The fall-through path |
| 429 | + // lowers the call as a scalar then treats the result as |
| 430 | + // a source descriptor — `load %x from non-pointer f32` |
| 431 | + // in the IR verifier, or afs_assign_allocatable with the |
| 432 | + // scalar value in the wrong arg register at runtime |
| 433 | + // (stdlib's pinv_s_operator hit this on the |
| 434 | + // `pinva = ieee_value(1.0, NaN)` error path). Route |
| 435 | + // through lower_array_assign so its bulk-fill plan |
| 436 | + // applies. Skip when args contain array refs (the |
| 437 | + // call really is producing an array result that other |
| 438 | + // arms above already handle) or when the callee is an |
| 439 | + // alloc-return user function (handled below). |
| 440 | + let callee_is_scalar_broadcast = local_is_array_like(&info) |
| 441 | + && !callee_is_local_array |
| 442 | + && !callee_is_elemental_array_intrinsic |
| 443 | + && !callee_is_transformational_intrinsic |
| 444 | + && call_args.iter().all(|arg| { |
| 445 | + if let crate::ast::expr::SectionSubscript::Element(e) |
| 446 | + = &arg.value |
| 447 | + { |
| 448 | + !expr_contains_array_refs(e, &ctx.locals) |
| 449 | + } else { |
| 450 | + false |
| 451 | + } |
| 452 | + }) |
| 453 | + && { |
| 454 | + if let Expr::Name { name: cname } = &callee.node { |
| 455 | + let lk = cname.to_lowercase(); |
| 456 | + !ctx.alloc_return_funcs.contains(&lk) |
| 457 | + } else { |
| 458 | + false |
| 459 | + } |
| 460 | + }; |
| 426 | 461 | if callee_is_local_array |
| 427 | 462 | || callee_is_elemental_array_intrinsic |
| 428 | 463 | || callee_is_transformational_intrinsic |
| 464 | + || callee_is_scalar_broadcast |
| 429 | 465 | { |
| 430 | 466 | lower_array_assign(b, ctx, name, &info, value); |
| 431 | 467 | return; |