added returning & more asm instructions

This commit is contained in:
2025-03-22 16:54:28 -04:00
parent 7f809d797c
commit 6c2f4e814f
11 changed files with 176 additions and 43 deletions

View File

@@ -1,9 +1,11 @@
fn start() { fn start() {
print("Helld!\n"); println("Helld!");
print("Hello World!!!!!\n"); println("Hello World!!!!!");
thinger(); thinger();
print("what\n"); println("what");
exit(39); print(tester());
arger("a", "b", "c");
exit(add(35, 4));
} }
fn thinger() { fn thinger() {
@@ -14,6 +16,11 @@ fn unused() {
print("el unused\n"); print("el unused\n");
} }
fn println(msg: slice<8>) {
print(msg);
print("\n");
}
fn print(msg: slice<8>) { fn print(msg: slice<8>) {
asm (a1 = msg) { asm (a1 = msg) {
ld a2, 8, a1 ld a2, 8, a1
@@ -24,6 +31,23 @@ fn print(msg: slice<8>) {
} }
} }
fn add(a: 64, b: 64) -> 64 {
let c: 64 = 0;
asm (t0 = a, t1 = b, a0 = c) {
ld t0, 0, t0
ld t1, 0, t1
add t0, t0, t1
sd t0, 0, a0
};
c
}
fn arger(a: slice<8>, b: slice<8>, c: slice<8>) {
print(a);
print(b);
println(c);
}
fn exit(status: 64) { fn exit(status: 64) {
asm (a0 = status) { asm (a0 = status) {
ld a0, 0, a0 ld a0, 0, a0
@@ -31,3 +55,7 @@ fn exit(status: 64) {
ecall ecall
}; };
} }
fn tester() -> slice<8> {
"hola\n"
}

View File

@@ -100,9 +100,8 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
let mut v = Vec::new(); let mut v = Vec::new();
let mut stack = HashMap::new(); let mut stack = HashMap::new();
let mut stack_len = 0; let mut stack_len = 0;
let has_stack = !f.stack.is_empty() || !f.args.is_empty() || f.makes_call;
let mut stack_ra = None; let mut stack_ra = None;
if has_stack { let mut stack_rva = None;
if f.makes_call { if f.makes_call {
// return addr // return addr
stack_ra = Some(stack_len); stack_ra = Some(stack_len);
@@ -116,13 +115,23 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
stack.insert(id, stack_len); stack.insert(id, stack_len);
stack_len += align(s); stack_len += align(s);
} }
if f.ret_size > 0 {
stack_rva = Some(stack_len);
stack_len += align(&f.ret_size);
}
v.push(LI::Addi { v.push(LI::Addi {
dest: sp, dest: sp,
src: sp, src: sp,
imm: -stack_len, imm: -stack_len,
}); });
let has_stack = stack_len > 0;
if has_stack {
if let Some(stack_ra) = stack_ra { if let Some(stack_ra) = stack_ra {
v.push(LI::Sd { src: ra, offset: stack_ra, base: sp }); v.push(LI::Sd {
src: ra,
offset: stack_ra,
base: sp,
});
} }
} }
for i in &f.instructions { for i in &f.instructions {
@@ -156,6 +165,19 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
} }
IRI::Call { dest, f, args } => { IRI::Call { dest, f, args } => {
let mut offset = 0; let mut offset = 0;
if let Some((dest, s)) = dest {
offset -= align(s);
v.push(LI::Addi {
dest: t0,
src: sp,
imm: stack[&dest],
});
v.push(LI::Sd {
src: t0,
offset,
base: sp,
})
}
for (arg, s) in args { for (arg, s) in args {
let bs = align(s); let bs = align(s);
offset -= bs; offset -= bs;
@@ -191,15 +213,39 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
offset: offset as i32, offset: offset as i32,
base: r(base), base: r(base),
}), }),
AI::Sd { src, base, offset } => v.push(LI::Sd {
src: r(src),
offset: offset as i32,
base: r(base),
}),
AI::Add { dest, src1, src2 } => v.push(LI::Add {
dest: r(dest),
src1: r(src1),
src2: r(src2),
}),
} }
} }
} }
IRI::Ret { src } => todo!(), IRI::Ret { src } => {
let Some(rva) = stack_rva else {
panic!("no return value address on stack!")
};
v.push(LI::Ld {
dest: t0,
offset: rva,
base: sp,
});
mov_mem(&mut v, sp, stack[src], t0, 0, t1, align(&f.ret_size) as u32);
}
} }
} }
if has_stack { if has_stack {
if let Some(stack_ra) = stack_ra { if let Some(stack_ra) = stack_ra {
v.push(LI::Ld { dest: ra, offset: stack_ra, base: sp }); v.push(LI::Ld {
dest: ra,
offset: stack_ra,
base: sp,
});
} }
v.push(LI::Addi { v.push(LI::Addi {
dest: sp, dest: sp,
@@ -210,5 +256,5 @@ pub fn compile(program: IRLProgram) -> (Vec<u8>, Option<Addr>) {
v.push(LI::Ret); v.push(LI::Ret);
fns.push((v, *sym)); fns.push((v, *sym));
} }
create_program(fns, data, Some(program.entry())) create_program(fns, data, Some(program.entry()), &program)
} }

View File

@@ -1,11 +1,12 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::ir::Symbol; use crate::ir::{IRLProgram, Symbol};
pub fn create_program<I: Instr>( pub fn create_program<I: Instr>(
fns: Vec<(Vec<I>, Symbol)>, fns: Vec<(Vec<I>, Symbol)>,
ro_data: Vec<(Vec<u8>, Symbol)>, ro_data: Vec<(Vec<u8>, Symbol)>,
start: Option<Symbol>, start: Option<Symbol>,
program: &IRLProgram,
) -> (Vec<u8>, Option<Addr>) { ) -> (Vec<u8>, Option<Addr>) {
let mut data = Vec::new(); let mut data = Vec::new();
let mut sym_table = SymTable::new(fns.len() + ro_data.len()); let mut sym_table = SymTable::new(fns.len() + ro_data.len());
@@ -36,6 +37,16 @@ pub fn create_program<I: Instr>(
} }
} }
} }
for (s, f) in program.fns() {
println!(
"{}: {:?}",
f.name,
sym_table.get(*s).map(|a| {
let pos = a.0 + 0x1000 + 0x40 + 0x38;
format!("0x{:x}", pos)
})
);
}
assert!(missing.is_empty()); assert!(missing.is_empty());
( (
data, data,

View File

@@ -1,7 +1,4 @@
use crate::{ use crate::{compiler::arch::riscv64::*, ir::VarInst};
compiler::arch::riscv64::*,
ir::{VarID, VarInst},
};
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum RV64Instruction { pub enum RV64Instruction {
@@ -23,6 +20,16 @@ pub enum RV64Instruction {
offset: i64, offset: i64,
base: RegRef, base: RegRef,
}, },
Sd {
src: RegRef,
offset: i64,
base: RegRef,
},
Add {
dest: RegRef,
src1: RegRef,
src2: RegRef,
},
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@@ -48,6 +55,8 @@ impl std::fmt::Debug for RV64Instruction {
Self::Mv { dest, src } => write!(f, "mv {dest:?}, {src:?}"), Self::Mv { dest, src } => write!(f, "mv {dest:?}, {src:?}"),
Self::La { dest, src } => write!(f, "la {dest:?}, {src:?}"), Self::La { dest, src } => write!(f, "la {dest:?}, {src:?}"),
Self::Ld { dest, offset, base } => write!(f, "ld {dest:?}, {offset}({base:?})"), Self::Ld { dest, offset, base } => write!(f, "ld {dest:?}, {offset}({base:?})"),
Self::Sd { src, offset, base } => write!(f, "sd {src:?}, {offset}({base:?})"),
Self::Add { dest, src1, src2 } => write!(f, "add {dest:?}, {src1:?}, {src2:?}"),
} }
} }
} }

