@@ -309,8 +309,16 @@ pub(crate) fn lower_intrinsic_subroutine( |
| 309 | 309 | true |
| 310 | 310 | } |
| 311 | 311 | "random_number" => { |
| 312 | + // F2018 §16.9.171: RANDOM_NUMBER(harvest) accepts both |
| 313 | + // scalar and array harvest. The scalar runtime fills only |
| 314 | + // one element; routing array actuals to it left N-1 slots |
| 315 | + // as stack garbage, which surfaced as denormal/NaN values |
| 316 | + // throughout stdlib examples (e.g. sparse_spmv: count() on |
| 317 | + // the resulting matrix returned 1 instead of m*n, malloc |
| 318 | + // sized COO%index(2,1), and the next assign ran past dim 0). |
| 312 | 319 | let harvest = nth_arg_ref(b, ctx, args, 0); |
| 313 | | - let runtime = nth_arg_expr(args, 0) |
| 320 | + let harvest_expr = nth_arg_expr(args, 0); |
| 321 | + let kind_is_f32 = harvest_expr |
| 314 | 322 | .and_then(|expr| { |
| 315 | 323 | generic_actual_expr_type_info( |
| 316 | 324 | expr, |
@@ -319,17 +327,50 @@ pub(crate) fn lower_intrinsic_subroutine( |
| 319 | 327 | Some(ctx.type_layouts), |
| 320 | 328 | ) |
| 321 | 329 | }) |
| 322 | | - .map(|ty| match ty { |
| 323 | | - crate::sema::symtab::TypeInfo::Real { kind: Some(kind) } if kind <= 4 => { |
| 324 | | - "afs_random_number_f32" |
| 325 | | - } |
| 326 | | - crate::sema::symtab::TypeInfo::Real { .. } |
| 327 | | - | crate::sema::symtab::TypeInfo::DoublePrecision => { |
| 328 | | - "afs_random_number_f64" |
| 330 | + .map(|ty| matches!( |
| 331 | + ty, |
| 332 | + crate::sema::symtab::TypeInfo::Real { kind: Some(k) } if k <= 4 |
| 333 | + )) |
| 334 | + .unwrap_or(false); |
| 335 | + let is_array = harvest_expr |
| 336 | + .map(|e| expr_returns_array(e, &ctx.locals, ctx.st)) |
| 337 | + .unwrap_or(false); |
| 338 | + if is_array { |
| 339 | + if let Some(expr) = harvest_expr { |
| 340 | + if let Some((desc, _elem_ty)) = lower_array_expr_descriptor( |
| 341 | + b, |
| 342 | + &ctx.locals, |
| 343 | + expr, |
| 344 | + ctx.st, |
| 345 | + Some(ctx.type_layouts), |
| 346 | + Some(ctx.internal_funcs), |
| 347 | + Some(ctx.contained_host_refs), |
| 348 | + Some(ctx.descriptor_params), |
| 349 | + ) { |
| 350 | + let n = b.call( |
| 351 | + FuncRef::External("afs_array_size".into()), |
| 352 | + vec![desc], |
| 353 | + IrType::Int(IntWidth::I64), |
| 354 | + ); |
| 355 | + let runtime = if kind_is_f32 { |
| 356 | + "afs_random_number_array_f32" |
| 357 | + } else { |
| 358 | + "afs_random_number_array_f64" |
| 359 | + }; |
| 360 | + b.call( |
| 361 | + FuncRef::External(runtime.into()), |
| 362 | + vec![harvest, n], |
| 363 | + IrType::Void, |
| 364 | + ); |
| 365 | + return true; |
| 329 | 366 | } |
| 330 | | - _ => "afs_random_number_f64", |
| 331 | | - }) |
| 332 | | - .unwrap_or("afs_random_number_f64"); |
| 367 | + } |
| 368 | + } |
| 369 | + let runtime = if kind_is_f32 { |
| 370 | + "afs_random_number_f32" |
| 371 | + } else { |
| 372 | + "afs_random_number_f64" |
| 373 | + }; |
| 333 | 374 | b.call( |
| 334 | 375 | FuncRef::External(runtime.into()), |
| 335 | 376 | vec![harvest], |