diff --git a/lang/src/lib.rs b/lang/src/lib.rs index ec969d9..60ec2dc 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -252,7 +252,7 @@ mod ty { parser::{self, Pos}, Size, Types, }, - core::{num::NonZeroU32, ops::Range}, + core::{num::NonZeroU32, ops::Range, usize}, }; pub type ArrayLen = u32; @@ -449,6 +449,15 @@ mod ty { Kind::Func(_) | Kind::Global(_) | Kind::Module(_) => unreachable!(), } } + + pub(crate) fn has_pointers(&self, tys: &Types) -> bool { + match self.expand() { + Kind::Struct(s) => tys.struct_fields(s).iter().any(|f| f.ty.has_pointers(tys)), + Kind::Ptr(_) => true, + Kind::Slice(s) => tys.ins.slices[s as usize].len == ArrayLen::MAX, + _ => false, + } + } } #[derive(PartialEq, Eq, Clone, Copy)] diff --git a/lang/src/son.rs b/lang/src/son.rs index 748f490..3a26050 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -16,7 +16,7 @@ use { Comptime, Func, Global, HashMap, Offset, OffsetIter, PLoc, Reloc, Sig, SymKey, TypeParser, TypedReloc, Types, }, - alloc::{string::String, vec::Vec}, + alloc::{borrow::ToOwned, string::String, vec::Vec}, core::{ assert_matches::debug_assert_matches, cell::RefCell, @@ -27,7 +27,6 @@ use { hashbrown::hash_map, hbbytecode::DisasmError, regalloc2::VReg, - std::borrow::ToOwned, }; const VOID: Nid = 0; @@ -45,7 +44,7 @@ trait StoreId: Sized { impl StoreId for Nid { fn to_store(self) -> Option { - (self != ENTRY).then_some(self) + (self != MEM).then_some(self) } } @@ -1134,7 +1133,7 @@ mod var { use { super::{Kind, Nid, Nodes}, crate::{ident::Ident, ty}, - std::{panic, vec::Vec}, + alloc::vec::Vec, }; // makes sure value inside is laways locked for this instance of variable @@ -1158,7 +1157,7 @@ mod var { pub fn set_value(&mut self, mut new_value: Nid, nodes: &mut Nodes) -> Nid { nodes.unlock(self.value); - std::mem::swap(&mut self.value, &mut new_value); + core::mem::swap(&mut self.value, &mut new_value); nodes.lock(self.value); new_value } @@ -1170,7 +1169,7 @@ mod var { pub fn remove(self, nodes: &mut Nodes) { nodes.unlock_remove(self.value); - std::mem::forget(self); + core::mem::forget(self); } pub fn set_value_remove(&mut self, new_value: Nid, nodes: &mut Nodes) { @@ -1184,7 +1183,7 @@ mod var { } else { nodes.unlock_remove(self.value); } - std::mem::forget(self); + core::mem::forget(self); } } @@ -1219,7 +1218,7 @@ mod var { pub fn clear(&mut self, nodes: &mut Nodes) { self.vars.drain(..).for_each(|n| n.remove(nodes)); self.loads.drain(..).for_each(|l| _ = nodes.unlock_remove(l)); - std::mem::take(&mut self.store).remove(nodes); + core::mem::take(&mut self.store).remove(nodes); } } } @@ -1268,15 +1267,17 @@ impl ItemCtx { self.nodes.lock(end); self.ctrl = self.nodes.new_node(ty::Id::VOID, Kind::Entry, [VOID]); debug_assert_eq!(self.ctrl, ENTRY); + self.nodes.lock(self.ctrl); let mem = self.nodes.new_node(ty::Id::VOID, Kind::Mem, [VOID]); debug_assert_eq!(mem, MEM); self.nodes.lock(mem); - self.scope.store = Variable::new(0, ty::Id::VOID, false, ENTRY, &mut self.nodes); + self.scope.store = Variable::new(0, ty::Id::VOID, false, MEM, &mut self.nodes); } fn finalize(&mut self) { self.scope.clear(&mut self.nodes); self.nodes.unlock(NEVER); + self.nodes.unlock(ENTRY); self.nodes.unlock(MEM); self.nodes.eliminate_stack_temporaries(); } @@ -1609,7 +1610,7 @@ impl ItemCtx { self.nodes.graphviz(tys, files); debug_assert!(self.code.is_empty()); - let tail = std::mem::take(&mut self.call_count) == 0; + let tail = core::mem::take(&mut self.call_count) == 0; '_open_function: { self.emit(instrs::addi64(reg::STACK_PTR, reg::STACK_PTR, 0)); @@ -1620,10 +1621,20 @@ impl ItemCtx { '_compute_stack: { let mems = core::mem::take(&mut self.nodes[MEM].outputs); for &stck in mems.iter() { + if !matches!(self.nodes[stck].kind, Kind::Stck | Kind::Arg) { + debug_assert_matches!( + self.nodes[stck].kind, + Kind::Phi | Kind::Return | Kind::Load + ); + continue; + } stack_size += tys.size_of(self.nodes[stck].ty); self.nodes[stck].offset = stack_size; } for &stck in mems.iter() { + if !matches!(self.nodes[stck].kind, Kind::Stck | Kind::Arg) { + continue; + } self.nodes[stck].offset = stack_size - self.nodes[stck].offset; } self.nodes[MEM].outputs = mems; @@ -1837,7 +1848,7 @@ impl TypeParser for Codegen<'_> { } fn eval_const(&mut self, file: FileId, expr: &Expr, ret: ty::Id) -> u64 { - let mut scope = std::mem::take(&mut self.ci.scope.vars); + let mut scope = core::mem::take(&mut self.ci.scope.vars); self.pool.push_ci(file, Some(ret), self.tasks.len(), &mut self.ci); self.ci.scope.vars = scope; @@ -1845,7 +1856,7 @@ impl TypeParser for Codegen<'_> { self.expr(&Expr::Return { pos: expr.pos(), val: Some(expr) }); - scope = std::mem::take(&mut self.ci.scope.vars); + scope = core::mem::take(&mut self.ci.scope.vars); self.ci.finalize(); if self.errors.borrow().len() == prev_err_len { @@ -2187,6 +2198,7 @@ impl<'a> Codegen<'a> { self.assert_ty(pos, &mut value, expected, "return value"); if self.ci.inline_depth == 0 { + debug_assert_ne!(self.ci.ctrl, VOID); let mut inps = Vc::from([self.ci.ctrl, value.id]); self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops); if let Some(str) = self.ci.scope.store.value().to_store() { @@ -2610,10 +2622,12 @@ impl<'a> Codegen<'a> { let mut tys = sig.args.args(); let mut cargs = cargs.iter(); let mut args = args.iter(); + let mut has_ptr_arg = false; while let Some(ty) = tys.next(&self.tys) { let carg = cargs.next().unwrap(); let arg = args.next().unwrap(); let Arg::Value(ty) = ty else { continue }; + has_ptr_arg |= ty.has_pointers(&self.tys); let mut value = self.expr_ctx(arg, Ctx::default().with_ty(ty))?; debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre); @@ -2627,20 +2641,22 @@ impl<'a> Codegen<'a> { self.ci.nodes.unlock(n); } - if let Some(str) = self.ci.scope.store.value().to_store() { - inps.push(str); + if has_ptr_arg { + if let Some(str) = self.ci.scope.store.value().to_store() { + inps.push(str); + } + self.ci.scope.loads.retain(|&load| { + if inps.contains(&load) { + return true; + } + + if !self.ci.nodes.unlock_remove(load) { + inps.push(load); + } + + false + }); } - self.ci.scope.loads.retain(|&load| { - if inps.contains(&load) { - return true; - } - - if !self.ci.nodes.unlock_remove(load) { - inps.push(load); - } - - false - }); let alt_value = match sig.ret.loc(&self.tys) { Loc::Reg => None, @@ -2655,7 +2671,9 @@ impl<'a> Codegen<'a> { self.ci.ctrl = self.ci.nodes.new_node(sig.ret, Kind::Call { func: fu, args: sig.args }, inps); - self.store_mem(VOID, ty::Id::VOID, VOID); + if has_ptr_arg { + self.store_mem(VOID, ty::Id::VOID, VOID); + } alt_value.or(Some(Value::new(self.ci.ctrl).ty(sig.ret))) } @@ -2737,7 +2755,7 @@ impl<'a> Codegen<'a> { } let prev_var_base = - std::mem::replace(&mut self.ci.inline_var_base, self.ci.scope.vars.len()); + core::mem::replace(&mut self.ci.inline_var_base, self.ci.scope.vars.len()); let prev_ret = self.ci.ret.replace(sig.ret); let prev_inline_ret = self.ci.inline_ret.take(); let prev_file = core::mem::replace(&mut self.ci.file, file); @@ -3950,7 +3968,6 @@ impl<'a> Function<'a> { } Kind::Stck if node.ty.loc(self.tys) == Loc::Reg && node.outputs.iter().all(|&n| { - matches!(self.nodes[n].kind, Kind::Stre | Kind::Load) || matches!(self.nodes[n].kind, Kind::BinOp { op: TokenKind::Add } if self.nodes.is_const(self.nodes[n].inputs[2]) @@ -4425,7 +4442,7 @@ mod tests { different_types; struct_return_from_module_function; sort_something_viredly; - //structs_in_registers; + structs_in_registers; comptime_function_from_another_file; inline_test; inlined_generic_functions; diff --git a/lang/tests/son_tests_exhaustive_loop_testing.txt b/lang/tests/son_tests_exhaustive_loop_testing.txt index a5a8891..392827a 100644 --- a/lang/tests/son_tests_exhaustive_loop_testing.txt +++ b/lang/tests/son_tests_exhaustive_loop_testing.txt @@ -23,11 +23,11 @@ main: JAL r31, r0, :multiple_breaks CP r3, r1 LI64 r1, 3d - LI64 r6, 1d + LI64 r7, 1d JEQ r3, r1, :0 - CP r1, r6 + CP r1, r7 JMP :1 - 0: CP r33, r6 + 0: CP r33, r7 CP r34, r1 LI64 r35, 4d CP r2, r35 diff --git a/lang/tests/son_tests_struct_return_from_module_function.txt b/lang/tests/son_tests_struct_return_from_module_function.txt index 88770b8..f0fa334 100644 --- a/lang/tests/son_tests_struct_return_from_module_function.txt +++ b/lang/tests/son_tests_struct_return_from_module_function.txt @@ -10,28 +10,28 @@ foo: ADDI64 r254, r254, 16d JALA r0, r31, 0a main: - ADDI64 r254, r254, -72d - ST r31, r254, 48a, 24h + ADDI64 r254, r254, -56d + ST r31, r254, 48a, 8h ADDI64 r2, r254, 32d JAL r31, r0, :foo ST r1, r254, 32a, 16h ADDI64 r8, r254, 16d - LD r32, r254, 32a, 8h JAL r31, r0, :foo ST r1, r254, 16a, 16h - ADDI64 r3, r254, 0d - LD r33, r254, 24a, 4h + ADDI64 r2, r254, 0d JAL r31, r0, :foo ST r1, r254, 0a, 16h - LI64 r9, 7d - LD r10, r254, 12a, 4h - ANDI r11, r10, 4294967295d - ANDI r8, r33, 4294967295d - ADD64 r12, r32, r8 - ADD64 r3, r12, r11 - SUB64 r1, r9, r3 - LD r31, r254, 48a, 24h - ADDI64 r254, r254, 72d + LI64 r7, 7d + LD r8, r254, 12a, 4h + ANDI r9, r8, 4294967295d + LD r5, r254, 24a, 4h + ANDI r8, r5, 4294967295d + LD r3, r254, 32a, 8h + ADD64 r11, r3, r8 + ADD64 r3, r11, r9 + SUB64 r1, r7, r3 + LD r31, r254, 48a, 8h + ADDI64 r254, r254, 56d JALA r0, r31, 0a code size: 359 ret: 0 diff --git a/lang/tests/son_tests_structs.txt b/lang/tests/son_tests_structs.txt index 2d4bf7f..0294578 100644 --- a/lang/tests/son_tests_structs.txt +++ b/lang/tests/son_tests_structs.txt @@ -1,26 +1,26 @@ main: - ADDI64 r254, r254, -88d - ST r31, r254, 64a, 24h + ADDI64 r254, r254, -96d + ST r31, r254, 64a, 32h LI64 r32, 3d LI64 r3, 4d ADDI64 r33, r254, 0d - ADDI64 r7, r254, 16d - ADDI64 r5, r254, 48d + ADDI64 r34, r254, 48d ST r3, r254, 48a, 8h ST r32, r254, 56a, 8h - BMC r5, r7, 16h - LD r3, r5, 0a, 16h + LD r3, r34, 0a, 16h JAL r31, r0, :odher_pass ST r1, r254, 0a, 16h + ADDI64 r11, r254, 16d ADDI64 r2, r254, 32d + BMC r34, r11, 16h BMC r33, r2, 16h LD r7, r254, 40a, 8h JNE r7, r32, :0 JAL r31, r0, :pass JMP :1 0: LI64 r1, 0d - 1: LD r31, r254, 64a, 24h - ADDI64 r254, r254, 88d + 1: LD r31, r254, 64a, 32h + ADDI64 r254, r254, 96d JALA r0, r31, 0a odher_pass: ADDI64 r254, r254, -16d