| 
						
						
						
					 | 
					 | 
					@ -1,11 +1,12 @@
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#[cfg(test)]
 | 
					 | 
					 | 
					 | 
					#[cfg(test)]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					mod tests;
 | 
					 | 
					 | 
					 | 
					mod tests;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::compiler::{Instruction, Module};
 | 
					 | 
					 | 
					 | 
					use crate::compiler::{
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    AddressingModel, BuiltinDecoration, Decoration, ExecutionMode, ExecutionModel, Instruction,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    MemoryModel, Module, StorageClass,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use std::fmt;
 | 
					 | 
					 | 
					 | 
					use std::fmt;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use super::StorageClass;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::parser::Ast;
 | 
					 | 
					 | 
					 | 
					use crate::parser::Ast;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#[derive(Debug, PartialEq, Clone)]
 | 
					 | 
					 | 
					 | 
					#[derive(Debug, PartialEq, Clone)]
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -43,48 +44,43 @@ pub fn parse_type(typ: &String) -> Type {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // So, *v4f32i is a pointer to a vector of 4 floats, with the storage class Input.
 | 
					 | 
					 | 
					 | 
					    // So, *v4f32i is a pointer to a vector of 4 floats, with the storage class Input.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // *v4f32o is a pointer to a vector of 4 floats, with the storage class Output.
 | 
					 | 
					 | 
					 | 
					    // *v4f32o is a pointer to a vector of 4 floats, with the storage class Output.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let c = typ.chars().next().unwrap();
 | 
					 | 
					 | 
					 | 
					    let mut chars = typ.chars();
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    match c {
 | 
					 | 
					 | 
					 | 
					    match chars.next() {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        '<' => {
 | 
					 | 
					 | 
					 | 
					        Some('<') => {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            assert_eq!(typ.as_str(), "<>");
 | 
					 | 
					 | 
					 | 
					            assert_eq!(typ.as_str(), "<>");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            Type::Void
 | 
					 | 
					 | 
					 | 
					            Type::Void
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        '*' => {
 | 
					 | 
					 | 
					 | 
					        Some('*') => {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let mut chars = typ.chars();
 | 
					 | 
					 | 
					 | 
					            let mut typ = chars.collect::<String>();
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            chars.next();
 | 
					 | 
					 | 
					 | 
					            let storage_class = match typ.pop() {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let typ = chars.collect::<String>();
 | 
					 | 
					 | 
					 | 
					                Some('i') => StorageClass::Input,
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let storage_class = match typ.chars().last().unwrap() {
 | 
					 | 
					 | 
					 | 
					                Some('o') => StorageClass::Output,
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                'i' => StorageClass::Input,
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                'o' => StorageClass::Output,
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                _ => panic!("Invalid storage class"),
 | 
					 | 
					 | 
					 | 
					                _ => panic!("Invalid storage class"),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            };
 | 
					 | 
					 | 
					 | 
					            };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let typ = typ.chars().take(typ.len() - 1).collect::<String>();
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            Type::Pointer(Box::new(parse_type(&typ)), storage_class)
 | 
					 | 
					 | 
					 | 
					            Type::Pointer(Box::new(parse_type(&typ)), storage_class)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        'v' => {
 | 
					 | 
					 | 
					 | 
					        Some('v') => {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let mut chars = typ.chars();
 | 
					 | 
					 | 
					 | 
					            let size = chars.next().map(|s| s.to_digit(10)).flatten().unwrap();
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            chars.next();
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let size = chars.next().unwrap().to_digit(10).unwrap();
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let typ = chars.collect::<String>();
 | 
					 | 
					 | 
					 | 
					            let typ = chars.collect::<String>();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            Type::Vector(Box::new(parse_type(&typ)), size)
 | 
					 | 
					 | 
					 | 
					            Type::Vector(Box::new(parse_type(&typ)), size)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        'f' => {
 | 
					 | 
					 | 
					 | 
					        Some('f') => {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let size = typ.chars().skip(1).collect::<String>().parse().unwrap();
 | 
					 | 
					 | 
					 | 
					            let size = chars.collect::<String>().parse().unwrap();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            Type::Float(size)
 | 
					 | 
					 | 
					 | 
					            Type::Float(size)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        's' => {
 | 
					 | 
					 | 
					 | 
					        Some('s') => {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let size = typ.chars().skip(1).collect::<String>().parse().unwrap();
 | 
					 | 
					 | 
					 | 
					            let size = chars.collect::<String>().parse().unwrap();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            Type::Int(size)
 | 
					 | 
					 | 
					 | 
					            Type::Int(size)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        'u' => {
 | 
					 | 
					 | 
					 | 
					        Some('u') => {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let size = typ.chars().skip(1).collect::<String>().parse().unwrap();
 | 
					 | 
					 | 
					 | 
					            let size = chars.collect::<String>().parse().unwrap();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            Type::Unsigned(size)
 | 
					 | 
					 | 
					 | 
					            Type::Unsigned(size)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        _ => panic!("Invalid type"),
 | 
					 | 
					 | 
					 | 
					        _ => panic!("Invalid type"),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) {
 | 
					 | 
					 | 
					 | 
					fn emit_type(typ: &Type, ops: &mut Vec<(String, String)>) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    match &typ {
 | 
					 | 
					 | 
					 | 
					    match &typ {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        Type::Void => {
 | 
					 | 
					 | 
					 | 
					        Type::Void => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ops.push(("%void".to_string(), "OpTypeVoid".to_string()));
 | 
					 | 
					 | 
					 | 
					            ops.push(("%void".to_string(), "OpTypeVoid".to_string()));
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -108,18 +104,14 @@ fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ));
 | 
					 | 
					 | 
					 | 
					            ));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        Type::Vector(in_typ, size) => {
 | 
					 | 
					 | 
					 | 
					        Type::Vector(in_typ, size) => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            emit_type(*in_typ.clone(), ops);
 | 
					 | 
					 | 
					 | 
					            emit_type(in_typ, ops);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ops.push((
 | 
					 | 
					 | 
					 | 
					            ops.push((
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                fix_name(&typ.to_string()),
 | 
					 | 
					 | 
					 | 
					                fix_name(&typ.to_string()),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                format!(
 | 
					 | 
					 | 
					 | 
					                format!("OpTypeVector {} {}", fix_name(&in_typ.to_string()), size),
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    "OpTypeVector {} {}",
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    fix_name(&in_typ.clone().to_string()),
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    size
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                ),
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ))
 | 
					 | 
					 | 
					 | 
					            ))
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        Type::Pointer(in_typ, storage_class) => {
 | 
					 | 
					 | 
					 | 
					        Type::Pointer(in_typ, storage_class) => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            emit_type(*in_typ.clone(), ops);
 | 
					 | 
					 | 
					 | 
					            emit_type(in_typ, ops);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let typ_id = fix_name(&typ.to_string());
 | 
					 | 
					 | 
					 | 
					            let typ_id = fix_name(&typ.to_string());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let storage_class = match storage_class {
 | 
					 | 
					 | 
					 | 
					            let storage_class = match storage_class {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                StorageClass::Input => "Input",
 | 
					 | 
					 | 
					 | 
					                StorageClass::Input => "Input",
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -138,23 +130,19 @@ fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fn fix_name(name: &String) -> String {
 | 
					 | 
					 | 
					 | 
					fn fix_name(name: &str) -> String {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    format!(
 | 
					 | 
					 | 
					 | 
					    format!(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        "%{}",
 | 
					 | 
					 | 
					 | 
					        "%{}",
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        name.clone()
 | 
					 | 
					 | 
					 | 
					        name.replace("-", "_")
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .replace("-", "_")
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .replace("*", "p")
 | 
					 | 
					 | 
					 | 
					            .replace("*", "p")
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .replace("<>", "void")
 | 
					 | 
					 | 
					 | 
					            .replace("<>", "void")
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    )
 | 
					 | 
					 | 
					 | 
					    )
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fn has_id<T>(name: String, ops: &Vec<(Option<String>, T)>) -> bool {
 | 
					 | 
					 | 
					 | 
					fn has_id<T>(name: &str, ops: &Vec<(Option<String>, T)>) -> bool {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    for op in ops {
 | 
					 | 
					 | 
					 | 
					    ops.iter()
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        if op.0.is_some() && op.0.clone().unwrap() == name {
 | 
					 | 
					 | 
					 | 
					        .find(|op| op.0.as_ref().map(|s| *s == name).unwrap_or(false))
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            return true;
 | 
					 | 
					 | 
					 | 
					        .is_some()
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    false
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> {
 | 
					 | 
					 | 
					 | 
					pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -170,15 +158,15 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let memory_model_address = match module.memory_model.addressing_model {
 | 
					 | 
					 | 
					 | 
					    let memory_model_address = match module.memory_model.addressing_model {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        crate::compiler::AddressingModel::Logical => "Logical",
 | 
					 | 
					 | 
					 | 
					        AddressingModel::Logical => "Logical",
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        crate::compiler::AddressingModel::Physical32 => "Physical32",
 | 
					 | 
					 | 
					 | 
					        AddressingModel::Physical32 => "Physical32",
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        crate::compiler::AddressingModel::Physical64 => "Physical64",
 | 
					 | 
					 | 
					 | 
					        AddressingModel::Physical64 => "Physical64",
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        crate::compiler::AddressingModel::PhysicalStorageBuffer64 => "PhysicalStorageBuffer64",
 | 
					 | 
					 | 
					 | 
					        AddressingModel::PhysicalStorageBuffer64 => "PhysicalStorageBuffer64",
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    };
 | 
					 | 
					 | 
					 | 
					    };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let memory_model_model = match module.memory_model.memory_model {
 | 
					 | 
					 | 
					 | 
					    let memory_model_model = match module.memory_model.memory_model {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        crate::compiler::MemoryModel::Simple => "Simple",
 | 
					 | 
					 | 
					 | 
					        MemoryModel::Simple => "Simple",
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        crate::compiler::MemoryModel::GLSL450 => "GLSL450",
 | 
					 | 
					 | 
					 | 
					        MemoryModel::GLSL450 => "GLSL450",
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        crate::compiler::MemoryModel::OpenCL => "OpenCL",
 | 
					 | 
					 | 
					 | 
					        MemoryModel::OpenCL => "OpenCL",
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        _ => todo!(),
 | 
					 | 
					 | 
					 | 
					        _ => todo!(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    };
 | 
					 | 
					 | 
					 | 
					    };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ops.push((
 | 
					 | 
					 | 
					 | 
					    ops.push((
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -192,8 +180,8 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    for entry in module.entry_points.clone() {
 | 
					 | 
					 | 
					 | 
					    for entry in module.entry_points.clone() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let exec_model = match entry.execution_model {
 | 
					 | 
					 | 
					 | 
					        let exec_model = match entry.execution_model {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            crate::compiler::ExecutionModel::Fragment => "Fragment",
 | 
					 | 
					 | 
					 | 
					            ExecutionModel::Fragment => "Fragment",
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            crate::compiler::ExecutionModel::Vertex => "Vertex",
 | 
					 | 
					 | 
					 | 
					            ExecutionModel::Vertex => "Vertex",
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        };
 | 
					 | 
					 | 
					 | 
					        };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let name = entry.name;
 | 
					 | 
					 | 
					 | 
					        let name = entry.name;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let interface: Vec<String> = entry
 | 
					 | 
					 | 
					 | 
					        let interface: Vec<String> = entry
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -202,7 +190,7 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .map(|i| fix_name(&i.to_string()))
 | 
					 | 
					 | 
					 | 
					            .map(|i| fix_name(&i.to_string()))
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .collect();
 | 
					 | 
					 | 
					 | 
					            .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let exec_mode = match entry.execution_mode {
 | 
					 | 
					 | 
					 | 
					        let exec_mode = match entry.execution_mode {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            crate::compiler::ExecutionMode::OriginUpperLeft => "OriginUpperLeft",
 | 
					 | 
					 | 
					 | 
					            ExecutionMode::OriginUpperLeft => "OriginUpperLeft",
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        };
 | 
					 | 
					 | 
					 | 
					        };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ops.push((
 | 
					 | 
					 | 
					 | 
					        ops.push((
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            None,
 | 
					 | 
					 | 
					 | 
					            None,
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -226,16 +214,16 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    for global in module.globals.clone() {
 | 
					 | 
					 | 
					 | 
					    for global in module.globals.clone() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let name = fix_name(&global.name);
 | 
					 | 
					 | 
					 | 
					        let name = fix_name(&global.name);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let _typ = global.typ;
 | 
					 | 
					 | 
					 | 
					        let typ = global.typ;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let storage_class = match global.storage_class {
 | 
					 | 
					 | 
					 | 
					        let storage_class = match global.storage_class {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            crate::compiler::StorageClass::Input => "Input",
 | 
					 | 
					 | 
					 | 
					            StorageClass::Input => "Input",
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            crate::compiler::StorageClass::Output => "Output",
 | 
					 | 
					 | 
					 | 
					            StorageClass::Output => "Output",
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            crate::compiler::StorageClass::Undefined => panic!("Bound a non-declared variable"),
 | 
					 | 
					 | 
					 | 
					            StorageClass::Undefined => panic!("Bound a non-declared variable"),
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        };
 | 
					 | 
					 | 
					 | 
					        };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let mut type_ops = Vec::new();
 | 
					 | 
					 | 
					 | 
					        let mut type_ops = Vec::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        emit_type(parse_type(&_typ), &mut type_ops);
 | 
					 | 
					 | 
					 | 
					        emit_type(&parse_type(&typ), &mut type_ops);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for op in type_ops {
 | 
					 | 
					 | 
					 | 
					        for op in type_ops {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if has_id(op.0.clone(), &ops) {
 | 
					 | 
					 | 
					 | 
					            if has_id(&op.0, &ops) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                continue;
 | 
					 | 
					 | 
					 | 
					                continue;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            }
 | 
					 | 
					 | 
					 | 
					            }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ops.push((Some(op.0), vec![op.1]));
 | 
					 | 
					 | 
					 | 
					            ops.push((Some(op.0), vec![op.1]));
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -244,17 +232,17 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            Some(name.clone()),
 | 
					 | 
					 | 
					 | 
					            Some(name.clone()),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            vec![
 | 
					 | 
					 | 
					 | 
					            vec![
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                "OpVariable".to_string(),
 | 
					 | 
					 | 
					 | 
					                "OpVariable".to_string(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                fix_name(&_typ),
 | 
					 | 
					 | 
					 | 
					                fix_name(&typ),
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                storage_class.to_string(),
 | 
					 | 
					 | 
					 | 
					                storage_class.to_string(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ],
 | 
					 | 
					 | 
					 | 
					            ],
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ));
 | 
					 | 
					 | 
					 | 
					        ));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for dec in global.decorations {
 | 
					 | 
					 | 
					 | 
					        for dec in global.decorations {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // Decorations have the format Location 0, or Builtin FragCoord
 | 
					 | 
					 | 
					 | 
					            // Decorations have the format Location 0, or Builtin FragCoord
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let dec = match dec {
 | 
					 | 
					 | 
					 | 
					            let dec = match dec {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                crate::compiler::Decoration::Location(loc) => format!("Location {}", loc),
 | 
					 | 
					 | 
					 | 
					                Decoration::Location(loc) => format!("Location {}", loc),
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                crate::compiler::Decoration::BuiltIn(builtin) => {
 | 
					 | 
					 | 
					 | 
					                Decoration::BuiltIn(builtin) => {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    let builtin = match builtin {
 | 
					 | 
					 | 
					 | 
					                    let builtin = match builtin {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        crate::compiler::BuiltinDecoration::FragCoord => "FragCoord",
 | 
					 | 
					 | 
					 | 
					                        BuiltinDecoration::FragCoord => "FragCoord",
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    };
 | 
					 | 
					 | 
					 | 
					                    };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    format!("BuiltIn {}", builtin)
 | 
					 | 
					 | 
					 | 
					                    format!("BuiltIn {}", builtin)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                }
 | 
					 | 
					 | 
					 | 
					                }
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -267,29 +255,26 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let name = fix_name(&format!("l_{}", fun.name));
 | 
					 | 
					 | 
					 | 
					        let name = fix_name(&format!("l_{}", fun.name));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let return_type = fix_name(&fun.return_type);
 | 
					 | 
					 | 
					 | 
					        let return_type = fix_name(&fun.return_type);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let mut type_ops = Vec::new();
 | 
					 | 
					 | 
					 | 
					        let mut type_ops = Vec::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        emit_type(parse_type(&fun.return_type), &mut type_ops);
 | 
					 | 
					 | 
					 | 
					        emit_type(&parse_type(&fun.return_type), &mut type_ops);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for op in type_ops {
 | 
					 | 
					 | 
					 | 
					        for op in type_ops {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if has_id(op.0.clone(), &ops) {
 | 
					 | 
					 | 
					 | 
					            if has_id(&op.0, &ops) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                continue;
 | 
					 | 
					 | 
					 | 
					                continue;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            }
 | 
					 | 
					 | 
					 | 
					            }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ops.push((Some(op.0), vec![op.1]));
 | 
					 | 
					 | 
					 | 
					            ops.push((Some(op.0), vec![op.1]));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ops.push((
 | 
					 | 
					 | 
					 | 
					        // Push OpFunctionType
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            Some(name.clone()),
 | 
					 | 
					 | 
					 | 
					        ops.push((Some(name), vec!["OpTypeFunction".to_string(), return_type]));
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            vec!["OpTypeFunction".to_string(), return_type.clone()],
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ));
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // for op in ops {
 | 
					 | 
					 | 
					 | 
					    // for op in ops {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //     if op.0.is_some() {
 | 
					 | 
					 | 
					 | 
					    //     if let Some(op0) = op.0 {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //         write!(spirv_asm, "{} = ", op.0.unwrap()).unwrap();
 | 
					 | 
					 | 
					 | 
					    //         write!(spirv_asm, "{} = ", op0).unwrap();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //     }
 | 
					 | 
					 | 
					 | 
					    //     }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //     for arg in op.1 {
 | 
					 | 
					 | 
					 | 
					    //     for arg in op.1 {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //         write!(spirv_asm, "{} ", arg).unwrap();
 | 
					 | 
					 | 
					 | 
					    //         write!(spirv_asm, "{} ", arg).unwrap();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //     }
 | 
					 | 
					 | 
					 | 
					    //     }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //     writeln!(spirv_asm).unwrap();
 | 
					 | 
					 | 
					 | 
					    //     writeln!(spirv_asm).unwrap();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // }
 | 
					 | 
					 | 
					 | 
					    // }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // spirv_asm
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ops
 | 
					 | 
					 | 
					 | 
					    ops
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -370,8 +355,7 @@ pub fn compile_ast_ssa(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    out: &mut Vec<(Option<String>, String)>,
 | 
					 | 
					 | 
					 | 
					    out: &mut Vec<(Option<String>, String)>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					) {
 | 
					 | 
					 | 
					 | 
					) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    match ast.clone().list() {
 | 
					 | 
					 | 
					 | 
					    match ast.clone().list() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        Some(l) => {
 | 
					 | 
					 | 
					 | 
					        Some(mut lst) => {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let mut lst = l.clone();
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            assert!(!lst.is_empty());
 | 
					 | 
					 | 
					 | 
					            assert!(!lst.is_empty());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let fun = lst.remove(0);
 | 
					 | 
					 | 
					 | 
					            let fun = lst.remove(0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            assert!(true); // no safe remove, thanks Rust
 | 
					 | 
					 | 
					 | 
					            assert!(true); // no safe remove, thanks Rust
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -421,9 +405,7 @@ pub fn compile_ast_ssa(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            }
 | 
					 | 
					 | 
					 | 
					            }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        None => {
 | 
					 | 
					 | 
					 | 
					        None => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let sym = ast.clone().symbol();
 | 
					 | 
					 | 
					 | 
					            let sym = ast.symbol().unwrap();
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            assert!(sym.is_some());
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let sym = sym.unwrap();
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            match match_number(&sym) {
 | 
					 | 
					 | 
					 | 
					            match match_number(&sym) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                Number::Int(i) => {
 | 
					 | 
					 | 
					 | 
					                Number::Int(i) => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    let key = format!("i32_{}", i);
 | 
					 | 
					 | 
					 | 
					                    let key = format!("i32_{}", i);
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -500,14 +482,14 @@ pub fn compile_fun_ssa(module: &mut Module, ops: &Vec<(Option<String>, String)>)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let mut out_pre = vec![];
 | 
					 | 
					 | 
					 | 
					        let mut out_pre = vec![];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for t in &types {
 | 
					 | 
					 | 
					 | 
					        for t in &types {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let typ = parse_type(t);
 | 
					 | 
					 | 
					 | 
					            let typ = parse_type(t);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if has_id(fix_name(&typ.to_string()), ops) {
 | 
					 | 
					 | 
					 | 
					            if has_id(&fix_name(&typ.to_string()), ops) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                continue;
 | 
					 | 
					 | 
					 | 
					                continue;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            }
 | 
					 | 
					 | 
					 | 
					            }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if has_id(fix_name(&typ.to_string()), &out_pre) {
 | 
					 | 
					 | 
					 | 
					            if has_id(&fix_name(&typ.to_string()), &out_pre) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                continue;
 | 
					 | 
					 | 
					 | 
					                continue;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            }
 | 
					 | 
					 | 
					 | 
					            }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let mut type_ops = vec![];
 | 
					 | 
					 | 
					 | 
					            let mut type_ops = vec![];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            emit_type(typ, &mut type_ops);
 | 
					 | 
					 | 
					 | 
					            emit_type(&typ, &mut type_ops);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            for type_op in type_ops {
 | 
					 | 
					 | 
					 | 
					            for type_op in type_ops {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                out_pre.push((Some(type_op.0), type_op.1));
 | 
					 | 
					 | 
					 | 
					                out_pre.push((Some(type_op.0), type_op.1));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            }
 | 
					 | 
					 | 
					 | 
					            }
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
 
 |