| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -34,7 +34,7 @@ impl fmt::Display for Type {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					pub fn parse_type(typ: String) -> Type {
 | 
					 | 
					 | 
					 | 
					pub fn parse_type(typ: &String) -> Type {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // pointers have the format *<t>i or *<t>o, for the storage class
 | 
					 | 
					 | 
					 | 
					    // pointers have the format *<t>i or *<t>o, for the storage class
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // floats have the format f<size>, so f32, f64...
 | 
					 | 
					 | 
					 | 
					    // floats have the format f<size>, so f32, f64...
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // ints have the format s<size>, so s32, s64...
 | 
					 | 
					 | 
					 | 
					    // ints have the format s<size>, so s32, s64...
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -54,14 +54,14 @@ pub fn parse_type(typ: String) -> Type {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                _ => panic!("Invalid storage class"),
 | 
					 | 
					 | 
					 | 
					                _ => panic!("Invalid storage class"),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            };
 | 
					 | 
					 | 
					 | 
					            };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let typ = typ.chars().take(typ.len() - 1).collect::<String>();
 | 
					 | 
					 | 
					 | 
					            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' => {
 | 
					 | 
					 | 
					 | 
					        'v' => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let mut chars = typ.chars();
 | 
					 | 
					 | 
					 | 
					            let mut chars = typ.chars();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            chars.next();
 | 
					 | 
					 | 
					 | 
					            chars.next();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let size = chars.next().unwrap().to_digit(10).unwrap();
 | 
					 | 
					 | 
					 | 
					            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' => {
 | 
					 | 
					 | 
					 | 
					        'f' => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let size = typ.chars().skip(1).collect::<String>().parse().unwrap();
 | 
					 | 
					 | 
					 | 
					            let size = typ.chars().skip(1).collect::<String>().parse().unwrap();
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -81,7 +81,7 @@ pub fn parse_type(typ: String) -> 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::Unsigned(size) => {
 | 
					 | 
					 | 
					 | 
					        Type::Unsigned(size) => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ops.push((format!("%u{}", size).to_string(), format!("OpTypeInt {}", size)));
 | 
					 | 
					 | 
					 | 
					            ops.push((format!("%u{}", size).to_string(), format!("OpTypeInt {}", size)));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        },
 | 
					 | 
					 | 
					 | 
					        },
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -91,26 +91,34 @@ fn emit_type(typ: Type, ops: &mut Vec<(String, String)>) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        Type::Float(size) => {
 | 
					 | 
					 | 
					 | 
					        Type::Float(size) => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ops.push((format!("%f{}", size).to_string(), format!("OpTypeFloat {}", size)));
 | 
					 | 
					 | 
					 | 
					            ops.push((format!("%f{}", size).to_string(), format!("OpTypeFloat {}", size)));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        },
 | 
					 | 
					 | 
					 | 
					        },
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        Type::Vector(typ, size) => {
 | 
					 | 
					 | 
					 | 
					        Type::Vector(in_typ, size) => {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            emit_type(*typ.clone(), ops);
 | 
					 | 
					 | 
					 | 
					            emit_type(*in_typ.clone(), ops);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let typ_id = format!("%{}", *typ.clone());
 | 
					 | 
					 | 
					 | 
					            ops.push((fix_name(&typ.to_string()), format!("OpTypeVector {} {}", fix_name(&in_typ.clone().to_string()), size)))
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ops.push((format!("%v{}{}", typ_id, size).to_string(), format!("OpTypeVector {} {}", typ_id, size)))
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        },
 | 
					 | 
					 | 
					 | 
					        },
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        Type::Pointer(typ, storage_class) => {
 | 
					 | 
					 | 
					 | 
					        Type::Pointer(in_typ, storage_class) => {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            emit_type(*typ.clone(), ops);
 | 
					 | 
					 | 
					 | 
					            emit_type(*in_typ.clone(), ops);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let typ_id = format!("%{}", *typ.clone());
 | 
					 | 
					 | 
					 | 
					            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",
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                StorageClass::Output => "Output",
 | 
					 | 
					 | 
					 | 
					                StorageClass::Output => "Output",
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                StorageClass::Undefined => panic!("Bound a non-declared variable"),
 | 
					 | 
					 | 
					 | 
					                StorageClass::Undefined => panic!("Bound a non-declared variable"),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            };
 | 
					 | 
					 | 
					 | 
					            };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ops.push((format!("%{}{}", typ_id, storage_class).to_string(), format!("OpTypePointer {} {}", storage_class, typ_id)))
 | 
					 | 
					 | 
					 | 
					            ops.push((typ_id, format!("OpTypePointer {} {}", storage_class, fix_name(&in_typ.to_string()))))
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        },
 | 
					 | 
					 | 
					 | 
					        },
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fn fix_name(name: &String) -> String {
 | 
					 | 
					 | 
					 | 
					fn fix_name(name: &String) -> String {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    format!("%{}", name.clone().replace("-", "_"))
 | 
					 | 
					 | 
					 | 
					    format!("%{}", name.clone().replace("-", "_").replace("*", "p"))
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					fn has_id(name: String, ops: &Vec<(Option<String>, Vec<String>)>) -> bool {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    for op in ops {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        if op.0.is_some() && op.0.clone().unwrap() == name {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            return true;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    false
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					pub fn spirv_meta(module: Module) -> String {
 | 
					 | 
					 | 
					 | 
					pub fn spirv_meta(module: Module) -> String {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -162,13 +170,15 @@ pub fn spirv_meta(module: Module) -> String {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            crate::compiler::StorageClass::Output => "Output",
 | 
					 | 
					 | 
					 | 
					            crate::compiler::StorageClass::Output => "Output",
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            crate::compiler::StorageClass::Undefined => panic!("Bound a non-declared variable"),
 | 
					 | 
					 | 
					 | 
					            crate::compiler::StorageClass::Undefined => panic!("Bound a non-declared variable"),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        };
 | 
					 | 
					 | 
					 | 
					        };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let typ_id = format!("%{}", _typ);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        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) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                continue;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ops.push((Some(op.0), vec![op.1]));
 | 
					 | 
					 | 
					 | 
					            ops.push((Some(op.0), vec![op.1]));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ops.push((Some(name.clone()), vec!["OpVariable".to_string(), typ_id.to_string(), storage_class.to_string()]));
 | 
					 | 
					 | 
					 | 
					        ops.push((Some(name.clone()), vec!["OpVariable".to_string(), fix_name(&_typ), 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 {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
 
 |