fortrangoingonforty/armfortas / 3e3048a

Browse files

Dispatch RANDOM_NUMBER on array harvest to array runtime variant

Authored by espadonne
Committed by mfwolffe
SHA
3e3048a34d6bacedfa0e959abbce0433b5398ff8
Parents
cd7682a
Tree
1de41dd

1 changed file

StatusFile+-
M src/ir/lower/intrinsic_sub.rs 52 11
src/ir/lower/intrinsic_sub.rsmodified
@@ -309,8 +309,16 @@ pub(crate) fn lower_intrinsic_subroutine(
309309
             true
310310
         }
311311
         "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).
312319
             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
314322
                 .and_then(|expr| {
315323
                     generic_actual_expr_type_info(
316324
                         expr,
@@ -319,17 +327,50 @@ pub(crate) fn lower_intrinsic_subroutine(
319327
                         Some(ctx.type_layouts),
320328
                     )
321329
                 })
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;
329366
                     }
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
+            };
333374
             b.call(
334375
                 FuncRef::External(runtime.into()),
335376
                 vec![harvest],