View File

@@ -9,6 +9,7 @@ pub struct IRLFunction {
pub instructions: Vec<IRLInstruction>, pub instructions: Vec<IRLInstruction>,
pub stack: HashMap<VarID, Size>, pub stack: HashMap<VarID, Size>,
pub args: Vec<(VarID, Size)>, pub args: Vec<(VarID, Size)>,
pub ret_size: Size,
pub makes_call: bool, pub makes_call: bool,
} }
@@ -34,7 +35,7 @@ pub enum IRLInstruction {
len: Len, len: Len,
}, },
Call { Call {
dest: VarID, dest: Option<(VarID, Size)>,
f: Symbol, f: Symbol,
args: Vec<(VarID, Size)>, args: Vec<(VarID, Size)>,
}, },

View File

@@ -106,8 +106,14 @@ impl IRLProgram {
makes_call = true; makes_call = true;
let fid = &p.fn_map[&f.id]; let fid = &p.fn_map[&f.id];
let sym = builder.func(fid); let sym = builder.func(fid);
let ret_size = p.size_of_var(dest.id).expect("unsized type");
let dest = if ret_size > 0 {
Some((dest.id, ret_size))
} else {
None
};
instrs.push(IRLInstruction::Call { instrs.push(IRLInstruction::Call {
dest: dest.id, dest,
f: sym, f: sym,
args: args args: args
.iter() .iter()
@@ -135,6 +141,7 @@ impl IRLProgram {
.iter() .iter()
.map(|a| (*a, p.size_of_var(*a).expect("unsized type"))) .map(|a| (*a, p.size_of_var(*a).expect("unsized type")))
.collect(), .collect(),
ret_size: p.size_of_type(&f.ret).expect("unsized type"),
stack, stack,
}, },
); );

View File

@@ -1,11 +1,12 @@
use std::fmt::Write; use std::fmt::Write;
use super::{arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, IRUInstrInst, VarID}; use super::{arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, IRUInstrInst, Type, VarID};
use crate::{common::FileSpan, compiler::arch::riscv64::Reg, util::Padder}; use crate::{common::FileSpan, compiler::arch::riscv64::Reg, util::Padder};
pub struct IRUFunction { pub struct IRUFunction {
pub name: String, pub name: String,
pub args: Vec<VarID>, pub args: Vec<VarID>,
pub ret: Type,
pub instructions: Vec<IRUInstrInst>, pub instructions: Vec<IRUInstrInst>,
} }
@@ -49,9 +50,10 @@ pub struct IRInstructions {
} }
impl IRUFunction { impl IRUFunction {
pub fn new(name: String, args: Vec<VarID>, instructions: IRInstructions) -> Self { pub fn new(name: String, args: Vec<VarID>, ret: Type, instructions: IRInstructions) -> Self {
Self { Self {
name, name,
ret,
args, args,
instructions: instructions.vec, instructions: instructions.vec,
} }

View File

@@ -1,11 +1,11 @@
// TODO: move this into ir, not parser // TODO: move this into ir, not parser
use super::{IRUProgram, Type}; use super::{IRUProgram, Type};
use crate::common::CompilerOutput; use crate::common::{CompilerMsg, CompilerOutput};
impl IRUProgram { impl IRUProgram {
pub fn validate(&self) -> CompilerOutput { pub fn validate(&self) -> CompilerOutput {
let mut output = CompilerOutput::new(); let mut output = CompilerOutput::new();
for f in self.fns.iter().flatten() { for (f, fd) in self.fns.iter().flatten().zip(&self.fn_defs) {
for i in &f.instructions { for i in &f.instructions {
match &i.i { match &i.i {
super::IRUInstruction::Mv { dest, src } => { super::IRUInstruction::Mv { dest, src } => {
@@ -35,6 +35,12 @@ impl IRUProgram {
todo!() todo!()
}; };
output.check_assign(self, ret, destty, dest.span); output.check_assign(self, ret, destty, dest.span);
if args.len() != argtys.len() {
output.err(CompilerMsg {
msg: "Wrong number of arguments to function".to_string(),
spans: vec![dest.span],
});
}
for (argv, argt) in args.iter().zip(argtys) { for (argv, argt) in args.iter().zip(argtys) {
let dest = self.get_var(argv.id); let dest = self.get_var(argv.id);
output.check_assign(self, argt, &dest.ty, argv.span); output.check_assign(self, argt, &dest.ty, argv.span);
@@ -43,7 +49,10 @@ impl IRUProgram {
super::IRUInstruction::AsmBlock { instructions, args } => { super::IRUInstruction::AsmBlock { instructions, args } => {
// TODO // TODO
} }
super::IRUInstruction::Ret { src } => todo!(), super::IRUInstruction::Ret { src } => {
let srcty = &self.get_var(src.id).ty;
output.check_assign(self, srcty, &fd.ret, src.span);
},
} }
} }
} }

View File

@@ -49,8 +49,8 @@ fn run_file(file: &str, gdb: bool) {
let output = namespace.validate(); let output = namespace.validate();
output.write_for(&mut stdout(), file); output.write_for(&mut stdout(), file);
if output.errs.is_empty() { if output.errs.is_empty() {
let program = IRLProgram::create(&namespace); let program = IRLProgram::create(&namespace).expect("morir");
let bin = compiler::compile(program.expect("morir")); let bin = compiler::compile(program);
println!("compiled"); println!("compiled");
save_run(&bin, gdb); save_run(&bin, gdb);
} }

View File

@@ -1,4 +1,4 @@
use super::{PAsmArg, FnLowerCtx, PIdent, Node, PInstruction}; use super::{FnLowerCtx, Node, PAsmArg, PIdent, PInstruction};
use crate::{ use crate::{
compiler::arch::riscv64::*, compiler::arch::riscv64::*,
ir::{ ir::{
@@ -40,6 +40,16 @@ impl RV64Instruction {
let base = RegRef::from_arg(base, ctx)?; let base = RegRef::from_arg(base, ctx)?;
Self::Ld { dest, offset, base } Self::Ld { dest, offset, base }
} }
"sd" => {
let [src, offset, base] = args else {
ctx.err("sd requires 3 arguments".to_string());
return None;
};
let src = RegRef::from_arg(src, ctx)?;
let offset = i64_from_arg(offset, ctx)?;
let base = RegRef::from_arg(base, ctx)?;
Self::Sd { src, offset, base }
}
"mv" => { "mv" => {
let [dest, src] = args else { let [dest, src] = args else {
ctx.err("la requires 2 arguments".to_string()); ctx.err("la requires 2 arguments".to_string());
@@ -49,6 +59,16 @@ impl RV64Instruction {
let src = RegRef::from_arg(src, ctx)?; let src = RegRef::from_arg(src, ctx)?;
Self::Mv { dest, src } Self::Mv { dest, src }
} }
"add" => {
let [dest, src1, src2] = args else {
ctx.err("add requires 3 arguments".to_string());
return None;
};
let dest = RegRef::from_arg(dest, ctx)?;
let src1 = RegRef::from_arg(src1, ctx)?;
let src2 = RegRef::from_arg(src2, ctx)?;
Self::Add { dest, src1, src2 }
}
w => { w => {
ctx.err_at(inst.op.span, format!("Unknown instruction '{}'", w)); ctx.err_at(inst.op.span, format!("Unknown instruction '{}'", w));
return None; return None;

View File

@@ -73,7 +73,7 @@ impl PFunction {
if let Some(src) = self.body.lower(&mut ctx) { if let Some(src) = self.body.lower(&mut ctx) {
instructions.push(IRUInstruction::Ret { src }, src.span); instructions.push(IRUInstruction::Ret { src }, src.span);
} }
IRUFunction::new(def.name.clone(), args, instructions) IRUFunction::new(def.name.clone(), args, def.ret, instructions)
} }
} }