fixing struct regurns
This commit is contained in:
parent
5c38115119
commit
0aec47e985
|
@ -9,7 +9,8 @@ Ty2 := struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
inst := Ty2.{ ty: Ty.{ a: 4, b: 1 }, c: 3 };
|
finst := Ty2.{ ty: Ty.{ a: 4, b: 1 }, c: 3 };
|
||||||
|
inst := odher_pass(finst);
|
||||||
if inst.c == 3 {
|
if inst.c == 3 {
|
||||||
return pass(&inst.ty);
|
return pass(&inst.ty);
|
||||||
}
|
}
|
||||||
|
@ -19,3 +20,7 @@ main := fn(): int {
|
||||||
pass := fn(t: *Ty): int {
|
pass := fn(t: *Ty): int {
|
||||||
return t.a - t.b;
|
return t.a - t.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
odher_pass := fn(t: Ty2): Ty2 {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
|
@ -388,7 +388,7 @@ impl<'a> Codegen<'a> {
|
||||||
let fn_label = self.labels[frame.label as usize].clone();
|
let fn_label = self.labels[frame.label as usize].clone();
|
||||||
|
|
||||||
log::dbg!("fn-args");
|
log::dbg!("fn-args");
|
||||||
let mut parama = 2..12;
|
let mut parama = 3..12;
|
||||||
for (arg, &ty) in args.iter().zip(fn_label.args.iter()) {
|
for (arg, &ty) in args.iter().zip(fn_label.args.iter()) {
|
||||||
let loc = self.load_arg(ty, &mut parama);
|
let loc = self.load_arg(ty, &mut parama);
|
||||||
self.vars.push(Variable {
|
self.vars.push(Variable {
|
||||||
|
@ -694,18 +694,50 @@ impl<'a> Codegen<'a> {
|
||||||
} => {
|
} => {
|
||||||
let func = self.get_label(*id);
|
let func = self.get_label(*id);
|
||||||
let fn_label = self.labels[func as usize].clone();
|
let fn_label = self.labels[func as usize].clone();
|
||||||
let mut parama = 2..12;
|
let mut parama = 3..12;
|
||||||
for (earg, &ty) in args.iter().zip(fn_label.args.iter()) {
|
for (earg, &ty) in args.iter().zip(fn_label.args.iter()) {
|
||||||
let arg = self.expr(earg, Some(ty))?;
|
let arg = self.expr(earg, Some(ty))?;
|
||||||
self.assert_ty(earg.pos(), ty, arg.ty);
|
self.assert_ty(earg.pos(), ty, arg.ty);
|
||||||
self.pass_arg(arg, &mut parama);
|
self.pass_arg(arg, &mut parama);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let size = self.size_of(fn_label.ret);
|
||||||
|
let loc = match size {
|
||||||
|
0 => Loc::Imm(0),
|
||||||
|
8 => Loc::RegRef(1),
|
||||||
|
16 => {
|
||||||
|
let stack = self.alloc_stack(16);
|
||||||
|
Loc::Stack(stack)
|
||||||
|
}
|
||||||
|
24..=u64::MAX => {
|
||||||
|
let stack = self.alloc_stack(size as u32);
|
||||||
|
let reg = self.gpa.allocate();
|
||||||
|
self.code
|
||||||
|
.encode(instrs::addi64(reg.0, STACK_PTR, stack as u64));
|
||||||
|
self.code.encode(instrs::cp(1, reg.0));
|
||||||
|
self.gpa.free(reg);
|
||||||
|
Loc::Stack(stack)
|
||||||
|
}
|
||||||
|
s => todo!("call return size: {}", s),
|
||||||
|
};
|
||||||
|
|
||||||
self.code.call(func);
|
self.code.call(func);
|
||||||
let reg = self.gpa.allocate();
|
|
||||||
self.code.encode(instrs::cp(reg.0, 1));
|
match size {
|
||||||
|
0 => {}
|
||||||
|
8 => {}
|
||||||
|
16 => {
|
||||||
|
if let Loc::Stack(stack) = loc {
|
||||||
|
self.store_stack(1, stack, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
24..=u64::MAX => {}
|
||||||
|
s => todo!("call return size: {}", s),
|
||||||
|
}
|
||||||
|
|
||||||
Some(Value {
|
Some(Value {
|
||||||
ty: self.ret,
|
ty: fn_label.ret,
|
||||||
loc: Loc::Reg(reg),
|
loc,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
E::Ident { name, id, .. } => {
|
E::Ident { name, id, .. } => {
|
||||||
|
@ -721,13 +753,27 @@ impl<'a> Codegen<'a> {
|
||||||
if let Some(val) = val {
|
if let Some(val) = val {
|
||||||
let val = self.expr(val, Some(self.ret))?;
|
let val = self.expr(val, Some(self.ret))?;
|
||||||
self.assert_ty(pos, self.ret, val.ty);
|
self.assert_ty(pos, self.ret, val.ty);
|
||||||
self.assign(
|
let size = self.size_of(val.ty);
|
||||||
Value {
|
match size {
|
||||||
ty: self.ret,
|
8 => {
|
||||||
loc: Loc::RegRef(1),
|
let val = self.loc_to_reg(val.loc);
|
||||||
},
|
self.code.encode(instrs::cp(1, val.0));
|
||||||
val,
|
self.gpa.free(val);
|
||||||
);
|
}
|
||||||
|
16 => {
|
||||||
|
let (ptr, off) = self.loc_to_ptr(val.loc);
|
||||||
|
self.code.encode(instrs::ld(1, ptr.0, off, 16));
|
||||||
|
self.gpa.free(ptr);
|
||||||
|
}
|
||||||
|
24..=u64::MAX => {
|
||||||
|
let (ptr, off) = self.loc_to_ptr(val.loc);
|
||||||
|
self.code.encode(instrs::addi64(ptr.0, ptr.0, off));
|
||||||
|
self.code
|
||||||
|
.encode(instrs::bmc(ptr.0, 1, size.try_into().unwrap()));
|
||||||
|
self.gpa.free(ptr);
|
||||||
|
}
|
||||||
|
s => todo!("return size: {}", s),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
self.ret_relocs.push(RetReloc {
|
self.ret_relocs.push(RetReloc {
|
||||||
offset: self.code.code.len() as u32,
|
offset: self.code.code.len() as u32,
|
||||||
|
@ -847,13 +893,15 @@ impl<'a> Codegen<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
E::BinOp { left, op, right } => {
|
E::BinOp { left, op, right } => {
|
||||||
let left = self.expr(left, expeted)?;
|
|
||||||
let right = self.expr(right, Some(left.ty))?;
|
|
||||||
if op == T::Assign {
|
if op == T::Assign {
|
||||||
|
let left = self.expr(left, expeted)?;
|
||||||
|
let right = self.expr(right, Some(left.ty))?;
|
||||||
return self.assign(left, right);
|
return self.assign(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let left = self.expr(left, expeted)?;
|
||||||
let lhs = self.loc_to_reg(left.loc);
|
let lhs = self.loc_to_reg(left.loc);
|
||||||
|
let right = self.expr(right, Some(left.ty))?;
|
||||||
let rhs = self.loc_to_reg(right.loc);
|
let rhs = self.loc_to_reg(right.loc);
|
||||||
|
|
||||||
let op = match op {
|
let op = match op {
|
||||||
|
@ -1062,6 +1110,7 @@ impl<'a> Codegen<'a> {
|
||||||
todo!("expected stack location, got {:?}", value.loc);
|
todo!("expected stack location, got {:?}", value.loc);
|
||||||
};
|
};
|
||||||
self.code.encode(instrs::addi64(p, STACK_PTR, stack));
|
self.code.encode(instrs::addi64(p, STACK_PTR, stack));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match value.loc {
|
match value.loc {
|
||||||
|
@ -1254,8 +1303,8 @@ mod tests {
|
||||||
fn generate(input: &'static str, output: &mut String) {
|
fn generate(input: &'static str, output: &mut String) {
|
||||||
let path = "test";
|
let path = "test";
|
||||||
let arena = crate::parser::Arena::default();
|
let arena = crate::parser::Arena::default();
|
||||||
let mut parser = super::parser::Parser::new(input, path, &arena);
|
let mut parser = super::parser::Parser::new(&arena);
|
||||||
let exprs = parser.file();
|
let exprs = parser.file(input, path);
|
||||||
let mut codegen = super::Codegen::default();
|
let mut codegen = super::Codegen::default();
|
||||||
codegen.file(path, input.as_bytes(), &exprs);
|
codegen.file(path, input.as_bytes(), &exprs);
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
|
|
|
@ -14,12 +14,12 @@ fn main() -> io::Result<()> {
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.map(|path| std::fs::read_to_string(&path).map(|src| (path, src)))
|
.map(|path| std::fs::read_to_string(&path).map(|src| (path, src)))
|
||||||
.collect::<io::Result<Vec<_>>>()?;
|
.collect::<io::Result<Vec<_>>>()?;
|
||||||
let mut arena = parser::Arena::default();
|
let arena = parser::Arena::default();
|
||||||
|
let mut parser = parser::Parser::new(&arena);
|
||||||
let mut codegen = codegen::Codegen::default();
|
let mut codegen = codegen::Codegen::default();
|
||||||
for (path, content) in files.iter() {
|
for (path, content) in files.iter() {
|
||||||
let file = parser::Parser::new(content, path, &arena).file();
|
let file = parser.file(&path, content.as_str());
|
||||||
codegen.file(path, content.as_bytes(), file);
|
codegen.file(path, content.as_bytes(), file);
|
||||||
arena.clear();
|
|
||||||
}
|
}
|
||||||
codegen.dump(&mut std::io::stdout())
|
codegen.dump(&mut std::io::stdout())
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,19 +23,23 @@ pub struct Parser<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Parser<'a, 'b> {
|
impl<'a, 'b> Parser<'a, 'b> {
|
||||||
pub fn new(input: &'a str, path: &'a str, arena: &'b Arena<'a>) -> Self {
|
pub fn new(arena: &'b Arena<'a>) -> Self {
|
||||||
let mut lexer = Lexer::new(input);
|
let mut lexer = Lexer::new("");
|
||||||
let token = lexer.next();
|
let token = lexer.next();
|
||||||
Self {
|
Self {
|
||||||
lexer,
|
lexer,
|
||||||
token,
|
token,
|
||||||
path,
|
path: "",
|
||||||
arena,
|
arena,
|
||||||
idents: Vec::new(),
|
idents: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file(&mut self) -> &'a [Expr<'a>] {
|
pub fn file(&mut self, input: &'a str, path: &'a str) -> &'a [Expr<'a>] {
|
||||||
|
self.path = path;
|
||||||
|
self.lexer = Lexer::new(input);
|
||||||
|
self.token = self.lexer.next();
|
||||||
|
|
||||||
let f = self.collect(|s| (s.token.kind != TokenKind::Eof).then(|| s.expr()));
|
let f = self.collect(|s| (s.token.kind != TokenKind::Eof).then(|| s.expr()));
|
||||||
self.pop_scope(0);
|
self.pop_scope(0);
|
||||||
let has_undeclared = !self.idents.is_empty();
|
let has_undeclared = !self.idents.is_empty();
|
||||||
|
@ -717,8 +721,8 @@ mod tests {
|
||||||
fn parse(input: &'static str, output: &mut String) {
|
fn parse(input: &'static str, output: &mut String) {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let mut arena = super::Arena::default();
|
let mut arena = super::Arena::default();
|
||||||
let mut parser = super::Parser::new(input, "test", &arena);
|
let mut parser = super::Parser::new(&arena);
|
||||||
for expr in parser.file() {
|
for expr in parser.file(input, "test") {
|
||||||
writeln!(output, "{}", expr).unwrap();
|
writeln!(output, "{}", expr).unwrap();
|
||||||
}
|
}
|
||||||
arena.clear();
|
arena.clear();
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 1120
|
code size: 1114
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 342
|
code size: 339
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 470
|
code size: 691
|
||||||
ret: 3
|
ret: 3
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
0
tests/hblang_codegen_tests_arithmetic.txt
Normal file
0
tests/hblang_codegen_tests_arithmetic.txt
Normal file
0
tests/hblang_codegen_tests_example.txt
Normal file
0
tests/hblang_codegen_tests_example.txt
Normal file
0
tests/hblang_codegen_tests_functions.txt
Normal file
0
tests/hblang_codegen_tests_functions.txt
Normal file
0
tests/hblang_codegen_tests_variables.txt
Normal file
0
tests/hblang_codegen_tests_variables.txt
Normal file
Loading…
Reference in a new issue