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