fortrangoingonforty/armfortas / ecb2c7f

Browse files

Allocate same-shape descriptor in elemental call path; dispatch IEEE intrinsics (port from trunk 4e04973)

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
ecb2c7f817cadfbf178741f3d390165b0ade5a7e
Parents
b240b7b
Tree
d23646a

1 changed file

StatusFile+-
M src/ir/lower/core.rs 31 13
src/ir/lower/core.rsmodified
@@ -23721,6 +23721,16 @@ pub(super) fn is_elemental_math_intrinsic(name: &str) -> bool {
2372123721
         | "logical" | "conjg" | "aimag" | "dimag"
2372223722
         | "mod" | "modulo" | "sign" | "dim" | "max" | "min"
2372323723
         | "ichar" | "iachar" | "achar" | "char"
23724
+        // F2018 §17.11 IEEE elemental intrinsics from `ieee_arithmetic`.
23725
+        // Without this dispatch, `ieee_is_nan(arr)` falls through to the
23726
+        // scalar `lower_intrinsic` arm which emits `fcmp ne desc, desc`
23727
+        // on the array's descriptor pointer — garbage that downstream
23728
+        // either rejects (IR verifier, "fcmp on non-float") or lets
23729
+        // through silently to corrupt the next allocaed slot.  stdlib
23730
+        // hits this in the rank-N branch of `median_all_*` (`if any(
23731
+        // ieee_is_nan(x))`) for `median`, `cov`, `sort_*`, etc.
23732
+        | "ieee_is_nan" | "ieee_is_finite" | "ieee_is_negative"
23733
+        | "ieee_is_normal" | "ieee_signbit" | "ieee_value"
2372423734
         // F2018 §16.9 character elementals — scalar form is already
2372523735
         // wired in lower_intrinsic; flagging them here lets reductions
2372623736
         // like `sum(len_trim(strs))` materialize the per-element
@@ -24190,22 +24200,30 @@ pub(super) fn lower_rank1_elemental_call_descriptor(
2419024200
         | crate::sema::symtab::TypeInfo::Class(_) => return None,
2419124201
         other => (type_info_to_ir_type(&other), None),
2419224202
     };
24193
-    let one_dim = b.const_i32(1);
24194
-    let lower = b.call(
24195
-        FuncRef::External("afs_array_lbound".into()),
24196
-        vec![control_desc, one_dim],
24197
-        IrType::Int(IntWidth::I64),
24198
-    );
24199
-    let upper = b.call(
24200
-        FuncRef::External("afs_array_ubound".into()),
24201
-        vec![control_desc, one_dim],
24202
-        IrType::Int(IntWidth::I64),
24203
-    );
24203
+    // F2018 §16.9: an elemental call yields a result of the SAME SHAPE
24204
+    // (rank + per-dim extents) as the array actuals. The previous
24205
+    // rank-1-only allocator collapsed rank-N actuals to dim 1's
24206
+    // extent, so a `(2,3)` source produced a 2-element mask and the
24207
+    // remaining four elements wrote past the buffer.  Use the
24208
+    // same-shape allocator so callees see the full rank-N descriptor.
2420424209
     let elem_size = result_char_len
2420524210
         .map(|len| b.const_i64(len))
2420624211
         .unwrap_or_else(|| b.const_i64(ir_scalar_byte_size(&result_elem_ty)));
24207
-    let result_desc =
24208
-        allocate_rank1_array_descriptor_with_runtime_bounds(b, lower, upper, elem_size);
24212
+    let result_desc = b.alloca(IrType::Array(Box::new(IrType::Int(IntWidth::I8)), 384));
24213
+    let zero32_for_alloc = b.const_i32(0);
24214
+    let sz384 = b.const_i64(384);
24215
+    b.call(
24216
+        FuncRef::External("memset".into()),
24217
+        vec![result_desc, zero32_for_alloc, sz384],
24218
+        IrType::Ptr(Box::new(IrType::Int(IntWidth::I8))),
24219
+    );
24220
+    let stat_for_alloc = b.alloca(IrType::Int(IntWidth::I32));
24221
+    b.store(zero32_for_alloc, stat_for_alloc);
24222
+    b.call(
24223
+        FuncRef::External("afs_allocate_like_with_elem_size".into()),
24224
+        vec![result_desc, control_desc, elem_size, stat_for_alloc],
24225
+        IrType::Void,
24226
+    );
2420924227
 
2421024228
     let n = b.call(
2421124229
         FuncRef::External("afs_array_size".into()),