|  |  |  | @ -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
 | 
			
		
	
		
			
				
					|  |  |  |  |     // floats have the format f<size>, so f32, f64...
 | 
			
		
	
		
			
				
					|  |  |  |  |     // ints have the format s<size>, so s32, s64...
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -54,14 +54,14 @@ pub fn parse_type(typ: String) -> Type { | 
			
		
	
		
			
				
					|  |  |  |  |                 _ => 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' => { | 
			
		
	
		
			
				
					|  |  |  |  |             let mut chars = typ.chars(); | 
			
		
	
		
			
				
					|  |  |  |  |             chars.next(); | 
			
		
	
		
			
				
					|  |  |  |  |             let size = chars.next().unwrap().to_digit(10).unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             let typ = chars.collect::<String>(); | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Vector(Box::new(parse_type(typ)), size) | 
			
		
	
		
			
				
					|  |  |  |  |             Type::Vector(Box::new(parse_type(&typ)), size) | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |         'f' => { | 
			
		
	
		
			
				
					|  |  |  |  |             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)>) { | 
			
		
	
		
			
				
					|  |  |  |  |     match typ { | 
			
		
	
		
			
				
					|  |  |  |  |     match &typ { | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Unsigned(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) => { | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((format!("%f{}", size).to_string(), format!("OpTypeFloat {}", size))); | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Vector(typ, size) => { | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(*typ.clone(), ops); | 
			
		
	
		
			
				
					|  |  |  |  |             let typ_id = format!("%{}", *typ.clone()); | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((format!("%v{}{}", typ_id, size).to_string(), format!("OpTypeVector {} {}", typ_id, size))) | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Vector(in_typ, size) => { | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(*in_typ.clone(), ops); | 
			
		
	
		
			
				
					|  |  |  |  |             ops.push((fix_name(&typ.to_string()), format!("OpTypeVector {} {}", fix_name(&in_typ.clone().to_string()), size))) | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Pointer(typ, storage_class) => { | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(*typ.clone(), ops); | 
			
		
	
		
			
				
					|  |  |  |  |             let typ_id = format!("%{}", *typ.clone()); | 
			
		
	
		
			
				
					|  |  |  |  |         Type::Pointer(in_typ, storage_class) => { | 
			
		
	
		
			
				
					|  |  |  |  |             emit_type(*in_typ.clone(), ops); | 
			
		
	
		
			
				
					|  |  |  |  |             let typ_id = fix_name(&typ.to_string()); | 
			
		
	
		
			
				
					|  |  |  |  |             let storage_class = match storage_class { | 
			
		
	
		
			
				
					|  |  |  |  |                 StorageClass::Input => "Input", | 
			
		
	
		
			
				
					|  |  |  |  |                 StorageClass::Output => "Output", | 
			
		
	
		
			
				
					|  |  |  |  |                 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 { | 
			
		
	
		
			
				
					|  |  |  |  |     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 { | 
			
		
	
	
		
			
				
					|  |  |  | @ -162,13 +170,15 @@ pub fn spirv_meta(module: Module) -> String { | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::StorageClass::Output => "Output", | 
			
		
	
		
			
				
					|  |  |  |  |             crate::compiler::StorageClass::Undefined => panic!("Bound a non-declared variable"), | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let typ_id = format!("%{}", _typ); | 
			
		
	
		
			
				
					|  |  |  |  |         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 { | 
			
		
	
		
			
				
					|  |  |  |  |             if has_id(op.0.clone(), &ops) { | 
			
		
	
		
			
				
					|  |  |  |  |                 continue; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             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 { | 
			
		
	
		
			
				
					|  |  |  |  |             // Decorations have the format Location 0, or Builtin FragCoord
 | 
			
		
	
		
			
				
					|  |  |  |  |             let dec = match dec { | 
			
		
	
	
		
			
				
					|  |  |  | 
 |