fortrangoingonforty/armfortas / 2e84df1

Browse files

Fold bit_size at compile time with named-kind suffixes

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
2e84df1f1eeea709e8ae9f80a28bccc032d133a3
Parents
6eb3594
Tree
e9e0ff2

1 changed file

StatusFile+-
M src/ir/lower.rs 52 0
src/ir/lower.rsmodified
@@ -6023,6 +6023,58 @@ fn eval_const_scalar(
60236023
                             None
60246024
                         }
60256025
                     }
6026
+                    "bit_size" => {
6027
+                        // F2018 §16.9.31: BIT_SIZE(I) returns the number of
6028
+                        // bits in the model integer for argument I. Folds at
6029
+                        // compile time when the argument has a known kind.
6030
+                        // Without this, module-level
6031
+                        // `integer, parameter :: K = bit_size(1_8)`
6032
+                        // initializers stored zero in .data — the linked
6033
+                        // binary then read K=0 inside any function that
6034
+                        // imported the module, breaking F2018 §13.7
6035
+                        // semantics. stdlib_random's MAX_INT_BIT_SIZE was
6036
+                        // the failing repro.
6037
+                        let arg = args.first()?;
6038
+                        let crate::ast::expr::SectionSubscript::Element(e) = &arg.value else {
6039
+                            return None;
6040
+                        };
6041
+                        let kind = match &e.node {
6042
+                            Expr::IntegerLiteral { kind, .. } => match kind.as_deref() {
6043
+                                None => 4,
6044
+                                Some(s) => match s.parse::<i64>().ok() {
6045
+                                    Some(k) => k,
6046
+                                    None => {
6047
+                                        let key = s.to_lowercase();
6048
+                                        match key.as_str() {
6049
+                                            "int8" => 1,
6050
+                                            "int16" => 2,
6051
+                                            "int32" => 4,
6052
+                                            "int64" => 8,
6053
+                                            _ => match param_consts.get(&key).copied() {
6054
+                                                Some(ConstScalar::Int(v)) => v as i64,
6055
+                                                _ => return None,
6056
+                                            },
6057
+                                        }
6058
+                                    }
6059
+                                },
6060
+                            },
6061
+                            Expr::Name { name } => {
6062
+                                let key = name.to_lowercase();
6063
+                                match key.as_str() {
6064
+                                    "int8" => 1,
6065
+                                    "int16" => 2,
6066
+                                    "int32" => 4,
6067
+                                    "int64" => 8,
6068
+                                    _ => match param_consts.get(&key).copied() {
6069
+                                        Some(ConstScalar::Int(v)) => v as i64,
6070
+                                        _ => return None,
6071
+                                    },
6072
+                                }
6073
+                            }
6074
+                            _ => 4,
6075
+                        };
6076
+                        Some(ConstScalar::Int((kind as i128) * 8))
6077
+                    }
60266078
                     "selected_real_kind" => {
60276079
                         if let Some(ConstScalar::Int(p)) = first_arg {
60286080
                             let p = p as i64;