@@ -695,6 +695,20 @@ impl<'a> ExpressionContext<'a> {
695
695
)
696
696
}
697
697
698
+ /// See docs for [`proc::index::bounds_check_iter`].
699
+ fn bounds_check_iter (
700
+ & self ,
701
+ chain : Handle < crate :: Expression > ,
702
+ ) -> impl Iterator <
703
+ Item = (
704
+ Handle < crate :: Expression > ,
705
+ index:: GuardedIndex ,
706
+ index:: IndexableLength ,
707
+ ) ,
708
+ > + ' _ {
709
+ index:: bounds_check_iter ( chain, self . module , self . function , self . info )
710
+ }
711
+
698
712
fn get_packed_vec_kind ( & self , expr_handle : Handle < crate :: Expression > ) -> Option < crate :: Scalar > {
699
713
match self . function . expressions [ expr_handle] {
700
714
crate :: Expression :: AccessIndex { base, index } => {
@@ -2647,68 +2661,38 @@ impl<W: Write> Writer<W> {
2647
2661
#[ allow( unused_variables) ]
2648
2662
fn put_bounds_checks (
2649
2663
& mut self ,
2650
- mut chain : Handle < crate :: Expression > ,
2664
+ chain : Handle < crate :: Expression > ,
2651
2665
context : & ExpressionContext ,
2652
2666
level : back:: Level ,
2653
2667
prefix : & ' static str ,
2654
2668
) -> Result < bool , Error > {
2655
2669
let mut check_written = false ;
2656
2670
2657
- // Iterate over the access chain, handling each expression.
2658
- loop {
2659
- // Produce a `GuardedIndex`, so we can shared code between the
2660
- // `Access` and `AccessIndex` cases.
2661
- let ( base, guarded_index) = match context. function . expressions [ chain] {
2662
- crate :: Expression :: Access { base, index } => {
2663
- ( base, Some ( index:: GuardedIndex :: Expression ( index) ) )
2664
- }
2665
- crate :: Expression :: AccessIndex { base, index } => {
2666
- // Don't try to check indices into structs. Validation already took
2667
- // care of them, and index::needs_guard doesn't handle that case.
2668
- let mut base_inner = context. resolve_type ( base) ;
2669
- if let crate :: TypeInner :: Pointer { base, .. } = * base_inner {
2670
- base_inner = & context. module . types [ base] . inner ;
2671
- }
2672
- match * base_inner {
2673
- crate :: TypeInner :: Struct { .. } => ( base, None ) ,
2674
- _ => ( base, Some ( index:: GuardedIndex :: Known ( index) ) ) ,
2675
- }
2676
- }
2677
- _ => break ,
2678
- } ;
2679
-
2680
- if let Some ( index) = guarded_index {
2681
- if let Some ( length) = context. access_needs_check ( base, index) {
2682
- if check_written {
2683
- write ! ( self . out, " && " ) ?;
2684
- } else {
2685
- write ! ( self . out, "{level}{prefix}" ) ?;
2686
- check_written = true ;
2687
- }
2671
+ // Iterate over the access chain, handling each required bounds check.
2672
+ for ( base, index, length) in context. bounds_check_iter ( chain) {
2673
+ if check_written {
2674
+ write ! ( self . out, " && " ) ?;
2675
+ } else {
2676
+ write ! ( self . out, "{level}{prefix}" ) ?;
2677
+ check_written = true ;
2678
+ }
2688
2679
2689
- // Check that the index falls within bounds. Do this with a single
2690
- // comparison, by casting the index to `uint` first, so that negative
2691
- // indices become large positive values.
2692
- write ! ( self . out, "uint(" ) ?;
2693
- self . put_index ( index, context, true ) ?;
2694
- self . out . write_str ( ") < " ) ?;
2695
- match length {
2696
- index:: IndexableLength :: Known ( value) => write ! ( self . out, "{value}" ) ?,
2697
- index:: IndexableLength :: Dynamic => {
2698
- let global =
2699
- context. function . originating_global ( base) . ok_or_else ( || {
2700
- Error :: GenericValidation (
2701
- "Could not find originating global" . into ( ) ,
2702
- )
2703
- } ) ?;
2704
- write ! ( self . out, "1 + " ) ?;
2705
- self . put_dynamic_array_max_index ( global, context) ?
2706
- }
2707
- }
2680
+ // Check that the index falls within bounds. Do this with a single
2681
+ // comparison, by casting the index to `uint` first, so that negative
2682
+ // indices become large positive values.
2683
+ write ! ( self . out, "uint(" ) ?;
2684
+ self . put_index ( index, context, true ) ?;
2685
+ self . out . write_str ( ") < " ) ?;
2686
+ match length {
2687
+ index:: IndexableLength :: Known ( value) => write ! ( self . out, "{value}" ) ?,
2688
+ index:: IndexableLength :: Dynamic => {
2689
+ let global = context. function . originating_global ( base) . ok_or_else ( || {
2690
+ Error :: GenericValidation ( "Could not find originating global" . into ( ) )
2691
+ } ) ?;
2692
+ write ! ( self . out, "1 + " ) ?;
2693
+ self . put_dynamic_array_max_index ( global, context) ?
2708
2694
}
2709
2695
}
2710
-
2711
- chain = base
2712
2696
}
2713
2697
2714
2698
Ok ( check_written)
0 commit comments