diff --git a/lang/src/son.rs b/lang/src/son.rs index 18b3e64..6cac0d1 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -3103,10 +3103,7 @@ impl<'a> Codegen<'a> { self.ci.inline_ret.take() { if value.ty.loc(self.tys) == Loc::Stack { - let stck = self.new_stack(pos, value.ty); - self.store_mem(stck, value.ty, value.id); - value.id = stck; - value.ptr = true; + self.spill(pos, &mut value); } debug_assert!( @@ -3141,10 +3138,7 @@ impl<'a> Codegen<'a> { self.ci.inline_ret = Some((pv, ctrl, scope, aclass)); } else { if value.ty.loc(self.tys) == Loc::Stack { - let stck = self.new_stack(pos, value.ty); - self.store_mem(stck, value.ty, value.id); - value.id = stck; - value.ptr = true; + self.spill(pos, &mut value); } for (i, aclass) in self.ci.scope.aclasses[..2].iter_mut().enumerate() { @@ -3271,10 +3265,7 @@ impl<'a> Codegen<'a> { let mut right = self.expr(right)?; if right.ty.loc(self.tys) == Loc::Stack { - let stck = self.new_stack(pos, right.ty); - self.store_mem(stck, right.ty, right.id); - right.id = stck; - right.ptr = true; + self.spill(pos, &mut right); } self.assign_pattern(left, right); Some(Value::VOID) @@ -3332,13 +3323,34 @@ impl<'a> Codegen<'a> { self.implicit_unwrap(left.pos(), &mut lhs); match lhs.ty.expand() { - _ if lhs.ty.is_pointer() - || lhs.ty.is_integer() - || lhs.ty == ty::Id::BOOL - || (lhs.ty == ty::Id::TYPE - && matches!(op, TokenKind::Eq | TokenKind::Ne)) - || (lhs.ty.is_float() && op.is_supported_float_op()) => - { + ty::Kind::Struct(s) if op.is_homogenous() => { + debug_assert!(lhs.ptr); + self.ci.nodes.lock(lhs.id); + let rhs = self.ptr_expr_ctx(right, Ctx::default().with_ty(lhs.ty)); + self.ci.nodes.unlock(lhs.id); + let mut rhs = rhs?; + debug_assert!(rhs.ptr); + self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand"); + let dst = self.new_stack(pos, lhs.ty); + self.struct_op(left.pos(), op, s, dst, lhs.id, rhs.id); + Some(Value::ptr(dst).ty(lhs.ty)) + } + ty::Kind::Struct(s) if op.is_compatison() => { + let binding_op = match op { + TokenKind::Eq => TokenKind::Band, + _ => TokenKind::Bor, + }; + + self.ci.nodes.lock(lhs.id); + let rhs = self.ptr_expr_ctx(right, Ctx::default().with_ty(lhs.ty)); + self.ci.nodes.unlock(lhs.id); + let mut rhs = rhs?; + self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand"); + + self.struct_fold_op(left.pos(), op, binding_op, s, lhs.id, rhs.id) + .or(Value::NEVER) + } + _ if op.is_scalar_op(lhs.ty) => { self.strip_ptr(&mut lhs); self.ci.nodes.lock(lhs.id); let rhs = self.expr_ctx(right, Ctx::default().with_ty(lhs.ty)); @@ -3370,33 +3382,6 @@ impl<'a> Codegen<'a> { self.ci.nodes.pass_aclass(aclass, bop.id); Some(bop) } - ty::Kind::Struct(s) if op.is_homogenous() => { - debug_assert!(lhs.ptr); - self.ci.nodes.lock(lhs.id); - let rhs = self.ptr_expr_ctx(right, Ctx::default().with_ty(lhs.ty)); - self.ci.nodes.unlock(lhs.id); - let mut rhs = rhs?; - debug_assert!(rhs.ptr); - self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand"); - let dst = self.new_stack(pos, lhs.ty); - self.struct_op(left.pos(), op, s, dst, lhs.id, rhs.id); - Some(Value::ptr(dst).ty(lhs.ty)) - } - ty::Kind::Struct(s) if op.is_compatison() => { - let binding_op = match op { - TokenKind::Eq => TokenKind::Band, - _ => TokenKind::Bor, - }; - - self.ci.nodes.lock(lhs.id); - let rhs = self.ptr_expr_ctx(right, Ctx::default().with_ty(lhs.ty)); - self.ci.nodes.unlock(lhs.id); - let mut rhs = rhs?; - self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand"); - - self.struct_fold_op(left.pos(), op, binding_op, s, lhs.id, rhs.id) - .or(Value::NEVER) - } _ => self .error(pos, fa!("'{} {op} _' is not supported", self.ty_display(lhs.ty))), } @@ -3519,12 +3504,7 @@ impl<'a> Codegen<'a> { match ty.loc(self.tys) { Loc::Reg if mem::take(&mut val.ptr) => val.id = self.load_mem(val.id, ty), - Loc::Stack if !val.ptr => { - let stack = self.new_stack(pos, ty); - self.store_mem(stack, val.ty, val.id); - val.id = stack; - val.ptr = true; - } + Loc::Stack if !val.ptr => self.spill(pos, &mut val), _ => {} } @@ -4364,6 +4344,14 @@ impl<'a> Codegen<'a> { } } + fn spill(&mut self, pos: Pos, value: &mut Value) { + debug_assert!(!value.ptr); + let stck = self.new_stack(pos, value.ty); + self.store_mem(stck, value.ty, value.id); + value.id = stck; + value.ptr = true; + } + fn checked_expr( &mut self, expr: &Expr, @@ -5029,10 +5017,7 @@ impl<'a> Codegen<'a> { if parser::find_symbol(&self.file().symbols, id).flags & idfl::REFERENCED != 0 && !right.ptr { - let stack = self.new_stack(pos, right.ty); - self.store_mem(stack, right.ty, right.id); - right.id = stack; - right.ptr = true; + self.spill(pos, &mut right); } self.ci.scope.vars.push(Variable::new( id, @@ -6061,6 +6046,16 @@ impl<'a> Codegen<'a> { } } +impl TokenKind { + fn is_scalar_op(self, ty: ty::Id) -> bool { + ty.is_pointer() + || ty.is_integer() + || ty == ty::Id::BOOL + || (ty == ty::Id::TYPE && matches!(self, TokenKind::Eq | TokenKind::Ne)) + || (ty.is_float() && self.is_supported_float_op()) + } +} + #[derive(Clone, Copy, Default)] struct TyScope { file: Module,