diff --git a/src/compiler/backend/mod.rs b/src/compiler/backend/mod.rs index 53c59ac..d6ed454 100644 --- a/src/compiler/backend/mod.rs +++ b/src/compiler/backend/mod.rs @@ -145,6 +145,7 @@ fn fix_name(name: &String) -> String { .replace("-", "_") .replace("*", "p") .replace("<>", "void") + .replace(".", "_") ) } @@ -223,9 +224,26 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> { ], )); } + for global in module.globals.clone() { + let name: String = fix_name(&global.name); + + 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) => { + let builtin = match builtin { + crate::compiler::BuiltinDecoration::FragCoord => "FragCoord", + }; + format!("BuiltIn {}", builtin) + } + }; + ops.push((None, vec!["OpDecorate".to_string(), name.clone(), dec])); + } + } for global in module.globals.clone() { - let name = fix_name(&global.name); + let name: String = fix_name(&global.name); let _typ = global.typ; let storage_class = match global.storage_class { crate::compiler::StorageClass::Input => "Input", @@ -248,19 +266,6 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> { 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) => { - let builtin = match builtin { - crate::compiler::BuiltinDecoration::FragCoord => "FragCoord", - }; - format!("BuiltIn {}", builtin) - } - }; - ops.push((None, vec!["OpDecorate".to_string(), name.clone(), dec])); - } } for fun in module.functions.clone() { @@ -337,6 +342,7 @@ fn compile_biop( counter: &mut i32, stack: &mut Vec<String>, out: &mut Vec<(Option<String>, String)>, + typ: &str, ) { assert!(lst.len() == 2); let rhs = lst.pop().unwrap(); @@ -352,7 +358,7 @@ fn compile_biop( format!( "{} {} {} {}", op, - fix_name(&String::from("f32")), + fix_name(&String::from(typ)), fix_name(&lhs_id), fix_name(&rhs_id), ), @@ -360,6 +366,68 @@ fn compile_biop( stack.push(id); } +fn compile_comp_constr( + lst: &mut Vec<Ast>, + vars: &mut Vec<(String, String)>, + constants: &mut Vec<(String, String)>, + types: &mut Vec<String>, + counter: &mut i32, + stack: &mut Vec<String>, + out: &mut Vec<(Option<String>, String)>, + typ: &str, +) { + types.push(String::from(typ)); + let typ_parsed = parse_type(&String::from(typ)); + match typ_parsed { + Type::Vector(_, size) => { + assert!(lst.len() == size as usize); + let mut inners: Vec<String> = vec![]; + for _ in 0..size { + let ast = lst.pop().unwrap(); + compile_ast_ssa(ast, vars, constants, types, counter, stack, out); + let res_id = stack.pop().unwrap(); + inners.push(res_id); + } + let id = String::from(counter.to_string()); + *counter += 1; + let mut out_str = String::new(); + out_str.push_str( + format!("OpCompositeConstruct {}", fix_name(&String::from(typ))).as_str(), + ); + inners.reverse(); + for inn in inners { + out_str.push_str(format!(" {}", fix_name(&inn)).as_str()); + } + out.push((Some(id.clone()), out_str)); + stack.push(id); + } + _ => { + panic!("Invalid vector!") + } + } +} + +fn compile_comp_extract( lst: &mut Vec<Ast>, + vars: &mut Vec<(String, String)>, + constants: &mut Vec<(String, String)>, + types: &mut Vec<String>, + counter: &mut i32, + stack: &mut Vec<String>, + out: &mut Vec<(Option<String>, String)>, + typ: &str, inx: u32) { + assert!(lst.len() == 1); + let vec = lst.pop().unwrap(); + compile_ast_ssa(vec, vars, constants, types, counter, stack, out); + let vec_id = stack.pop().unwrap(); + let id = counter.to_string(); + *counter += 1; + out.push(( + Some(id.clone()), + format!("OpCompositeExtract {} {} {}", fix_name(&String::from(typ)), fix_name(&vec_id), inx), + )); + stack.push(id); +} + pub fn compile_ast_ssa( ast: Ast, vars: &mut Vec<(String, String)>, @@ -378,13 +446,82 @@ pub fn compile_ast_ssa( let fun_name = fun.symbol(); assert!(fun_name.is_some()); let fun_name = fun_name.unwrap(); + if fun_name.starts_with(".") { + let to_split = &fun_name[1..fun_name.len()]; + let split = to_split.split("-").collect::<Vec<&str>>(); + assert!(split.len() == 2); + let inx = split[0]; + let typ = split[1]; + let inx = str::parse::<u32>(inx).expect("Invalid index!"); + compile_comp_extract(&mut lst, vars, constants, types, counter, stack, out, typ, inx); + return; + } + + if fun_name.starts_with("/") { + let typ = &fun_name[1..fun_name.len()]; + compile_biop( + "OpFDiv", &mut lst, vars, constants, types, counter, stack, out, typ, + ); + return; + } + + + if fun_name.starts_with("*") { + let typ = &fun_name[1..fun_name.len()]; + compile_biop( + "OpFMul", &mut lst, vars, constants, types, counter, stack, out, typ, + ); + return; + } + + + if fun_name.starts_with("+") { + let typ = &fun_name[1..fun_name.len()]; + compile_biop( + "OpFAdd", &mut lst, vars, constants, types, counter, stack, out, typ, + ); + return; + } + + + if fun_name.starts_with("-") { + let typ = &fun_name[1..fun_name.len()]; + compile_biop( + "OpFSub", &mut lst, vars, constants, types, counter, stack, out, typ, + ); + return; + } + + if fun_name.starts_with("v") { + compile_comp_constr( + &mut lst, vars, constants, types, counter, stack, out, fun_name.as_str(), + ); + return; + } + + if fun_name.starts_with("load-ptr-") { + let typ = &fun_name[9..fun_name.len()]; + assert!(lst.len() == 1); + let ptr = lst.pop().unwrap(); + compile_ast_ssa(ptr, vars, constants, types, counter, stack, out); + let ptr_id = stack.pop().unwrap(); + let id: String = counter.to_string(); + *counter += 1; + out.push(( + Some(id.clone()), + format!("OpLoad {} {}", fix_name(&String::from(typ)), fix_name(&ptr_id)), + )); + stack.push(id); + return; + } + match fun_name.as_str() { "store-ptr" => { assert!(lst.len() == 2); - let ptr = lst.pop().unwrap(); let val = lst.pop().unwrap(); - compile_ast_ssa(ptr, vars, constants, types, counter, stack, out); + let ptr = lst.pop().unwrap(); compile_ast_ssa(val, vars, constants, types, counter, stack, out); + compile_ast_ssa(ptr, vars, constants, types, counter, stack, out); let val_id = stack.pop().unwrap(); let ptr_id = stack.pop().unwrap(); out.push(( @@ -392,26 +529,6 @@ pub fn compile_ast_ssa( format!("OpStore {} {}", fix_name(&val_id), fix_name(&ptr_id)), )); } - "/" => { - compile_biop( - "OpFDiv", &mut lst, vars, constants, types, counter, stack, out, - ); - } - "*" => { - compile_biop( - "OpFMul", &mut lst, vars, constants, types, counter, stack, out, - ); - } - "+" => { - compile_biop( - "OpFAdd", &mut lst, vars, constants, types, counter, stack, out, - ); - } - "-" => { - compile_biop( - "OpFSub", &mut lst, vars, constants, types, counter, stack, out, - ); - } s => { panic!( "Unknown function: {} with params {:#?} in context:\n{:#?}", @@ -534,6 +651,10 @@ pub fn compile_fun_ssa(module: &mut Module, ops: &Vec<(Option<String>, String)>) out_ops.push((None, op.1)); } } + + out_ops.push((None, String::from("OpReturn"))); + out_ops.push((None, String::from("OpFunctionEnd"))); + for op in out_ops { let split: Vec<String> = op.1.split(" ").map(|s| s.to_string()).collect(); let op_name: String = (&split[0]).clone(); diff --git a/src/compiler/backend/tests.rs b/src/compiler/backend/tests.rs index 6420b62..e4be473 100644 --- a/src/compiler/backend/tests.rs +++ b/src/compiler/backend/tests.rs @@ -63,7 +63,7 @@ fn test_block_ssa() { (dec out-color:*f32o Output) (entry main Fragment OriginUpperLeft (:out-color)) (fun (main) :<> - (store-ptr out-color (/ 1.0 (+ 1.0 1.0)))) + (store-ptr out-color (/f32 1.0 (+f32 1.0 1.0)))) "; let ast = parse(tokenize(src)); let mut module = meta_compile(ast.unwrap()).unwrap(); @@ -117,7 +117,7 @@ fn test_fun_ssa() { (dec out-color:*f32o Output) (entry main Fragment OriginUpperLeft (:out-color)) (fun (main) :<> - (store-ptr out-color (/ 1.0 (+ 1.0 1.0)))) + (store-ptr out-color (/f32 1.0 (+f32 1.0 1.0)))) "; let ast = parse(tokenize(src)); let mut module = meta_compile(ast.unwrap()).unwrap(); @@ -171,6 +171,40 @@ fn test_fun_ssa() { op: "OpStore".to_string(), operands: vec!["%out_color".to_string(), "%1".to_string()], }, + Instruction { + result_id: None, + op: "OpReturn".to_string(), + operands: vec![] + }, + Instruction { + result_id: None, + op: "OpFunctionEnd".to_string(), + operands: vec![] + } ]; assert_eq!(res, res_spv); } + +#[test] +fn test_fun_ssa_vec() { + use crate::compiler::backend::*; + use crate::compiler::*; + use crate::parser::*; + let src = " + (module Shader Logical GLSL450) + (import :std GLSL.std.450) + (bind (out-color:*v4f32o) (Location 0)) + (dec out-color:*v4f32o Output) + (entry main Fragment OriginUpperLeft (:out-color)) + (fun (main) :<> + (store-ptr out-color (v4f32 1.0 1.0 0.0 1.0))) +"; + let ast = parse(tokenize(src)); + let mut module = meta_compile(ast.unwrap()).unwrap(); + let ops = vec![]; + compile_fun_ssa(&mut module, &ops); + let res = module.functions.pop().unwrap(); + let res = res.body.unwrap(); + println!("{:#?}", res); + println!("{:#?}", module) +} \ No newline at end of file