From 9db2b68e7b3e4bc2e49233930bca5cac5f1f0495 Mon Sep 17 00:00:00 2001
From: itycodes <dev@itycodes.org>
Date: Mon, 10 Mar 2025 17:14:23 +0100
Subject: [PATCH] Move function preamble to backend

---
 src/compiler/backend/mod.rs   | 13 ++++++++++++-
 src/compiler/backend/tests.rs | 14 ++++++++++++++
 src/main.rs                   |  5 -----
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/compiler/backend/mod.rs b/src/compiler/backend/mod.rs
index c9c2a97..53c59ac 100644
--- a/src/compiler/backend/mod.rs
+++ b/src/compiler/backend/mod.rs
@@ -274,7 +274,6 @@ pub fn spirv_meta(module: &mut Module) -> Vec<(Option<String>, Vec<String>)> {
             }
             ops.push((Some(op.0), vec![op.1]));
         }
-        // Push OpFunctionType
         ops.push((
             Some(name.clone()),
             vec!["OpTypeFunction".to_string(), return_type.clone()],
@@ -475,6 +474,7 @@ pub fn compile_ast_ssa(
 }
 
 pub fn compile_fun_ssa(module: &mut Module, ops: &Vec<(Option<String>, String)>) {
+    let mut label_counter = Box::new(0);
     for fun in module.functions.iter_mut() {
         assert!(fun.ast.is_some());
         let ast = fun.ast.as_mut().unwrap();
@@ -515,6 +515,17 @@ pub fn compile_fun_ssa(module: &mut Module, ops: &Vec<(Option<String>, String)>)
         for c in &constants {
             out_pre.push((Some(fix_name(&c.0.clone())), c.1.clone()));
         }
+
+        // TODO non-void type
+        out_pre.push((
+            Some(fix_name(&fun.name)),
+            format!("OpFunction %void None %l_{}", fun.name),
+        ));
+        out_pre.push((
+            Some(format!("%n_{}", label_counter.to_string())),
+            "OpLabel".to_string(),
+        ));
+        *label_counter += 1;
         let mut out_ops = out_pre.clone();
         for op in out_op {
             if op.0.is_some() {
diff --git a/src/compiler/backend/tests.rs b/src/compiler/backend/tests.rs
index acbc86a..6420b62 100644
--- a/src/compiler/backend/tests.rs
+++ b/src/compiler/backend/tests.rs
@@ -138,6 +138,20 @@ fn test_fun_ssa() {
             op: "OpConstant".to_string(),
             operands: vec!["%f32".to_string(), "1".to_string()],
         },
+        Instruction {
+            result_id: Some("%main".to_string()),
+            op: "OpFunction".to_string(),
+            operands: vec![
+                "%void".to_string(),
+                "None".to_string(),
+                "%l_main".to_string(),
+            ],
+        },
+        Instruction {
+            result_id: Some("%n_0".to_string()),
+            op: "OpLabel".to_string(),
+            operands: vec![],
+        },
         Instruction {
             result_id: Some("%0".to_string()),
             op: "OpFAdd".to_string(),
diff --git a/src/main.rs b/src/main.rs
index d746ffe..ae97a6e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -84,12 +84,8 @@ fn main() -> ExitCode {
         writeln!(res).unwrap();
     }
 
-    let mut counter: u32 = 0;
     for fun in module.functions.iter() {
         // TODO non-void type
-        // TODO this should NOT be in the frontend
-        writeln!(res, "%{} = OpFunction %void None %l_{}", fun.name, fun.name).unwrap();
-        writeln!(res, "%n_{} = OpLabel", counter.to_string()).unwrap();
         for inst in fun.body.clone().unwrap().iter() {
             if let Some(id) = inst.result_id.as_ref() {
                 write!(res, "{} = ", id).unwrap();
@@ -99,7 +95,6 @@ fn main() -> ExitCode {
                 write!(res, " {}", op).unwrap();
             }
             writeln!(res).unwrap();
-            counter += 1;
         }
     }