diff --git a/src/compiler/backend/mod.rs b/src/compiler/backend/mod.rs index 5b6ada9..88cc01a 100644 --- a/src/compiler/backend/mod.rs +++ b/src/compiler/backend/mod.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod tests; -use crate::compiler::Module; +use crate::compiler::{Instruction, Module}; use std::fmt; use std::fmt::Write; @@ -395,16 +395,24 @@ pub fn compile_ast_ssa( )); } "/" => { - compile_biop("OpFDiv", &mut lst, vars, constants, types, counter, stack, out); + compile_biop( + "OpFDiv", &mut lst, vars, constants, types, counter, stack, out, + ); } "*" => { - compile_biop("OpFMul", &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( + "OpFAdd", &mut lst, vars, constants, types, counter, stack, out, + ); } "-" => { - compile_biop("OpFSub", &mut lst, vars, constants, types, counter, stack, out); + compile_biop( + "OpFSub", &mut lst, vars, constants, types, counter, stack, out, + ); } s => { panic!( @@ -466,3 +474,61 @@ pub fn compile_ast_ssa( } } } + +pub fn compile_fun_ssa(module: &mut Module) { + for fun in module.functions.iter_mut() { + assert!(fun.ast.is_some()); + let ast = fun.ast.as_mut().unwrap(); + let block = ast.clone().list().unwrap().get(0).unwrap().clone(); + let mut vars = vec![]; + let mut constants = vec![]; + let mut types = vec![]; + let mut counter = Box::new(0); + let mut stack = vec![]; + let mut out_op = vec![]; + for v in &module.globals { + vars.push((v.name.clone(), v.typ.clone())); + } + compile_ast_ssa( + block, + &mut vars, + &mut constants, + &mut types, + &mut counter, + &mut stack, + &mut out_op, + ); + let mut out_pre = vec![]; + for t in &types { + let typ = parse_type(t); + let mut type_ops = vec![]; + emit_type(typ, &mut type_ops); + for type_op in type_ops { + out_pre.push((Some(type_op.0), type_op.1)); + } + } + for c in &constants { + out_pre.push((Some(fix_name(&c.0.clone())), c.1.clone())); + } + let mut out_ops = out_pre.clone(); + for op in out_op { + if op.0.is_some() { + out_ops.push((Some(fix_name(&op.0.unwrap())), op.1)); + } else { + out_ops.push((None, op.1)); + } + } + for op in out_ops { + let split: Vec = op.1.split(" ").map(|s| s.to_string()).collect(); + let op_name: String = (&split[0]).clone(); + let op_args: Vec = split[1..].iter().map(|s| s.clone()).collect(); + let op_id = op.0.clone(); + let ins: Instruction = Instruction { + result_id: op_id, + op: op_name, + operands: op_args, + }; + fun.body.as_mut().unwrap().push(ins); + } + } +} diff --git a/src/compiler/backend/tests.rs b/src/compiler/backend/tests.rs index b8e775c..36d5734 100644 --- a/src/compiler/backend/tests.rs +++ b/src/compiler/backend/tests.rs @@ -103,3 +103,58 @@ fn test_block_ssa() { println!("----------"); assert!(stack.is_empty()); } + +#[test] +fn test_fun_ssa() { + use crate::compiler::backend::*; + use crate::compiler::*; + use crate::parser::*; + let src = " + (module Shader Logical GLSL450) + (import :std GLSL.std.450) + (bind (out-color:*f32) (Location 0)) + (dec out-color:*f32 Output) + (entry main Fragment OriginUpperLeft (:out-color)) + (fun (main) :<> + (store-ptr out-color (/ 1.0 (+ 1.0 1.0)))) +"; + let ast = parse(tokenize(src)); + let mut module = meta_compile(ast.unwrap()).unwrap(); + compile_fun_ssa(&mut module); + let res = module.functions.pop().unwrap(); + let res = res.body.unwrap(); + println!("{:#?}", res); + // TODO we need to unify the place where we call fix_name + let res_spv: Vec = vec![ + Instruction { + result_id: Some("%f32".to_string()), + op: "OpTypeFloat".to_string(), + operands: vec!["32".to_string()], + }, + Instruction { + result_id: Some("%f32_1".to_string()), + op: "OpConstant".to_string(), + operands: vec!["%f32".to_string(), "1".to_string()], + }, + Instruction { + result_id: Some("%0".to_string()), + op: "OpFAdd".to_string(), + operands: vec![ + "%f32".to_string(), + "%f32_1".to_string(), + "%f32_1".to_string(), + ], + }, + Instruction { + result_id: Some("%1".to_string()), + op: "OpFDiv".to_string(), + operands: vec!["%f32".to_string(), "%f32_1".to_string(), "%0".to_string()], + }, + Instruction { + result_id: None, + op: "OpStore".to_string(), + operands: vec!["%out_color".to_string(), "%1".to_string()], + }, + ]; + assert_eq!(res, res_spv); +}