From 73c9ccef6a0e0ff39aea4888b26a0c3525a16f88 Mon Sep 17 00:00:00 2001 From: Jakub Doka Date: Mon, 21 Oct 2024 17:04:29 +0200 Subject: [PATCH] simplifing code patterns and sixing argument passing --- lang/src/codegen.rs | 54 ++++----- lang/src/lib.rs | 49 ++++++-- lang/src/son.rs | 168 ++++++++++++--------------- lang/tests/son_tests_inline_test.txt | 11 +- lang/tests/son_tests_wide_ret.txt | 45 +++---- 5 files changed, 169 insertions(+), 158 deletions(-) diff --git a/lang/src/codegen.rs b/lang/src/codegen.rs index a80564ea..1a4273e8 100644 --- a/lang/src/codegen.rs +++ b/lang/src/codegen.rs @@ -8,7 +8,7 @@ use { }, reg, ty::{self, TyCheck}, - Comptime, Field, Func, Global, OffsetIter, ParamAlloc, Reloc, Sig, Struct, SymKey, + Comptime, Field, Func, Global, OffsetIter, PLoc, ParamAlloc, Reloc, Sig, Struct, SymKey, TypeParser, TypedReloc, Types, }, alloc::{string::String, vec::Vec}, @@ -1037,7 +1037,7 @@ impl Codegen { ); }; - let mut parama = self.tys.parama(ty); + let (_, mut parama) = self.tys.parama(ty); let base = self.pool.arg_locs.len(); for arg in args { let arg = self.expr(arg)?; @@ -1402,7 +1402,7 @@ impl Codegen { unreachable!(); }; - let mut parama = self.tys.parama(sig.ret); + let (_, mut parama) = self.tys.parama(sig.ret); let base = self.pool.arg_locs.len(); let mut sig_args = sig.args.range(); let mut should_momize = !args.is_empty() && sig.ret == ty::Id::from(ty::TYPE); @@ -2135,7 +2135,7 @@ impl Codegen { self.ci.emit_prelude(); - let mut parama = self.tys.parama(sig.ret); + let (ret, mut parama) = self.tys.parama(sig.ret); let mut sig_args = sig.args.range(); for arg in args.iter() { let ty = self.tys.ins.args[sig_args.next().unwrap()]; @@ -2147,7 +2147,7 @@ impl Codegen { self.ci.vars.push(Variable { id: arg.id, value: Value { ty, loc } }); } - if self.tys.size_of(sig.ret) > 16 { + if let PLoc::Ref(..) = ret { let reg = self.ci.regs.allocate(); self.ci.emit(instrs::cp(reg.get(), 1)); self.ci.ret_reg = reg; @@ -2179,20 +2179,21 @@ impl Codegen { if size == 0 { return Loc::default(); } - let (src, dst) = match size { - 0 => (Loc::default(), Loc::default()), - ..=8 if flags & idfl::REFERENCED == 0 => { - (Loc::reg(parama.next()), Loc::reg(self.ci.regs.allocate())) + let (src, dst) = match parama.next(ty, &self.tys) { + PLoc::None => (Loc::default(), Loc::default()), + PLoc::Reg(r, _) if flags & idfl::REFERENCED == 0 => { + (Loc::reg(r), Loc::reg(self.ci.regs.allocate())) } - 1..=8 => (Loc::reg(parama.next()), Loc::stack(self.ci.stack.allocate(size))), - 9..=16 => (Loc::reg(parama.next_wide()), Loc::stack(self.ci.stack.allocate(size))), - _ if flags & (idfl::MUTABLE | idfl::REFERENCED) == 0 => { - let ptr = parama.next(); + PLoc::Reg(r, _) => (Loc::reg(r), Loc::stack(self.ci.stack.allocate(size))), + PLoc::WideReg(r, _) => (Loc::reg(r), Loc::stack(self.ci.stack.allocate(size))), + PLoc::Ref(ptr, _) if flags & (idfl::MUTABLE | idfl::REFERENCED) == 0 => { let reg = self.ci.regs.allocate(); self.ci.emit(instrs::cp(reg.get(), ptr)); return Loc::reg(reg).into_derefed(); } - _ => (Loc::reg(parama.next()).into_derefed(), Loc::stack(self.ci.stack.allocate(size))), + PLoc::Ref(ptr, _) => { + (Loc::reg(ptr).into_derefed(), Loc::stack(self.ci.stack.allocate(size))) + } }; self.store_sized(src, &dst, size); @@ -2265,23 +2266,16 @@ impl Codegen { } fn pass_arg(&mut self, value: &Value, parama: &mut ParamAlloc) { - self.pass_arg_low(&value.loc, self.tys.size_of(value.ty), parama) - } - - fn pass_arg_low(&mut self, loc: &Loc, size: Size, parama: &mut ParamAlloc) { - if size > 16 { - let Loc::Rt { reg, stack, offset, .. } = loc else { unreachable!() }; - self.stack_offset(parama.next(), reg.get(), stack.as_ref(), *offset as _); - return; + match parama.next(value.ty, &self.tys) { + PLoc::None => {} + PLoc::Reg(r, _) | PLoc::WideReg(r, _) => { + self.store_typed(&value.loc, Loc::reg(r), value.ty) + } + PLoc::Ref(ptr, _) => { + let Loc::Rt { reg, stack, offset, .. } = &value.loc else { unreachable!() }; + self.stack_offset(ptr, reg.get(), stack.as_ref(), *offset as _); + } } - - let dst = match size { - 0 => return, - 9..=16 => Loc::reg(parama.next_wide()), - _ => Loc::reg(parama.next()), - }; - - self.store_sized(loc, dst, size); } fn store_typed(&mut self, src: impl Into, dst: impl Into, ty: ty::Id) { diff --git a/lang/src/lib.rs b/lang/src/lib.rs index afc117a9..24a16e10 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -21,7 +21,8 @@ str_from_raw_parts, ptr_sub_ptr, slice_from_ptr_range, - is_sorted + is_sorted, + iter_next_chunk )] #![feature(pointer_is_aligned_to)] #![warn(clippy::dbg_macro)] @@ -247,7 +248,7 @@ mod ty { ident, lexer::TokenKind, parser::{self, Pos}, - Size, + Size, Types, }, core::{num::NonZeroU32, ops::Range}, }; @@ -405,6 +406,21 @@ mod ty { Self::UINT } } + + pub fn loc(&self, tys: &Types) -> Loc { + match self.expand() { + Kind::Ptr(_) | Kind::Builtin(_) => Loc::Reg, + Kind::Struct(_) if tys.size_of(*self) == 0 => Loc::Reg, + Kind::Struct(_) | Kind::Slice(_) => Loc::Stack, + Kind::Func(_) | Kind::Global(_) | Kind::Module(_) => unreachable!(), + } + } + } + + #[derive(PartialEq, Eq, Clone, Copy)] + pub enum Loc { + Reg, + Stack, } #[derive(PartialEq, Eq, Default, Debug, Clone, Copy)] @@ -771,15 +787,23 @@ impl Array { } } +enum PLoc { + None, + Reg(u8, u16), + WideReg(u8, u16), + Ref(u8, u32), +} + struct ParamAlloc(Range); impl ParamAlloc { - pub fn next(&mut self) -> u8 { - self.0.next().expect("too many paramteters") - } - - fn next_wide(&mut self) -> u8 { - (self.next(), self.next()).0 + pub fn next(&mut self, ty: ty::Id, tys: &Types) -> PLoc { + match tys.size_of(ty) { + 0 => PLoc::None, + size @ 1..=8 => PLoc::Reg(self.0.next().unwrap(), size as _), + size @ 9..=16 => PLoc::WideReg(self.0.next_chunk::<2>().unwrap()[0], size as _), + size @ 17.. => PLoc::Ref(self.0.next().unwrap(), size), + } } } @@ -1202,8 +1226,13 @@ impl Types { instrs::disasm(&mut sluce, &functions, output, eca_handler) } - fn parama(&self, ret: impl Into) -> ParamAlloc { - ParamAlloc(2 + (9..=16).contains(&self.size_of(ret.into())) as u8..12) + fn parama(&self, ret: impl Into) -> (PLoc, ParamAlloc) { + let mut iter = ParamAlloc(1..12); + let ret = iter.next(ret.into(), self); + if let PLoc::None = ret { + iter.0.start += 1; + } + (ret, iter) } fn make_ptr(&mut self, base: ty::Id) -> ty::Id { diff --git a/lang/src/son.rs b/lang/src/son.rs index 31898110..2ea58427 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -10,10 +10,10 @@ use { CtorField, Expr, ExprRef, FileId, Pos, }, reg, task, - ty::{self, ArrayLen, Tuple}, + ty::{self, ArrayLen, Loc, Tuple}, vc::{BitSet, Vc}, - Comptime, Func, Global, HashMap, Offset, OffsetIter, Reloc, Sig, TypeParser, TypedReloc, - Types, + Comptime, Func, Global, HashMap, Offset, OffsetIter, PLoc, Reloc, Sig, TypeParser, + TypedReloc, Types, }, alloc::{string::String, vec::Vec}, core::{ @@ -1093,20 +1093,16 @@ impl ItemCtx { *saved_regs.entry(hvenc).or_insert(would_insert) }; - let mut parama = tys.parama(sig.ret); - + let (retl, mut parama) = tys.parama(sig.ret); for (ti, &arg) in sig.args.range().zip(fuc.nodes[VOID].outputs.iter().skip(2)) { let ty = tys.ins.args[ti]; - if tys.size_of(ty) == 0 { - continue; - } - if let size @ 9..=16 = tys.size_of(ty) { - let rg = parama.next_wide(); - self.emit(instrs::st(rg, reg::STACK_PTR, fuc.nodes[arg].offset as _, size as _)); - self.emit(instrs::addi64(rg, reg::STACK_PTR, fuc.nodes[arg].offset as _)); - } else { - parama.next(); - } + let (rg, size) = match parama.next(ty, tys) { + PLoc::WideReg(rg, size) => (rg, size), + PLoc::Reg(rg, size) if ty.loc(tys) == Loc::Stack => (rg, size), + PLoc::Reg(..) | PLoc::Ref(..) | PLoc::None => continue, + }; + self.emit(instrs::st(rg, reg::STACK_PTR, fuc.nodes[arg].offset as _, size)); + self.emit(instrs::addi64(rg, reg::STACK_PTR, fuc.nodes[arg].offset as _)); } for (i, block) in fuc.blocks.iter().enumerate() { @@ -1177,17 +1173,13 @@ impl ItemCtx { } } Kind::Return => { - match tys.size_of(sig.ret) { - 0..=8 => {} - size @ 9..=16 => { - self.emit(instrs::ld(reg::RET, atr(allocs[0]), 0, size as _)); + match retl { + PLoc::None | PLoc::Reg(..) => {} + PLoc::WideReg(r, size) => { + self.emit(instrs::ld(r, atr(allocs[0]), 0, size)) } - size @ 17.. => { - self.emit(instrs::bmc( - atr(allocs[0]), - reg::RET, - size.try_into().unwrap(), - )); + PLoc::Ref(r, size) => { + self.emit(instrs::bmc(atr(allocs[0]), r, size.try_into().unwrap())); } } @@ -1243,14 +1235,29 @@ impl ItemCtx { } } Kind::Call { func } => { + let (ret, mut parama) = tys.parama(node.ty); + let mut allocs = allocs.iter(); + for ti in tys.ins.funcs[func as usize].sig.unwrap().args.range() { + let ty = tys.ins.args[ti]; + let (rg, size) = match parama.next(ty, tys) { + PLoc::Reg(rg, size) if ty.loc(tys) == Loc::Stack => (rg, size), + PLoc::WideReg(rg, size) => (rg, size), + PLoc::None | PLoc::Ref(..) | PLoc::Reg(..) => continue, + }; + let &arg = allocs.next().unwrap(); + if size > 8 { + allocs.next().unwrap(); + } + self.emit(instrs::ld(rg, atr(arg), 0, size)); + } self.relocs.push(TypedReloc { target: ty::Kind::Func(func).compress(), reloc: Reloc::new(self.code.len(), 3, 4), }); self.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0)); - if let size @ 9..=16 = tys.size_of(node.ty) { + if let PLoc::WideReg(r, size) = ret { let stck = fuc.nodes[*node.inputs.last().unwrap()].offset; - self.emit(instrs::st(reg::RET, reg::STACK_PTR, stck as _, size as _)); + self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size)); } } Kind::Global { global } => { @@ -1589,6 +1596,7 @@ impl TypeParser for Codegen<'_> { code: core::mem::take(&mut self.ci.code), ..Default::default() }; + self.pool.pop_ci(&mut self.ci); self.complete_call_graph(); @@ -2043,12 +2051,8 @@ impl<'a> Codegen<'a> { let mut inps = Vc::from([self.ci.ctrl]); for ((arg, carg), tyx) in args.iter().zip(cargs).zip(sig.args.range()) { let ty = self.tys.ins.args[tyx]; - if self.tys.size_of(ty) == 0 { - continue; - } let mut value = self.expr_ctx(arg, Ctx::default().with_ty(ty))?; debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre); - debug_assert_ne!(value.id, 0); self.assert_ty(arg.pos(), &mut value, ty, fa!("argument {}", carg.name)); self.ci.nodes.lock(value.id); @@ -2074,9 +2078,9 @@ impl<'a> Codegen<'a> { false }); - let alt_value = match self.tys.size_of(sig.ret) { - 0..=8 => None, - 9.. => { + let alt_value = match sig.ret.loc(&self.tys) { + Loc::Reg => None, + Loc::Stack => { let stck = self.ci.nodes.new_node_nop(sig.ret, Kind::Stck, [VOID, MEM]); inps.push(stck); Some(Value::ptr(stck).ty(sig.ret)) @@ -2692,7 +2696,7 @@ impl<'a> Codegen<'a> { for arg in args.iter() { let ty = self.tys.ins.args[sig_args.next().unwrap()]; let mut deps = Vc::from([VOID]); - if matches!(self.tys.size_of(ty), 9..=16) { + if ty.loc(&self.tys) == Loc::Stack { deps.push(MEM); } let value = self.ci.nodes.new_node_nop(ty, Kind::Arg, [VOID]); @@ -2994,18 +2998,15 @@ impl<'a> Function<'a> { } } Kind::Return => { - let ops = match self.tys.size_of(self.sig.ret) { - 0 => vec![], - 1..=8 => { + let ops = match self.tys.parama(self.sig.ret).0 { + PLoc::None => vec![], + PLoc::Reg(r, ..) => { vec![regalloc2::Operand::reg_fixed_use( self.rg(node.inputs[1]), - regalloc2::PReg::new(1, regalloc2::RegClass::Int), + regalloc2::PReg::new(r as _, regalloc2::RegClass::Int), )] } - 9..=16 => { - vec![self.urg(self.nodes[node.inputs[1]].inputs[1])] - } - 17.. => { + PLoc::WideReg(..) | PLoc::Ref(..) => { vec![self.urg(self.nodes[node.inputs[1]].inputs[1])] } }; @@ -3035,32 +3036,17 @@ impl<'a> Function<'a> { Kind::Entry => { self.nodes[nid].ralloc_backref = self.add_block(nid); - let mut parama = self.tys.parama(self.sig.ret); + let (_, mut parama) = self.tys.parama(self.sig.ret); for (ti, arg) in self.sig.args.range().zip(self.nodes[VOID].clone().outputs.into_iter().skip(2)) { let ty = self.tys.ins.args[ti]; - match self.tys.size_of(ty) { - 0 => continue, - 1..=8 => { + match parama.next(ty, self.tys) { + PLoc::None => {} + PLoc::Reg(r, _) | PLoc::WideReg(r, _) | PLoc::Ref(r, _) => { self.add_instr(NEVER, vec![regalloc2::Operand::reg_fixed_def( self.rg(arg), - regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int), - )]); - } - 9..=16 => { - self.add_instr(NEVER, vec![regalloc2::Operand::reg_fixed_def( - self.rg(arg), - regalloc2::PReg::new( - parama.next_wide() as _, - regalloc2::RegClass::Int, - ), - )]); - } - _ => { - self.add_instr(NEVER, vec![regalloc2::Operand::reg_fixed_def( - self.rg(arg), - regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int), + regalloc2::PReg::new(r as _, regalloc2::RegClass::Int), )]); } } @@ -3120,20 +3106,18 @@ impl<'a> Function<'a> { )); } - let mut parama = self.tys.parama(fuc.ret); - let mut inps = node.inputs[1..].iter(); - for ti in fuc.args.range() { + let (ret, mut parama) = self.tys.parama(fuc.ret); + for (ti, &(mut i)) in fuc.args.range().zip(node.inputs[1..].iter()) { let ty = self.tys.ins.args[ti]; - match self.tys.size_of(ty) { - 0 => continue, - 1..=8 => { + match parama.next(ty, self.tys) { + PLoc::None => {} + PLoc::Reg(r, _) => { ops.push(regalloc2::Operand::reg_fixed_use( - self.rg(*inps.next().unwrap()), - regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int), + self.rg(i), + regalloc2::PReg::new(r as _, regalloc2::RegClass::Int), )); } - 9..=16 => { - let mut i = *inps.next().unwrap(); + PLoc::WideReg(r, _) => { loop { match self.nodes[i].kind { Kind::Stre { .. } => i = self.nodes[i].inputs[2], @@ -3145,15 +3129,14 @@ impl<'a> Function<'a> { debug_assert!(i != 0); ops.push(regalloc2::Operand::reg_fixed_use( self.rg(i), - regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int), + regalloc2::PReg::new(r as _, regalloc2::RegClass::Int), )); ops.push(regalloc2::Operand::reg_fixed_use( self.rg(i), - regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int), + regalloc2::PReg::new(r as usize + 1, regalloc2::RegClass::Int), )); } - _ => { - let mut i = *inps.next().unwrap(); + PLoc::Ref(r, _) => { loop { match self.nodes[i].kind { Kind::Stre { .. } => i = self.nodes[i].inputs[2], @@ -3165,20 +3148,17 @@ impl<'a> Function<'a> { debug_assert!(i != 0); ops.push(regalloc2::Operand::reg_fixed_use( self.rg(i), - regalloc2::PReg::new(parama.next() as _, regalloc2::RegClass::Int), + regalloc2::PReg::new(r as _, regalloc2::RegClass::Int), )); } } } - match self.tys.size_of(fuc.ret) { - 0..=16 => {} - 17.. => { - ops.push(regalloc2::Operand::reg_fixed_use( - self.rg(*node.inputs.last().unwrap()), - regalloc2::PReg::new(1, regalloc2::RegClass::Int), - )); - } + if let PLoc::Ref(r, _) = ret { + ops.push(regalloc2::Operand::reg_fixed_use( + self.rg(*node.inputs.last().unwrap()), + regalloc2::PReg::new(r as _, regalloc2::RegClass::Int), + )); } self.add_instr(nid, ops); @@ -3203,6 +3183,7 @@ impl<'a> Function<'a> { // .iter() // .all(|&n| matches!(self.nodes[n].kind, Kind::Stre | Kind::Load))) // }) => {} + Kind::Stck if self.tys.size_of(node.ty) == 0 => self.nodes.lock(nid), Kind::Stck => { let ops = vec![self.drg(nid)]; self.add_instr(nid, ops); @@ -3212,6 +3193,9 @@ impl<'a> Function<'a> { self.add_instr(nid, ops); } Kind::Phi | Kind::Arg | Kind::Mem => {} + Kind::Load { .. } if matches!(self.tys.size_of(node.ty), 0 | 9..) => { + self.nodes.lock(nid) + } Kind::Load { .. } => { let mut region = node.inputs[1]; if self.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add }) @@ -3219,13 +3203,11 @@ impl<'a> Function<'a> { { region = self.nodes[region].inputs[1] } - if self.tys.size_of(node.ty) <= 8 { - let ops = match self.nodes[region].kind { - Kind::Stck => vec![self.drg(nid)], - _ => vec![self.drg(nid), self.urg(region)], - }; - self.add_instr(nid, ops); - } + let ops = match self.nodes[region].kind { + Kind::Stck => vec![self.drg(nid)], + _ => vec![self.drg(nid), self.urg(region)], + }; + self.add_instr(nid, ops); } Kind::Stre if node.inputs[2] == VOID => self.nodes.lock(nid), Kind::Stre => { diff --git a/lang/tests/son_tests_inline_test.txt b/lang/tests/son_tests_inline_test.txt index a8a2c336..1220e09b 100644 --- a/lang/tests/son_tests_inline_test.txt +++ b/lang/tests/son_tests_inline_test.txt @@ -47,6 +47,9 @@ main: CP r2, r3 CP r4, r5 CP r6, r7 + LD r2, r2, 0a, 16h + LD r4, r4, 0a, 16h + LD r6, r6, 0a, 16h JAL r31, r0, :line ADDI64 r7, r254, 0d ADDI64 r5, r254, 16d @@ -61,6 +64,9 @@ main: CP r2, r3 CP r4, r5 CP r6, r7 + LD r2, r2, 0a, 16h + LD r4, r4, 0a, 16h + LD r6, r6, 0a, 16h JAL r31, r0, :rect_line JAL r31, r0, :example LD r31, r254, 96a, 16h @@ -86,7 +92,6 @@ rect_line: 2: ADDI64 r9, r9, 1d JMP :4 1: JALA r0, r31, 0a -timed out -code size: 797 -ret: 0 +code size: 875 +ret: 4 status: Ok(()) diff --git a/lang/tests/son_tests_wide_ret.txt b/lang/tests/son_tests_wide_ret.txt index 1f82bec9..2ace021d 100644 --- a/lang/tests/son_tests_wide_ret.txt +++ b/lang/tests/son_tests_wide_ret.txt @@ -14,29 +14,30 @@ main: ADDI64 r254, r254, 56d JALA r0, r31, 0a maina: - ADDI64 r254, r254, -88d - ST r31, r254, 24a, 64h + ADDI64 r254, r254, -100d + ST r31, r254, 28a, 72h + ADDI64 r32, r254, 24d JAL r31, r0, :small_struct - LI64 r32, 1d - LI64 r33, 3d - LI64 r34, 0d - ADDI64 r35, r254, 0d - ADDI64 r36, r254, 16d - ST r34, r254, 16a, 1h - ST r34, r254, 17a, 1h - ST r34, r254, 18a, 1h - ST r33, r254, 19a, 1h - ST r32, r254, 20a, 1h - ST r34, r254, 21a, 1h - ST r34, r254, 22a, 1h - ST r34, r254, 23a, 1h - LD r37, r254, 16a, 8h - ST r37, r254, 0a, 8h + LI64 r33, 1d + LI64 r34, 3d + LI64 r35, 0d + ADDI64 r36, r254, 0d + ADDI64 r37, r254, 16d + ST r35, r254, 16a, 1h + ST r35, r254, 17a, 1h + ST r35, r254, 18a, 1h + ST r34, r254, 19a, 1h + ST r33, r254, 20a, 1h + ST r35, r254, 21a, 1h + ST r35, r254, 22a, 1h + ST r35, r254, 23a, 1h LD r38, r254, 16a, 8h - ST r38, r254, 8a, 8h - LD r1, r35, 0a, 16h - LD r31, r254, 24a, 64h - ADDI64 r254, r254, 88d + ST r38, r254, 0a, 8h + LD r39, r254, 16a, 8h + ST r39, r254, 8a, 8h + LD r1, r36, 0a, 16h + LD r31, r254, 28a, 72h + ADDI64 r254, r254, 100d JALA r0, r31, 0a small_struct: ADDI64 r254, r254, -4d @@ -47,6 +48,6 @@ small_struct: LD r1, r254, 0a, 4h ADDI64 r254, r254, 4d JALA r0, r31, 0a -code size: 532 +code size: 543 ret: 2 status: Ok(())