fortrangoingonforty/armfortas / e6f0227

Browse files

Fall back to actual's descriptor backing in proc-pointer call dispatch

Authored by espadonne
Committed by mfwolffe
SHA
e6f02276c774a717a16bf316c236a0eaf1d5cf77
Parents
f465834
Tree
d204062

2 changed files

StatusFile+-
M src/ir/lower/core.rs 17 0
M src/ir/lower/expr.rs 29 10
src/ir/lower/core.rsmodified
@@ -22316,6 +22316,23 @@ pub(super) fn local_uses_array_descriptor(info: &LocalInfo) -> bool {
2231622316
     info.allocatable || info.descriptor_arg
2231722317
 }
2231822318
 
22319
+/// True if `expr` is a simple Name reference to a local whose runtime
22320
+/// representation is a descriptor (assumed-shape, allocatable, pointer
22321
+/// array). Used as a fallback when an abstract-interface mask lookup
22322
+/// misses, so we still pass the descriptor instead of the data pointer.
22323
+pub(super) fn actual_is_descriptor_array(
22324
+    locals: &HashMap<String, LocalInfo>,
22325
+    expr: &crate::ast::expr::SpannedExpr,
22326
+) -> bool {
22327
+    if let Expr::Name { name } = &expr.node {
22328
+        if let Some(info) = locals.get(&name.to_lowercase()) {
22329
+            return local_uses_array_descriptor(info)
22330
+                || (!info.dims.is_empty() && info.descriptor_arg);
22331
+        }
22332
+    }
22333
+    false
22334
+}
22335
+
2231922336
 const DESC_CHAR_SLOT_TABLE: i32 = 1 << 3;
2232022337
 
2232122338
 pub(super) fn array_descriptor_addr(b: &mut FuncBuilder, info: &LocalInfo) -> ValueId {
src/ir/lower/expr.rsmodified
@@ -2025,15 +2025,24 @@ pub(crate) fn lower_expr_full(
20252025
                                     )
20262026
                                     .unwrap_or(IrType::Int(IntWidth::I32));
20272027
                                     // Honor the abstract-interface descriptor
2028
-                                    // mask when forwarding actuals.  Without
2029
-                                    // this, an assumed-shape dummy
2030
-                                    // (`real(8), intent(in) :: x(:)`) received
2031
-                                    // only a base data pointer in place of
2032
-                                    // the descriptor — the callee then read
2033
-                                    // dims/rank out of the array elements'
2034
-                                    // bytes and segfaulted (stdlib's iterative
2035
-                                    // solvers all dispatch dot_product through
2036
-                                    // a procedure-pointer field this way).
2028
+                                    // mask when forwarding actuals.  When an
2029
+                                    // actual is a descriptor-backed array
2030
+                                    // (assumed-shape dummy / allocatable /
2031
+                                    // pointer), pass its full descriptor —
2032
+                                    // the callee declared via the abstract
2033
+                                    // interface must take a descriptor for
2034
+                                    // assumed-shape parameters. Without this,
2035
+                                    // `lower_arg_by_ref_full` returned the
2036
+                                    // base data pointer (loaded out of the
2037
+                                    // descriptor) and the callee tried to
2038
+                                    // read rank/dims out of the array elements'
2039
+                                    // bytes — stdlib's iterative solvers all
2040
+                                    // dispatch dot_product/matvec through a
2041
+                                    // procedure-pointer field of a class arg
2042
+                                    // this way and SEGV'd deep inside
2043
+                                    // stdlib_dot_product_dp on an indirect
2044
+                                    // load whose target was the array's first
2045
+                                    // f64 (1.0 = bits 0x3ff0...).
20372046
                                     let callee_descriptor_args =
20382047
                                         first_procedure_lookup(&abi_lookup_keys, |k| {
20392048
                                             descriptor_params
@@ -2046,10 +2055,20 @@ pub(crate) fn lower_expr_full(
20462055
                                             e,
20472056
                                         ) = &arg.value
20482057
                                         {
2049
-                                            let wants_descriptor = callee_descriptor_args
2058
+                                            let mask_says_descriptor = callee_descriptor_args
20502059
                                                 .as_ref()
20512060
                                                 .map(|mask| mask.get(i).copied().unwrap_or(false))
20522061
                                                 .unwrap_or(false);
2062
+                                            // Fallback: if the lookup missed
2063
+                                            // (abstract iface not in
2064
+                                            // descriptor_params), inspect the
2065
+                                            // actual itself. A descriptor-
2066
+                                            // backed local must be passed by
2067
+                                            // descriptor regardless.
2068
+                                            let actual_is_descriptor_backed =
2069
+                                                actual_is_descriptor_array(locals, e);
2070
+                                            let wants_descriptor = mask_says_descriptor
2071
+                                                || actual_is_descriptor_backed;
20532072
                                             let v = if wants_descriptor {
20542073
                                                 lower_arg_descriptor(
20552074
                                                     b,