added returning & more asm instructions
This commit is contained in:
@@ -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"
|
||||||
|
}
|
||||||
|
|||||||
@@ -100,29 +100,38 @@ 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;
|
||||||
|
let mut stack_rva = None;
|
||||||
|
if f.makes_call {
|
||||||
|
// return addr
|
||||||
|
stack_ra = Some(stack_len);
|
||||||
|
stack_len += 8;
|
||||||
|
}
|
||||||
|
for (id, s) in &f.stack {
|
||||||
|
stack.insert(id, stack_len);
|
||||||
|
stack_len += align(s);
|
||||||
|
}
|
||||||
|
for (id, s) in f.args.iter().rev() {
|
||||||
|
stack.insert(id, stack_len);
|
||||||
|
stack_len += align(s);
|
||||||
|
}
|
||||||
|
if f.ret_size > 0 {
|
||||||
|
stack_rva = Some(stack_len);
|
||||||
|
stack_len += align(&f.ret_size);
|
||||||
|
}
|
||||||
|
v.push(LI::Addi {
|
||||||
|
dest: sp,
|
||||||
|
src: sp,
|
||||||
|
imm: -stack_len,
|
||||||
|
});
|
||||||
|
let has_stack = stack_len > 0;
|
||||||
if has_stack {
|
if has_stack {
|
||||||
if f.makes_call {
|
|
||||||
// return addr
|
|
||||||
stack_ra = Some(stack_len);
|
|
||||||
stack_len += 8;
|
|
||||||
}
|
|
||||||
for (id, s) in &f.stack {
|
|
||||||
stack.insert(id, stack_len);
|
|
||||||
stack_len += align(s);
|
|
||||||
}
|
|
||||||
for (id, s) in f.args.iter().rev() {
|
|
||||||
stack.insert(id, stack_len);
|
|
||||||
stack_len += align(s);
|
|
||||||
}
|
|
||||||
v.push(LI::Addi {
|
|
||||||
dest: sp,
|
|
||||||
src: sp,
|
|
||||||
imm: -stack_len,
|
|
||||||
});
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)>,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user