]> rethought.computer Git - sorel-lang.git/commitdiff
mostly complete asm generation keep/02e65853c456b7e0d9cb98180c96aac02b2f91a6
authorBryan English <bryan@rethought.computer>
Mon, 19 Jan 2026 03:58:34 +0000 (22:58 -0500)
committerBryan English <bryan@rethought.computer>
Tue, 10 Feb 2026 04:08:54 +0000 (04:08 +0000)
hylo-lang/hyloc/src/main.rs
hylo-lang/hyloc/src/riscv_asm_codegen.rs

index 275e0312d9b94a01b1f00b5ce762367010a40df5..579930c001a177a229bf89c7759e33de110b4c40 100644 (file)
@@ -10,7 +10,9 @@ use anyhow::Result;
 fn main() -> Result<()> {
     let filename = std::env::args().nth(1).expect("must provide a file to compile");
     let module = ir::compile(&filename)?;
-    let mut interp = Interpreter::new(&module)?;
-    interp.run()?;
+    // let mut interp = Interpreter::new(&module)?;
+    // interp.run()?;
+    let mut generator = riscv_asm_codegen::CodeGen::new(&module, 4096);
+    println!("{}", generator.assembly()?);
     Ok(())
 }
index 521d95bbb499be53ecbbf790a7e9198591054363..7810f5637e18a948e651b7ed795718915e07ceb8 100644 (file)
@@ -2,13 +2,65 @@ use hylo_ir::*;
 
 use anyhow::*;
 
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
 
 pub struct CodeGen<'a> {
     module: &'a IRModule,
     data_stack_size: usize,
 }
 
