fn put_access_chain(
        &mut self,
        chain: Handle<crate::Expression>,
        policy: index::BoundsCheckPolicy,
        context: &ExpressionContext,
    ) -> BackendResult {
        match context.function.expressions[chain] {
            crate::Expression::Access { base, index } => {
                let mut base_ty = context.resolve_type(base);

                // Look through any pointers to see what we're really indexing.
                if let crate::TypeInner::Pointer { base, space: _ } = *base_ty {
                    base_ty = &context.module.types[base].inner;
                }

                self.put_subscripted_access_chain(
                    base,
                    base_ty,
                    index::GuardedIndex::Expression(index),
                    policy,
                    context,
                )?;
            }
            crate::Expression::AccessIndex { base, index } => {
                let base_resolution = &context.info[base].ty;
                let mut base_ty = base_resolution.inner_with(&context.module.types);
                let mut base_ty_handle = base_resolution.handle();

                // Look through any pointers to see what we're really indexing.
                if let crate::TypeInner::Pointer { base, space: _ } = *base_ty {
                    base_ty = &context.module.types[base].inner;
                    base_ty_handle = Some(base);
                }

                // Handle structs and anything else that can use `.x` syntax here, so
                // `put_subscripted_access_chain` won't have to handle the absurd case of
                // indexing a struct with an expression.
                match *base_ty {
                    crate::TypeInner::Struct { .. } => {
                        let base_ty = base_ty_handle.unwrap();
                        self.put_access_chain(base, policy, context)?;
                        let name = &self.names[&NameKey::StructMember(base_ty, index)];
                        write!(self.out, ".{}", name)?;
                    }
                    crate::TypeInner::ValuePointer { .. } | crate::TypeInner::Vector { .. } => {
                        self.put_access_chain(base, policy, context)?;
                        // Prior to Metal v2.1 component access for packed vectors wasn't available
                        // however array indexing is
                        if context.get_packed_vec_kind(base).is_some() {
                            write!(self.out, "[{}]", index)?;
                        } else {
                            write!(self.out, ".{}", back::COMPONENTS[index as usize])?;
                        }
                    }
                    _ => {
                        self.put_subscripted_access_chain(
                            base,
                            base_ty,
                            index::GuardedIndex::Known(index),
                            policy,
                            context,
                        )?;
                    }
                }
            }
            _ => self.put_expression(chain, context, false)?,
        }

        Ok(())
    }
/// Write the access chain `chain`.
///
/// `chain` is a subtree of [`Access`] and [`AccessIndex`] expressions,
/// operating either on a pointer to a value, or on a value directly.
///
/// Generate bounds checks code only if `policy` is [`Restrict`]. The
/// [`ReadZeroSkipWrite`] policy requires checks before any accesses take place, so
/// that must be handled in the caller.
///
/// Handle the entire chain, recursing back into `put_expression` only for index
/// expressions and the base expression that originates the pointer or composite value
/// being accessed. This allows `put_expression` to assume that any `Access` or
/// `AccessIndex` expressions it sees are the top of a chain, so it can emit
/// `ReadZeroSkipWrite` checks.
///
/// [`Access`]: crate::Expression::Access
/// [`AccessIndex`]: crate::Expression::AccessIndex
/// [`Restrict`]: crate::proc::index::BoundsCheckPolicy::Restrict
/// [`ReadZeroSkipWrite`]: crate::proc::index::BoundsCheckPolicy::ReadZeroSkipWrite
Write the access chain `chain`.

Generate bounds checks code only if `policy` is [`Restrict`]. The
[`ReadZeroSkipWrite`] policy requires checks before any accesses take place, so
that must be handled in the caller.

Handle the entire chain, recursing back into `put_expression` only for index
expressions and the base expression that originates the pointer or composite value
being accessed.


