@@ -257,6 +257,14 @@ fn wideops_table() -> WideOpsTable {
257257thread_local ! {
258258 static WIDE_TMP_CTR : Cell <usize > = const { Cell :: new( 0 ) } ;
259259}
260+ /// 64-bit word count for a `native_bytes` size class — the length of the
261+ /// `uint64_t _wN[]` scratch that holds a value of that size. Must round UP:
262+ /// `native_bytes` returns 4 for widths <= 32, and a truncating `/ 8` would
263+ /// declare a zero-length array whose word-0 store is out of bounds.
264+ fn wide_words ( nb : usize ) -> usize {
265+ nb. div_ceil ( 8 )
266+ }
267+
260268/// Fresh `_wN` index, unique within a function emit (monotonic; reset by
261269/// `emit_function` / `emit_event_function` so emitted source is deterministic).
262270fn next_wide_tmp ( ) -> usize {
@@ -761,7 +769,7 @@ fn emit_wide_const(
761769 let ( width, digits) : ( usize , Vec < u64 > ) = match value {
762770 Value :: U64 ( x) if x. width == 0 => {
763771 let target = ctx_width. max ( proto_width) ;
764- let count = native_bytes ( target) / 8 ;
772+ let count = wide_words ( native_bytes ( target) ) ;
765773 let d = if x. payload != 0 {
766774 vec ! [ u64 :: MAX ; count]
767775 } else {
@@ -773,7 +781,7 @@ fn emit_wide_const(
773781 Value :: BigUint ( x) => ( proto_width, x. payload . to_u64_digits ( ) ) ,
774782 } ;
775783 let nb = native_bytes ( width) ;
776- let nw = nb / 8 ;
784+ let nw = wide_words ( nb ) ;
777785 let t = next_wide_tmp ( ) ;
778786 let mut init = String :: new ( ) ;
779787 for i in 0 ..nw {
@@ -833,7 +841,7 @@ fn emit_wide_expr(expr: &ProtoExpression, pre: &mut String) -> Option<WideRef> {
833841 let idx = emit_expr ( & dyn_sel. index_expr ) ?;
834842 let max_idx = dyn_sel. num_elements - 1 ;
835843 let src_nb = native_bytes ( * var_full_width) ;
836- let src_nw = src_nb / 8 ;
844+ let src_nw = wide_words ( src_nb) ;
837845 let t = next_wide_tmp ( ) ;
838846 pre. push_str ( & format ! (
839847 "uint64_t _w{t}[{src_nw}]; \
@@ -861,7 +869,7 @@ fn emit_wide_expr(expr: &ProtoExpression, pre: &mut String) -> Option<WideRef> {
861869 return None ;
862870 }
863871 let src_nb = native_bytes ( * var_full_width) ;
864- let src_nw = src_nb / 8 ;
872+ let src_nw = wide_words ( src_nb) ;
865873 let res_nb = native_bytes ( nbits) ;
866874 let t = next_wide_tmp ( ) ;
867875 pre. push_str ( & format ! (
@@ -964,7 +972,7 @@ fn emit_wide_operand(
964972 target_nb : usize ,
965973 pre : & mut String ,
966974) -> Option < WideRef > {
967- let tnw = target_nb / 8 ;
975+ let tnw = wide_words ( target_nb) ;
968976 // A wide-pointer NODE whose wide emit has no arm may still be scalar-
969977 // emittable when its RESULT is ≤128 bits (e.g. a dynamic select on a
970978 // >128-bit var, which reads a 64..128-bit element into a register):
@@ -1053,7 +1061,7 @@ fn emit_wide_rhs_field(
10531061 return None ;
10541062 }
10551063 let src_nb = native_bytes ( src_w) ;
1056- let src_nw = src_nb / 8 ;
1064+ let src_nw = wide_words ( src_nb) ;
10571065 let r = emit_wide_operand ( expr, src_nb, pre) ?;
10581066 let fld = next_wide_tmp ( ) ;
10591067 pre. push_str ( & format ! (
@@ -1122,7 +1130,7 @@ fn emit_wide_operand_signed(
11221130 let w = expr. width ( ) ;
11231131 if signed && w > 0 && w < target_nb * 8 {
11241132 let t = next_wide_tmp ( ) ;
1125- let tnw = target_nb / 8 ;
1133+ let tnw = wide_words ( target_nb) ;
11261134 pre. push_str ( & format ! (
11271135 "uint64_t _w{t}[{tnw}]; vw_sext_copy((uint8_t*)_w{t}, {src}, {w}u, {target_nb}u); " ,
11281136 src = r. addr,
@@ -1229,7 +1237,7 @@ fn emit_wide_binary(
12291237 let width = expr_context. width ;
12301238 let result_nb = native_bytes ( width) ;
12311239 let op_nb = native_bytes ( width. max ( x. width ( ) ) . max ( y. width ( ) ) ) ;
1232- let nw = op_nb / 8 ;
1240+ let nw = wide_words ( op_nb) ;
12331241 let mask_pack = wpack ( op_nb, width) ;
12341242 match op {
12351243 Op :: BitAnd | Op :: BitOr | Op :: BitXor | Op :: BitXnor | Op :: Add | Op :: Sub | Op :: Mul => {
@@ -1307,7 +1315,7 @@ fn emit_wide_binary(
13071315/// mask after the op; identity is unmasked.
13081316fn emit_wide_unary ( op : Op , x : & ProtoExpression , width : usize , pre : & mut String ) -> Option < WideRef > {
13091317 let nb = native_bytes ( width) ;
1310- let nw = nb / 8 ;
1318+ let nw = wide_words ( nb ) ;
13111319 let x_ref = emit_wide_operand ( x, nb, pre) ?;
13121320 match op {
13131321 Op :: Add => Some ( WideRef {
@@ -1373,7 +1381,7 @@ fn emit_wide_ternary(
13731381 pre : & mut String ,
13741382) -> Option < WideRef > {
13751383 let nb = native_bytes ( width) ;
1376- let nw = nb / 8 ;
1384+ let nw = wide_words ( nb ) ;
13771385 let c = emit_expr ( cond) ?;
13781386 let mut t_ref = emit_wide_operand ( true_expr, nb, pre) ?;
13791387 let mut f_ref = emit_wide_operand ( false_expr, nb, pre) ?;
@@ -1435,7 +1443,7 @@ fn emit_wide_concat(
14351443 pre : & mut String ,
14361444) -> Option < WideRef > {
14371445 let nb = native_bytes ( width) ;
1438- let nw = nb / 8 ;
1446+ let nw = wide_words ( nb ) ;
14391447 let acc = next_wide_tmp ( ) ;
14401448 pre. push_str ( & format ! ( "uint64_t _w{acc}[{nw}] = {{0}}; " ) ) ;
14411449
@@ -2283,7 +2291,7 @@ fn emit_event_ff_assign_wide(a: &ProtoAssignStatement) -> Option<String> {
22832291 }
22842292 let packed = dst_raw == cur_off;
22852293 let nb = native_bytes ( a. dst_width ) ;
2286- let nw = nb / 8 ;
2294+ let nw = wide_words ( nb ) ;
22872295 let mut pre = String :: new ( ) ;
22882296 // Build the RHS to `nb` bytes, then copy into a fresh scratch and mask it
22892297 // there (the canonical FF slot must not be clobbered before commit; the
@@ -2549,7 +2557,7 @@ fn emit_event_ff_assign_dynamic_wide(a: &ProtoAssignDynamicStatement) -> Option<
25492557 return None ;
25502558 }
25512559 let nb = native_bytes ( a. dst_width ) ;
2552- let nw = nb / 8 ;
2560+ let nw = wide_words ( nb ) ;
25532561 let max_idx = a. dst_num_elements . saturating_sub ( 1 ) ;
25542562 let idx = emit_expr ( & a. dst_index_expr ) ?;
25552563 let mut pre = String :: new ( ) ;
@@ -3560,7 +3568,7 @@ pub fn emit_stmt(stmt: &ProtoStatement) -> Option<String> {
35603568 return None ;
35613569 }
35623570 let nb = native_bytes ( a. dst_width ) ;
3563- let nw = nb / 8 ;
3571+ let nw = wide_words ( nb ) ;
35643572 if win > nb * 8 {
35653573 return None ;
35663574 }
@@ -3629,7 +3637,7 @@ pub fn emit_stmt(stmt: &ProtoStatement) -> Option<String> {
36293637 return None ;
36303638 }
36313639 let nb = native_bytes ( a. dst_width ) ;
3632- let nw = nb / 8 ;
3640+ let nw = wide_words ( nb ) ;
36333641 let dst = format ! ( "(uint8_t*)(comb_values + {store_off:#x})" ) ;
36343642 let dmask = wpack ( nb, a. dst_width ) ;
36353643 // Non-foldable rhs_select (rhs isn't a plain variable):
@@ -4075,7 +4083,7 @@ pub fn emit_stmt(stmt: &ProtoStatement) -> Option<String> {
40754083 return None ;
40764084 }
40774085 let nb = native_bytes ( a. dst_width ) ;
4078- let nw = nb / 8 ;
4086+ let nw = wide_words ( nb ) ;
40794087 let max_idx = a. dst_num_elements . saturating_sub ( 1 ) ;
40804088 let idx_str = emit_expr ( & a. dst_index_expr ) ?;
40814089 let dmask = wpack ( nb, a. dst_width ) ;
@@ -4495,7 +4503,7 @@ fn emit_expr_inner(expr: &ProtoExpression, needs_clean: bool) -> Option<String>
44954503 if off < 0 {
44964504 return None ;
44974505 }
4498- let nw = native_bytes ( * var_full_width) / 8 ;
4506+ let nw = wide_words ( native_bytes ( * var_full_width) ) ;
44994507 let m: u128 = if dyn_sel. window >= 128 {
45004508 !0u128
45014509 } else {
@@ -4534,7 +4542,7 @@ fn emit_expr_inner(expr: &ProtoExpression, needs_clean: bool) -> Option<String>
45344542 if off < 0 {
45354543 return None ;
45364544 }
4537- let nw = native_bytes ( * var_full_width) / 8 ;
4545+ let nw = wide_words ( native_bytes ( * var_full_width) ) ;
45384546 return Some ( format ! (
45394547 "({{ uint64_t _idx_raw = (uint64_t)({idx}); \
45404548 uint64_t _idx = _idx_raw < {max} ? _idx_raw : {max}; \
@@ -5281,7 +5289,7 @@ fn emit_expr_inner(expr: &ProtoExpression, needs_clean: bool) -> Option<String>
52815289 return None ;
52825290 }
52835291 let src_nb = native_bytes ( x_w) ;
5284- let src_nw = src_nb / 8 ;
5292+ let src_nw = wide_words ( src_nb) ;
52855293 let mut pre = String :: new ( ) ;
52865294 let xr = emit_wide_operand ( x, src_nb, & mut pre) ?;
52875295 let count = emit_expr ( y) ?;
0 commit comments