+
+// Some inspiration
+// ================
+//
+// * https://github.com/aw/fiveforths/blob/master/docs/REFERENCE.md#registers-list
+//     * Except using sp as a more C ABI style stack pointer, and s2 for the data stack
+// 
+
+// Implementation Choices
+// ======================
+//
+// Data Stack pointer: s2
+// No return stack pointer (using C ABI, so sp, sorta)
+// Use t0, t1, t2 for temporary values in words
+// Data stack grows down
+
+
+macro_rules! asm_macro {
+    ($name:ident, $src:expr) => {
+        fn $name(lines: &mut Vec<String>) {
+            lines.push($src.to_string());
+        }
+    };
+    ($name:ident, $src:expr, $arg0:ty) => {
+        fn $name(lines: &mut Vec<String>, val0: $arg0) {
+            lines.push(format!($src, val0));
+        }
+    };
+    ($name:ident, $src:expr, $arg0:ty, $arg1:ty) => {
+        fn $name(lines: &mut Vec<String>, val0: $arg0, val1: $arg1) {
+            lines.push(format!($src, val0, val1));
+        }
+    };
+}
+
+asm_macro!(copy_top_stack_value_to, "    lw   {}, 0(s2)", &str);
+asm_macro!(copy_offset_stack_value_to, "    lw   {}, {}*8(s2)", &str, isize);
+asm_macro!(deref_pointer_to_from, "    lw   {}, 0({})", &str, &str);
+asm_macro!(copy_to_top_of_stack, "    sw {}, 0(s2)", &str);
+asm_macro!(move_stack_ptr_by_cells, "    addi s2, s2, {}*8", isize);
+
+fn pop_to(lines: &mut Vec<String>, reg: &str) {
+    copy_top_stack_value_to(lines, reg);
+    move_stack_ptr_by_cells(lines, 1);
+}
+
+fn push_from(lines: &mut Vec<String>, reg: &str) {
+    move_stack_ptr_by_cells(lines, -1);
+    copy_to_top_of_stack(lines, reg);
+}
+
+
 impl<'a> CodeGen<'a> {
     pub fn new(ir_mod: &'a IRModule, data_stack_size: usize) -> Self {
         Self {
@@ -42,11 +94,16 @@ impl<'a> CodeGen<'a> {
         lines.push(".data\n".to_string());
         lines.push("data_stack:".to_string());
         lines.push(format!("    .space {}", self.data_stack_size));
+        lines.push("data_stack_end:".to_string());
 
         // Code
         // TODO align?
         lines.push(".text\n".to_string());
 
+        let mut if_block_count = 0;
+        let mut if_stack = vec![];
+        let mut seen_else = HashSet::new();
+
         for ir in &self.module.text {
             match ir {
                 IR::Label(name) => {
@@ -62,6 +119,151 @@ impl<'a> CodeGen<'a> {
                     lines.push("    addi sp, sp, 16".to_string()); // restore stack pointer
                     lines.push("    ret".to_string());
                 },
+                IR::Load => {
+                    copy_top_stack_value_to(&mut lines, "t0");
+                    deref_pointer_to_from(&mut lines, "t0", "t0");
+                    copy_to_top_of_stack(&mut lines, "t0");
+                },
+                IR::Store => { // ( x addr -- )
+                    copy_top_stack_value_to(&mut lines, "t1");
+                    copy_offset_stack_value_to(&mut lines, "t0", 1);
+                    lines.push("    sw t0, 0(t1)".to_string());                // store x at addr 
+                    move_stack_ptr_by_cells(&mut lines, 2);
+                },
+                IR::StackPush(num) => {
+                    lines.push(format!("    li t0, {}", num));
+                    push_from(&mut lines, "t0");
+                },
+                IR::AddU64 => {
+                    pop_to(&mut lines, "t0");
+                    pop_to(&mut lines, "t1");
+                    lines.push("    addi t0, t0, t1".to_string());
+                    push_from(&mut lines, "t0");
+                },
+                IR::SubtractU64 => {
+                    pop_to(&mut lines, "t1");
+                    pop_to(&mut lines, "t0");
+                    lines.push("    sub  t0, t0, t1".to_string());
+                    push_from(&mut lines, "t0");
+                },
+                IR::Dup => {
+                    copy_top_stack_value_to(&mut lines, "t0");
+                    push_from(&mut lines, "t0");
+                },
+                IR::Swap => {
+                    pop_to(&mut lines, "t0");
+                    pop_to(&mut lines, "t1");
+                    push_from(&mut lines, "t0");
+                    push_from(&mut lines, "t1");
+                },
+                IR::Drop => {
+                    move_stack_ptr_by_cells(&mut lines, 1);
+                },
+                IR::Equals => {
+                    // Yes, this is the same as subtract, since we're treating 0 as true, and
+                    // others as false.
+                    pop_to(&mut lines, "t1");
+                    pop_to(&mut lines, "t0");
+                    lines.push("    sub  t0, t0, t1".to_string());
+                    push_from(&mut lines, "t0");
+                },
+                IR::GreaterThan => {
+                    pop_to(&mut lines, "t1");
+                    pop_to(&mut lines, "t0");
+                    lines.push("    sgt  t0, t0, t1".to_string());
+                    lines.push("    seqz t0, t0".to_string()); // remember, 0 is true, others are
+                                                               // false
+                    push_from(&mut lines, "t0");
+                },
+                IR::BitwiseOr => {
+                    pop_to(&mut lines, "t1");
+                    pop_to(&mut lines, "t0");
+                    lines.push("    or   t0, t0, t1".to_string());
+                    push_from(&mut lines, "t0");
+                },
+                IR::Sys0 => {
+                    pop_to(&mut lines, "a7");
+                    lines.push("    ecall".to_string());
+                    push_from(&mut lines, "a0");
+                },
+                IR::Sys1 => {
+                    pop_to(&mut lines, "a7");
+                    pop_to(&mut lines, "a0");
+                    lines.push("    ecall".to_string());
+                    push_from(&mut lines, "a0");
+                },
+                IR::Sys2 => {
+                    pop_to(&mut lines, "a7");
+                    pop_to(&mut lines, "a1");
+                    pop_to(&mut lines, "a0");
+                    lines.push("    ecall".to_string());
+                    push_from(&mut lines, "a0");
+                },
+                IR::Sys3 => {
+                    pop_to(&mut lines, "a7");
+                    pop_to(&mut lines, "a2");
+                    pop_to(&mut lines, "a1");
+                    pop_to(&mut lines, "a0");
+                    lines.push("    ecall".to_string());
+                    push_from(&mut lines, "a0");
+                },
+                IR::Sys4 => {
+                    pop_to(&mut lines, "a7");
+                    pop_to(&mut lines, "a3");
+                    pop_to(&mut lines, "a2");
+                    pop_to(&mut lines, "a1");
+                    pop_to(&mut lines, "a0");
+                    lines.push("    ecall".to_string());
+                    push_from(&mut lines, "a0");
+                },
+                IR::Sys5 => {
+                    pop_to(&mut lines, "a7");
+                    pop_to(&mut lines, "a4");
+                    pop_to(&mut lines, "a3");
+                    pop_to(&mut lines, "a2");
+                    pop_to(&mut lines, "a1");
+                    pop_to(&mut lines, "a0");
+                    lines.push("    ecall".to_string());
+                    push_from(&mut lines, "a0");
+                },
+                IR::Sys6 => {
+                    pop_to(&mut lines, "a7");
+                    pop_to(&mut lines, "a5");
+                    pop_to(&mut lines, "a4");
+                    pop_to(&mut lines, "a3");
+                    pop_to(&mut lines, "a2");
+                    pop_to(&mut lines, "a1");
+                    pop_to(&mut lines, "a0");
+                    lines.push("    ecall".to_string());
+                    push_from(&mut lines, "a0");
+                },
+                IR::PutN => {
+                    lines.push("    call putn".to_string());
+                },
+                // https://cmput229.github.io/229-labs-RISCV/RISC-V-Examples_Public/03-Conditionals/03b-If_Else.html
+                IR::If => {
+                    pop_to(&mut lines, "t0");
+                    lines.push(format!("    bnez t0, _else_{}", if_block_count));
+                    if_stack.push(if_block_count);
+                    if_block_count += 1;
+                },
+                IR::Else => {
+                    let if_counter = if_stack.last().unwrap().clone();
+                    lines.push(format!("    j _endif_{}", if_counter));
+                    lines.push(format!("_else_{}:", if_counter));
+                    seen_else.insert(if_counter);
+                },
+                IR::EndIf => {
+                    let stack = &mut if_stack;
+                    let if_counter = stack.last().unwrap().clone();
+                    if !seen_else.contains(&if_counter) {
+                        lines.push(format!("_else_{}:", if_counter));
+                    } else {
+                        lines.push(format!("_endif_{}:", if_counter));
+                        seen_else.remove(&if_counter);
+                    }
+                    stack.pop();
+                }
                 _ => bail!("not implemented yet"),
             }
         }
@@ -69,3 +271,4 @@ impl<'a> CodeGen<'a> {
         Ok(lines.join("\n"))
     }
 }
+