diff --git a/lang/src/son.rs b/lang/src/son.rs index 89a966ea..18b3e64e 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -3071,11 +3071,10 @@ impl<'a> Codegen<'a> { } Expr::Return { pos, val } => { let mut value = if let Some(val) = val { - self.raw_expr_ctx(val, Ctx { ty: self.ci.ret })? + self.ptr_expr_ctx(val, Ctx { ty: self.ci.ret })? } else { Value { ty: ty::Id::VOID, ..Default::default() } }; - self.strip_var(&mut value); let expected = *self.ci.ret.get_or_insert(value.ty); self.assert_ty(pos, &mut value, expected, "return value"); @@ -3190,8 +3189,7 @@ impl<'a> Codegen<'a> { Expr::UnOp { op: TokenKind::Band, val, pos } => { let ctx = Ctx { ty: ctx.ty.and_then(|ty| self.tys.base_of(ty)) }; - let mut val = self.raw_expr_ctx(val, ctx)?; - self.strip_var(&mut val); + let mut val = self.ptr_expr_ctx(val, ctx)?; if val.ptr { val.ptr = false; @@ -3316,8 +3314,7 @@ impl<'a> Codegen<'a> { right: Expr::Null { .. }, .. } => { - let mut cmped = self.raw_expr(left)?; - self.strip_var(&mut cmped); + let cmped = self.ptr_expr(left)?; let Some(ty) = self.tys.inner_of(cmped.ty) else { return self.error( @@ -3331,8 +3328,7 @@ impl<'a> Codegen<'a> { Expr::BinOp { left, pos, op, right } if !matches!(op, TokenKind::Assign | TokenKind::Decl) => { - let mut lhs = self.raw_expr_ctx(left, ctx)?; - self.strip_var(&mut lhs); + let mut lhs = self.ptr_expr_ctx(left, ctx)?; self.implicit_unwrap(left.pos(), &mut lhs); match lhs.ty.expand() { @@ -3348,7 +3344,6 @@ impl<'a> Codegen<'a> { let rhs = self.expr_ctx(right, Ctx::default().with_ty(lhs.ty)); self.ci.nodes.unlock(lhs.id); let mut rhs = rhs?; - self.strip_var(&mut rhs); self.implicit_unwrap(right.pos(), &mut rhs); let (ty, aclass) = self.binop_ty(pos, &mut lhs, &mut rhs, op); if op.is_compatison() { @@ -3378,10 +3373,9 @@ impl<'a> Codegen<'a> { ty::Kind::Struct(s) if op.is_homogenous() => { debug_assert!(lhs.ptr); self.ci.nodes.lock(lhs.id); - let rhs = self.raw_expr_ctx(right, Ctx::default().with_ty(lhs.ty)); + let rhs = self.ptr_expr_ctx(right, Ctx::default().with_ty(lhs.ty)); self.ci.nodes.unlock(lhs.id); let mut rhs = rhs?; - self.strip_var(&mut rhs); debug_assert!(rhs.ptr); self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand"); let dst = self.new_stack(pos, lhs.ty); @@ -3395,10 +3389,9 @@ impl<'a> Codegen<'a> { }; self.ci.nodes.lock(lhs.id); - let rhs = self.raw_expr_ctx(right, Ctx::default().with_ty(lhs.ty)); + let rhs = self.ptr_expr_ctx(right, Ctx::default().with_ty(lhs.ty)); self.ci.nodes.unlock(lhs.id); let mut rhs = rhs?; - self.strip_var(&mut 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) @@ -3409,8 +3402,7 @@ impl<'a> Codegen<'a> { } } Expr::Index { base, index } => { - let mut bs = self.raw_expr(base)?; - self.strip_var(&mut bs); + let mut bs = self.ptr_expr(base)?; if let Some(base) = self.tys.base_of(bs.ty) { bs.ptr = true; @@ -3508,8 +3500,7 @@ impl<'a> Codegen<'a> { self.gen_inferred_const(ctx, ty::Id::DINT, len) } Expr::Directive { name: "bitcast", args: [val], pos } => { - let mut val = self.raw_expr(val)?; - self.strip_var(&mut val); + let mut val = self.ptr_expr(val)?; inference!(ty, ctx, self, pos, "type", "@as(, @bitcast())"); @@ -3541,8 +3532,7 @@ impl<'a> Codegen<'a> { Some(val) } Expr::Directive { name: "unwrap", args: [expr], .. } => { - let mut val = self.raw_expr(expr)?; - self.strip_var(&mut val); + let mut val = self.ptr_expr(expr)?; if !val.ty.is_optional() { return self.error( @@ -3661,7 +3651,7 @@ impl<'a> Codegen<'a> { } Expr::Directive { name: "as", args: [ty, expr], pos } => { let ty = self.ty(ty); - let mut val = self.raw_expr_ctx(expr, Ctx::default().with_ty(ty))?; + let mut val = self.ptr_expr_ctx(expr, Ctx::default().with_ty(ty))?; if let Some(ity) = ctx.ty && ity.try_upcast(ty) == Some(ty) @@ -3669,7 +3659,6 @@ impl<'a> Codegen<'a> { { self.error(pos, "the type is known at this point, remove the hint"); } - self.strip_var(&mut val); self.assert_ty(expr.pos(), &mut val, ty, "hinted expr"); Some(val) } @@ -4381,8 +4370,7 @@ impl<'a> Codegen<'a> { expected_ty: ty::Id, hint: impl Display, ) -> Option { - let mut value = self.raw_expr_ctx(expr, Ctx::default().with_ty(expected_ty))?; - self.strip_var(&mut value); + let mut value = self.ptr_expr_ctx(expr, Ctx::default().with_ty(expected_ty))?; self.assert_ty(expr.pos(), &mut value, expected_ty, hint); self.strip_ptr(&mut value); Some(value) @@ -4395,8 +4383,7 @@ impl<'a> Codegen<'a> { pos: Pos, name: &str, ) -> Option> { - let mut vtarget = self.raw_expr(target)?; - self.strip_var(&mut vtarget); + let mut vtarget = self.ptr_expr(target)?; self.implicit_unwrap(pos, &mut vtarget); let tty = vtarget.ty; @@ -4658,8 +4645,7 @@ impl<'a> Codegen<'a> { &mut self.ci.nodes, ), Arg::Value(ty) => { - let mut value = self.raw_expr_ctx(arg, Ctx::default().with_ty(ty))?; - self.strip_var(&mut value); + let mut value = self.ptr_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)); @@ -4761,11 +4747,8 @@ impl<'a> Codegen<'a> { let carg = cargs.next().unwrap(); let Arg::Value(ty) = ty else { continue }; - let mut value = self.raw_expr_ctx(arg, Ctx::default().with_ty(ty))?; - self.strip_var(&mut value); + let value = self.checked_expr(arg, ty, fa!("argument {}", carg.name))?; debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre); - self.assert_ty(arg.pos(), &mut value, ty, fa!("argument {}", carg.name)); - self.strip_ptr(&mut value); self.add_clobbers(value, &mut clobbered_aliases); self.ci.nodes.lock(value.id); @@ -4814,13 +4797,12 @@ impl<'a> Codegen<'a> { let f = &self.files[c.file]; let Expr::BinOp { left, right, .. } = c.ast.get(f) else { unreachable!() }; - let mut value = left + let value = left .find_pattern_path(c.name, right, |expr, is_ct| { debug_assert!(is_ct); - self.raw_expr_ctx(expr, ctx) + self.ptr_expr_ctx(expr, ctx) }) .unwrap_or_else(|_| unreachable!())?; - self.strip_var(&mut value); self.ci.file = prev_file; self.ci.parent = prev_parent; Some(value) @@ -5079,13 +5061,26 @@ impl<'a> Codegen<'a> { } } - fn expr_ctx(&mut self, expr: &Expr, ctx: Ctx) -> Option { + fn ptr_expr_ctx(&mut self, expr: &Expr, ctx: Ctx) -> Option { let mut n = self.raw_expr_ctx(expr, ctx)?; - self.strip_var(&mut n); + if mem::take(&mut n.var) { + let id = (u16::MAX - n.id) as usize; + n.ptr = self.ci.scope.vars[id].ptr; + n.id = self.ci.scope.vars[id].value(); + } + Some(n) + } + + fn expr_ctx(&mut self, expr: &Expr, ctx: Ctx) -> Option { + let mut n = self.ptr_expr_ctx(expr, ctx)?; self.strip_ptr(&mut n); Some(n) } + fn ptr_expr(&mut self, expr: &Expr) -> Option { + self.ptr_expr_ctx(expr, Default::default()) + } + fn expr(&mut self, expr: &Expr) -> Option { self.expr_ctx(expr, Default::default()) } @@ -5110,14 +5105,6 @@ impl<'a> Codegen<'a> { seted } - fn strip_var(&mut self, n: &mut Value) { - if mem::take(&mut n.var) { - let id = (u16::MAX - n.id) as usize; - n.ptr = self.ci.scope.vars[id].ptr; - n.id = self.ci.scope.vars[id].value(); - } - } - fn gen_defers(&mut self, base: usize) -> Option<()> { let defers = mem::take(&mut self.ci.defers); for &(_, defer) in defers.iter().skip(base).rev() { @@ -5444,7 +5431,6 @@ impl<'a> Codegen<'a> { fn wrap_in_opt(&mut self, pos: Pos, val: &mut Value) { debug_assert!(!val.var); - let was_ptr = val.ptr; let oty = self.tys.make_opt(val.ty); if let Some((uninit, ..)) = self.tys.nieche_of(val.ty) { @@ -5456,9 +5442,9 @@ impl<'a> Codegen<'a> { let OptLayout { flag_ty, flag_offset, payload_offset } = self.tys.opt_layout(val.ty); + self.strip_ptr(val); match oty.loc(self.tys) { Loc::Reg => { - self.strip_ptr(val); // registers have inverted offsets so that accessing the inner type is a noop let flag_offset = self.tys.size_of(oty) * 8 - flag_offset * 8 - 1; let fill = self.ci.nodes.new_const(oty, 1i64 << flag_offset); @@ -5471,7 +5457,6 @@ impl<'a> Codegen<'a> { val.ty = oty; } Loc::Stack => { - self.strip_ptr(val); let stack = self.new_stack(pos, oty); let fill = self.ci.nodes.new_const(flag_ty, 1); self.store_mem(stack, flag_ty, fill); @@ -5482,10 +5467,6 @@ impl<'a> Codegen<'a> { val.ty = oty; } } - - if !was_ptr { - self.strip_ptr(val); - } } fn implicit_unwrap(&mut self, pos: Pos, opt: &mut Value) {