Write the access chain ` chain ` . Generate bounds checks code only if ` policy ` is [ ` Restrict ` ] . The [ ` ReadZeroSkipWrite ` ] policy requires checks before any accesses take place so that must be handled in the caller . Handle the entire chain recursing back into ` put_expression ` only for index expressions and the base expression that originates the pointer or composite value being accessed .
fn put_access_chain(
        &mut self,
        chain: Handle<crate::Expression>,
        policy: index::BoundsCheckPolicy,
        context: &ExpressionContext,
    ) -> BackendResult {
        match context.function.expressions[chain] {
            crate::Expression::Access { base, index } => {
                let mut base_ty = context.resolve_type(base);
                // Look through any pointers to see what we're really indexing.
                if let crate::TypeInner::Pointer { base, space: _ } = *base_ty {
                    base_ty = &context.module.types[base].inner;
                }
                self.put_subscripted_access_chain(
                    base,
                    base_ty,
                    index::GuardedIndex::Expression(index),
                    policy,
                    context,
                )?;
            }
            crate::Expression::AccessIndex { base, index } => {
                let base_resolution = &context.info[base].ty;
                let mut base_ty = base_resolution.inner_with(&context.module.types);
                let mut base_ty_handle = base_resolution.handle();
                // Look through any pointers to see what we're really indexing.
                if let crate::TypeInner::Pointer { base, space: _ } = *base_ty {
                    base_ty = &context.module.types[base].inner;
                    base_ty_handle = Some(base);
                }
                // Handle structs and anything else that can use `.x` syntax here, so
                // `put_subscripted_access_chain` won't have to handle the absurd case of
                // indexing a struct with an expression.
                match *base_ty {
                    crate::TypeInner::Struct { .. } => {
                        let base_ty = base_ty_handle.unwrap();
                        self.put_access_chain(base, policy, context)?;
                        let name = &self.names[&NameKey::StructMember(base_ty, index)];
                        write!(self.out, ".{}", name)?;
                    }
                    crate::TypeInner::ValuePointer { .. } | crate::TypeInner::Vector { .. } => {
                        self.put_access_chain(base, policy, context)?;
                        // Prior to Metal v2.1 component access for packed vectors wasn't available
                        // however array indexing is
                        if context.get_packed_vec_kind(base).is_some() {
                            write!(self.out, "[{}]", index)?;
                        } else {
                            write!(self.out, ".{}", back::COMPONENTS[index as usize])?;
                        }
                    }
                    _ => {
                        self.put_subscripted_access_chain(
                            base,
                            base_ty,
                            index::GuardedIndex::Known(index),
                            policy,
                            context,
                        )?;
                    }
                }
            }
            _ => self.put_expression(chain, context, false)?,
        }
        Ok(())
    }
fn put_access_chain ( & mut self , chain : Handle < crate :: Expression > , policy : index :: BoundsCheckPolicy , context : & ExpressionContext , ) -> BackendResult { match context . function . expressions [ chain ] { crate :: Expression :: Access { base , index } => { let mut base_ty = context . resolve_type ( base ) ; // Look through any pointers to see what we're really indexing. if let crate :: TypeInner :: Pointer { base , space : _ } = * base_ty { base_ty = & context . module . types [ base ] . inner ; } self . put_subscripted_access_chain ( base , base_ty , index :: GuardedIndex :: Expression ( index ) , policy , context , ) ? ; } crate :: Expression :: AccessIndex { base , index } => { let base_resolution = & context . info [ base ] . ty ; let mut base_ty = base_resolution . inner_with ( & context . module . types ) ; let mut base_ty_handle = base_resolution . handle ( ) ; // Look through any pointers to see what we're really indexing. if let crate :: TypeInner :: Pointer { base , space : _ } = * base_ty { base_ty = & context . module . types [ base ] . inner ; base_ty_handle = Some ( base ) ; } // Handle structs and anything else that can use `.x` syntax here, so // `put_subscripted_access_chain` won't have to handle the absurd case of // indexing a struct with an expression. match * base_ty { crate :: TypeInner :: Struct { .. } => { let base_ty = base_ty_handle . unwrap ( ) ; self . put_access_chain ( base , policy , context ) ? ; let name = & self . names [ & NameKey :: StructMember ( base_ty , index ) ] ; write ! ( self out " " name ) ? ; } crate :: TypeInner :: ValuePointer { .. } | crate :: TypeInner :: Vector { .. } => { self . put_access_chain ( base , policy , context ) ? ; // Prior to Metal v2.1 component access for packed vectors wasn't available // however array indexing is if context . get_packed_vec_kind ( base ) . is_some ( ) { write ! ( self out " " index ) ? ; } else { write ! ( self out " " back COMPONENTS [ index as usize ] ) ? ; } } _ => { self . put_subscripted_access_chain ( base , base_ty , index :: GuardedIndex :: Known ( index ) , policy , context , ) ? ; } } } _ => self . put_expression ( chain , context , false ) ? , } Ok ( ( ) ) }
Write the access chain `chain`.
Write the access chain ` chain ` .
&mut self
chain
Handle<crate::Expression>
policy
index::BoundsCheckPolicy
context
&ExpressionContext
&mut self
chain
Handle<crate::Expression>
policy
index::BoundsCheckPolicy
context
&ExpressionContext