fn find_variables_in_function(
    spirv: &Spirv,
    function: Id,
    inspected_functions: &mut HashSet<Id>,
    found_variables: &mut HashSet<Id>,
) {
    inspected_functions.insert(function);
    let mut in_function = false;
    for instruction in spirv.instructions() {
        if !in_function {
            match instruction {
                Instruction::Function { result_id, .. } if result_id == &function => {
                    in_function = true;
                }
                _ => {}
            }
        } else {
            // We only care about instructions that accept pointers.
            // https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_universal_validation_rules
            match instruction {
                Instruction::Load { pointer, .. } | Instruction::Store { pointer, .. } => {
                    found_variables.insert(*pointer);
                }
                Instruction::AccessChain { base, .. }
                | Instruction::InBoundsAccessChain { base, .. } => {
                    found_variables.insert(*base);
                }
                Instruction::FunctionCall {
                    function,
                    arguments,
                    ..
                } => {
                    arguments.iter().for_each(|&x| {
                        found_variables.insert(x);
                    });
                    if !inspected_functions.contains(function) {
                        find_variables_in_function(
                            spirv,
                            *function,
                            inspected_functions,
                            found_variables,
                        );
                    }
                }
                Instruction::ImageTexelPointer {
                    image,
                    coordinate,
                    sample,
                    ..
                } => {
                    found_variables.insert(*image);
                    found_variables.insert(*coordinate);
                    found_variables.insert(*sample);
                }
                Instruction::CopyMemory { target, source, .. } => {
                    found_variables.insert(*target);
                    found_variables.insert(*source);
                }
                Instruction::CopyObject { operand, .. } => {
                    found_variables.insert(*operand);
                }
                Instruction::AtomicLoad { pointer, .. }
                | Instruction::AtomicIIncrement { pointer, .. }
                | Instruction::AtomicIDecrement { pointer, .. }
                | Instruction::AtomicFlagTestAndSet { pointer, .. }
                | Instruction::AtomicFlagClear { pointer, .. } => {
                    found_variables.insert(*pointer);
                }
                Instruction::AtomicStore { pointer, value, .. }
                | Instruction::AtomicExchange { pointer, value, .. }
                | Instruction::AtomicIAdd { pointer, value, .. }
                | Instruction::AtomicISub { pointer, value, .. }
                | Instruction::AtomicSMin { pointer, value, .. }
                | Instruction::AtomicUMin { pointer, value, .. }
                | Instruction::AtomicSMax { pointer, value, .. }
                | Instruction::AtomicUMax { pointer, value, .. }
                | Instruction::AtomicAnd { pointer, value, .. }
                | Instruction::AtomicOr { pointer, value, .. }
                | Instruction::AtomicXor { pointer, value, .. } => {
                    found_variables.insert(*pointer);
                    found_variables.insert(*value);
                }
                Instruction::AtomicCompareExchange {
                    pointer,
                    value,
                    comparator,
                    ..
                }
                | Instruction::AtomicCompareExchangeWeak {
                    pointer,
                    value,
                    comparator,
                    ..
                } => {
                    found_variables.insert(*pointer);
                    found_variables.insert(*value);
                    found_variables.insert(*comparator);
                }
                Instruction::ExtInst { operands, .. } => {
                    // We don't know which extended instructions take pointers,
                    // so we must interpret every operand as a pointer.
                    operands.iter().for_each(|&o| {
                        found_variables.insert(o);
                    });
                }
                Instruction::FunctionEnd => return,
                _ => {}
            }
        }
    }
}
// Recursively finds every pointer variable used in the execution of a function.
Recursively finds every pointer variable used in the execution of a function.
Recursively finds every pointer variable used in the execution of a function .
fn find_variables_in_function(
    spirv: &Spirv,
    function: Id,
    inspected_functions: &mut HashSet<Id>,
    found_variables: &mut HashSet<Id>,
) {
    inspected_functions.insert(function);
    let mut in_function = false;
    for instruction in spirv.instructions() {
        if !in_function {
            match instruction {
                Instruction::Function { result_id, .. } if result_id == &function => {
                    in_function = true;
                }
                _ => {}
            }
        } else {
            // We only care about instructions that accept pointers.
            // https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_universal_validation_rules
            match instruction {
                Instruction::Load { pointer, .. } | Instruction::Store { pointer, .. } => {
                    found_variables.insert(*pointer);
                }
                Instruction::AccessChain { base, .. }
                | Instruction::InBoundsAccessChain { base, .. } => {
                    found_variables.insert(*base);
                }
                Instruction::FunctionCall {
                    function,
                    arguments,
                    ..
                } => {
                    arguments.iter().for_each(|&x| {
                        found_variables.insert(x);
                    });
                    if !inspected_functions.contains(function) {
                        find_variables_in_function(
                            spirv,
                            *function,
                            inspected_functions,
                            found_variables,
                        );
                    }
                }
                Instruction::ImageTexelPointer {
                    image,
                    coordinate,
                    sample,
                    ..
                } => {
                    found_variables.insert(*image);
                    found_variables.insert(*coordinate);
                    found_variables.insert(*sample);
                }
                Instruction::CopyMemory { target, source, .. } => {
                    found_variables.insert(*target);
                    found_variables.insert(*source);
                }
                Instruction::CopyObject { operand, .. } => {
                    found_variables.insert(*operand);
                }
                Instruction::AtomicLoad { pointer, .. }
                | Instruction::AtomicIIncrement { pointer, .. }
                | Instruction::AtomicIDecrement { pointer, .. }
                | Instruction::AtomicFlagTestAndSet { pointer, .. }
                | Instruction::AtomicFlagClear { pointer, .. } => {
                    found_variables.insert(*pointer);
                }
                Instruction::AtomicStore { pointer, value, .. }
                | Instruction::AtomicExchange { pointer, value, .. }
                | Instruction::AtomicIAdd { pointer, value, .. }
                | Instruction::AtomicISub { pointer, value, .. }
                | Instruction::AtomicSMin { pointer, value, .. }
                | Instruction::AtomicUMin { pointer, value, .. }
                | Instruction::AtomicSMax { pointer, value, .. }
                | Instruction::AtomicUMax { pointer, value, .. }
                | Instruction::AtomicAnd { pointer, value, .. }
                | Instruction::AtomicOr { pointer, value, .. }
                | Instruction::AtomicXor { pointer, value, .. } => {
                    found_variables.insert(*pointer);
                    found_variables.insert(*value);
                }
                Instruction::AtomicCompareExchange {
                    pointer,
                    value,
                    comparator,
                    ..
                }
                | Instruction::AtomicCompareExchangeWeak {
                    pointer,
                    value,
                    comparator,
                    ..
                } => {
                    found_variables.insert(*pointer);
                    found_variables.insert(*value);
                    found_variables.insert(*comparator);
                }
                Instruction::ExtInst { operands, .. } => {
                    // We don't know which extended instructions take pointers,
                    // so we must interpret every operand as a pointer.
                    operands.iter().for_each(|&o| {
                        found_variables.insert(o);
                    });
                }
                Instruction::FunctionEnd => return,
                _ => {}
            }
        }
    }
}
fn find_variables_in_function ( spirv : & Spirv , function : Id , inspected_functions : & mut HashSet < Id > , found_variables : & mut HashSet < Id > , ) { inspected_functions . insert ( function ) ; let mut in_function = false ; for instruction in spirv . instructions ( ) { if ! in_function { match instruction { Instruction :: Function { result_id , .. } if result_id == & function => { in_function = true ; } _ => { } } } else { // We only care about instructions that accept pointers. // https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_universal_validation_rules match instruction { Instruction :: Load { pointer , .. } | Instruction :: Store { pointer , .. } => { found_variables . insert ( * pointer ) ; } Instruction :: AccessChain { base , .. } | Instruction :: InBoundsAccessChain { base , .. } => { found_variables . insert ( * base ) ; } Instruction :: FunctionCall { function , arguments , .. } => { arguments . iter ( ) . for_each ( | & x | { found_variables . insert ( x ) ; } ) ; if ! inspected_functions . contains ( function ) { find_variables_in_function ( spirv , * function , inspected_functions , found_variables , ) ; } } Instruction :: ImageTexelPointer { image , coordinate , sample , .. } => { found_variables . insert ( * image ) ; found_variables . insert ( * coordinate ) ; found_variables . insert ( * sample ) ; } Instruction :: CopyMemory { target , source , .. } => { found_variables . insert ( * target ) ; found_variables . insert ( * source ) ; } Instruction :: CopyObject { operand , .. } => { found_variables . insert ( * operand ) ; } Instruction :: AtomicLoad { pointer , .. } | Instruction :: AtomicIIncrement { pointer , .. } | Instruction :: AtomicIDecrement { pointer , .. } | Instruction :: AtomicFlagTestAndSet { pointer , .. } | Instruction :: AtomicFlagClear { pointer , .. } => { found_variables . insert ( * pointer ) ; } Instruction :: AtomicStore { pointer , value , .. } | Instruction :: AtomicExchange { pointer , value , .. } | Instruction :: AtomicIAdd { pointer , value , .. } | Instruction :: AtomicISub { pointer , value , .. } | Instruction :: AtomicSMin { pointer , value , .. } | Instruction :: AtomicUMin { pointer , value , .. } | Instruction :: AtomicSMax { pointer , value , .. } | Instruction :: AtomicUMax { pointer , value , .. } | Instruction :: AtomicAnd { pointer , value , .. } | Instruction :: AtomicOr { pointer , value , .. } | Instruction :: AtomicXor { pointer , value , .. } => { found_variables . insert ( * pointer ) ; found_variables . insert ( * value ) ; } Instruction :: AtomicCompareExchange { pointer , value , comparator , .. } | Instruction :: AtomicCompareExchangeWeak { pointer , value , comparator , .. } => { found_variables . insert ( * pointer ) ; found_variables . insert ( * value ) ; found_variables . insert ( * comparator ) ; } Instruction :: ExtInst { operands , .. } => { // We don't know which extended instructions take pointers, // so we must interpret every operand as a pointer. operands . iter ( ) . for_each ( | & o | { found_variables . insert ( o ) ; } ) ; } Instruction :: FunctionEnd => return , _ => { } } } } }
Recursively finds every pointer variable used in the execution of a function.
Recursively finds every pointer variable used in the execution of a function .
spirv
&Spirv
function
Id
inspected_functions
&mut HashSet<Id>
found_variables
&mut HashSet<Id>
spirv
&Spirv
function
Id
inspected_functions
&mut HashSet<Id>
found_variables
&mut HashSet<Id>