diff --git a/lang/src/son.rs b/lang/src/son.rs index 6838b97c..423546ad 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -22,6 +22,7 @@ use { fmt::{self, Debug, Display, Write}, format_args as fa, mem, ops::{self}, + usize, }, hashbrown::hash_map, regalloc2::VReg, @@ -1778,6 +1779,11 @@ impl<'a> Codegen<'a> { return NEVER; } + debug_assert!( + self.ci.nodes[region].kind != Kind::Load || self.ci.nodes[region].ty.is_pointer() + ); + debug_assert!(self.ci.nodes[region].kind != Kind::Stre); + let mut vc = Vc::from([VOID, value, region]); self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops); self.ci.nodes.unlock(self.ci.scope.store); @@ -1801,6 +1807,10 @@ impl<'a> Codegen<'a> { fn load_mem(&mut self, region: Nid, ty: ty::Id) -> Nid { debug_assert_ne!(region, VOID); + debug_assert!( + self.ci.nodes[region].kind != Kind::Load || self.ci.nodes[region].ty.is_pointer() + ); + debug_assert!(self.ci.nodes[region].kind != Kind::Stre); let mut vc = Vc::from([VOID, region]); self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops); if let Some(str) = self.ci.scope.store.to_store() { @@ -2013,6 +2023,7 @@ impl<'a> Codegen<'a> { Some(self.ci.nodes.new_node_lit(val.ty, Kind::UnOp { op }, [VOID, val.id])) } Expr::BinOp { left, op: TokenKind::Decl, right } => { + std::println!("{}", self.ast_display(right)); let mut right = self.expr(right)?; if right.ty.loc(&self.tys) == Loc::Stack { let stck = self.ci.nodes.new_node_nop(right.ty, Kind::Stck, [VOID, MEM]); @@ -2030,10 +2041,16 @@ impl<'a> Codegen<'a> { self.assert_ty(left.pos(), &mut value, dest.ty, "assignment source"); if dest.var { - self.ci.nodes.lock(value.id); let var = &mut self.ci.scope.vars[(u16::MAX - dest.id) as usize]; - let prev = core::mem::replace(&mut var.value, value.id); - self.ci.nodes.unlock_remove(prev); + + if var.ptr { + let val = var.value; + self.store_mem(val, value.id); + } else { + self.ci.nodes.lock(value.id); + let prev = core::mem::replace(&mut var.value, value.id); + self.ci.nodes.unlock_remove(prev); + } } else if dest.ptr { self.store_mem(dest.id, value.id); } else { @@ -2045,14 +2062,46 @@ impl<'a> Codegen<'a> { Expr::BinOp { left, op, right } if !matches!(op, TokenKind::Assign | TokenKind::Decl) => { - let mut lhs = self.expr_ctx(left, ctx)?; - self.ci.nodes.lock(lhs.id); - let rhs = self.expr_ctx(right, Ctx::default().with_ty(lhs.ty)); - self.ci.nodes.unlock(lhs.id); - let mut rhs = rhs?; - let ty = self.binop_ty(left.pos(), &mut rhs, &mut lhs, op); - let inps = [VOID, lhs.id, rhs.id]; - Some(self.ci.nodes.new_node_lit(ty::bin_ret(ty, op), Kind::BinOp { op }, inps)) + let mut lhs = self.raw_expr_ctx(left, ctx)?; + self.strip_var(&mut lhs); + + match lhs.ty.expand() { + _ if lhs.ty.is_pointer() || lhs.ty.is_integer() || lhs.ty == ty::Id::BOOL => { + if core::mem::take(&mut lhs.ptr) { + lhs.id = self.load_mem(lhs.id, lhs.ty); + } + self.ci.nodes.lock(lhs.id); + 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); + let ty = self.binop_ty(left.pos(), &mut rhs, &mut lhs, op); + let inps = [VOID, lhs.id, rhs.id]; + Some(self.ci.nodes.new_node_lit( + ty::bin_ret(ty, op), + Kind::BinOp { op }, + inps, + )) + } + ty::Kind::Struct(s) if op.is_homogenous() => { + self.ci.nodes.lock(lhs.id); + let rhs = self.raw_expr_ctx(right, Ctx::default().with_ty(lhs.ty)); + self.ci.nodes.unlock(lhs.id); + let mut rhs = rhs?; + self.strip_var(&mut rhs); + let dst = self.ci.nodes.new_node(lhs.ty, Kind::Stck, [VOID, MEM]); + self.struct_op(left.pos(), op, s, dst, lhs.id, rhs.id); + Some(Value::ptr(dst).ty(lhs.ty)) + } + _ => { + self.ci.nodes.unlock(lhs.id); + self.report( + left.pos(), + fa!("'{0} {op} {0}' is not supported", self.ty_display(lhs.ty),), + ); + Value::NEVER + } + } } Expr::Index { base, index } => { let mut bs = self.raw_expr(base)?; @@ -2773,6 +2822,45 @@ impl<'a> Codegen<'a> { } } + fn struct_op( + &mut self, + pos: Pos, + op: TokenKind, + s: ty::Struct, + dst: Nid, + lhs: Nid, + rhs: Nid, + ) -> bool { + let mut offs = OffsetIter::new(s, &self.tys); + while let Some((ty, off)) = offs.next_ty(&self.tys) { + let lhs = self.offset(lhs, off); + let rhs = self.offset(rhs, off); + let dst = self.offset(dst, off); + match ty.expand() { + _ if ty.is_pointer() || ty.is_integer() || ty == ty::Id::BOOL => { + let lhs = self.load_mem(lhs, ty); + let rhs = self.load_mem(rhs, ty); + let res = self.ci.nodes.new_node(ty, Kind::BinOp { op }, [VOID, lhs, rhs]); + self.store_mem(dst, res); + } + ty::Kind::Struct(is) => { + if !self.struct_op(pos, op, is, dst, lhs, rhs) { + self.report( + pos, + fa!( + "... when appliing '{0} {op} {0}'", + self.ty_display(ty::Kind::Struct(s).compress()) + ), + ); + } + } + _ => self.report(pos, fa!("'{0} {op} {0}' is not supported", self.ty_display(ty))), + } + } + + true + } + fn compute_signature(&mut self, func: &mut ty::Func, pos: Pos, args: &[Expr]) -> Option { let fuc = &self.tys.ins.funcs[*func as usize]; let fast = self.files[fuc.file as usize].clone(); @@ -3952,7 +4040,7 @@ mod tests { pointers; structs; hex_octal_binary_literals; - //struct_operators; + struct_operators; global_variables; directives; c_strings; diff --git a/lang/tests/son_tests_struct_operators.txt b/lang/tests/son_tests_struct_operators.txt new file mode 100644 index 00000000..fbacfade --- /dev/null +++ b/lang/tests/son_tests_struct_operators.txt @@ -0,0 +1,145 @@ +main: + ADDI64 r254, r254, -440d + ST r31, r254, 352a, 88h + LI64 r4, 4d + LI64 r9, 1d + LI64 r7, 3d + LI64 r11, 2d + LI64 r12, 1d + LI64 r8, 0d + ADDI64 r3, r254, 336d + ADDI64 r2, r254, 340d + ADDI64 r2, r254, 344d + ADDI64 r10, r254, 348d + ST r8, r254, 348a, 1h + ST r8, r254, 349a, 1h + ST r8, r254, 350a, 1h + ST r8, r254, 351a, 1h + BMC r10, r2, 4h + ST r9, r254, 340a, 1h + ST r9, r254, 341a, 1h + ST r9, r254, 342a, 1h + ST r9, r254, 343a, 1h + LD r6, r254, 340a, 1h + LD r8, r254, 344a, 1h + ADD8 r9, r6, r8 + ST r9, r254, 336a, 1h + LD r1, r254, 341a, 1h + LD r5, r254, 345a, 1h + ADD8 r5, r5, r1 + ST r5, r254, 337a, 1h + LD r8, r254, 342a, 1h + LD r9, r254, 346a, 1h + ADD8 r1, r9, r8 + ST r1, r254, 338a, 1h + LD r5, r254, 343a, 1h + LD r6, r254, 347a, 1h + ADD8 r6, r6, r5 + ST r6, r254, 339a, 1h + BMC r3, r2, 4h + LD r2, r254, 347a, 1h + LD r3, r254, 344a, 1h + LD r1, r254, 345a, 1h + LD r5, r254, 346a, 1h + ADD8 r5, r5, r1 + ADD8 r8, r3, r5 + ADD8 r1, r2, r8 + ANDI r1, r1, 255d + ANDI r4, r4, 255d + JEQ r1, r4, :0 + LI64 r1, 1008d + JMP :1 + 0: LI64 r5, 0d + LI64 r32, 4d + ADDI64 r2, r254, 0d + ADDI64 r8, r254, 16d + ADDI64 r9, r254, 32d + ADDI64 r10, r254, 64d + ADDI64 r3, r254, 96d + ADDI64 r1, r254, 112d + ADDI64 r4, r1, 16d + ADDI64 r33, r254, 144d + ADDI64 r34, r254, 160d + ADDI64 r35, r254, 176d + ADDI64 r36, r254, 208d + ADDI64 r37, r254, 224d + ADDI64 r38, r254, 240d + ADDI64 r39, r38, 16d + ADDI64 r40, r254, 272d + ADDI64 r41, r254, 288d + ADDI64 r6, r254, 304d + ADDI64 r42, r254, 320d + ST r12, r254, 320a, 8h + ST r11, r254, 328a, 8h + BMC r42, r6, 16h + ST r7, r254, 288a, 8h + ST r32, r254, 296a, 8h + BMC r41, r40, 16h + LD r7, r254, 272a, 8h + LD r11, r254, 304a, 8h + ADD64 r7, r7, r11 + ST r7, r254, 224a, 8h + LD r11, r254, 280a, 8h + LD r12, r254, 312a, 8h + ADD64 r7, r11, r12 + ST r7, r254, 232a, 8h + BMC r37, r38, 16h + LD r7, r254, 304a, 8h + LD r11, r254, 272a, 8h + SUB64 r11, r11, r7 + ST r11, r254, 208a, 8h + LD r7, r254, 312a, 8h + LD r11, r254, 280a, 8h + SUB64 r7, r11, r7 + ST r7, r254, 216a, 8h + BMC r36, r39, 16h + BMC r38, r35, 32h + ST r5, r254, 160a, 8h + ST r5, r254, 168a, 8h + BMC r34, r33, 16h + LD r11, r254, 272a, 8h + LD r12, r254, 144a, 8h + SUB64 r12, r12, r11 + ST r12, r254, 96a, 8h + LD r5, r254, 280a, 8h + LD r7, r254, 152a, 8h + SUB64 r7, r7, r5 + ST r7, r254, 104a, 8h + BMC r3, r1, 16h + BMC r6, r4, 16h + BMC r1, r10, 32h + LD r5, r254, 176a, 8h + LD r6, r254, 64a, 8h + ADD64 r11, r6, r5 + ST r11, r254, 32a, 8h + LD r12, r254, 184a, 8h + LD r1, r254, 72a, 8h + ADD64 r3, r12, r1 + ST r3, r254, 40a, 8h + LD r7, r254, 192a, 8h + LD r11, r254, 80a, 8h + ADD64 r11, r7, r11 + ST r11, r254, 48a, 8h + LD r3, r254, 200a, 8h + LD r4, r254, 88a, 8h + ADD64 r5, r3, r4 + ST r5, r254, 56a, 8h + BMC r9, r10, 32h + LD r11, r254, 80a, 8h + LD r12, r254, 64a, 8h + ADD64 r3, r11, r12 + ST r3, r254, 16a, 8h + LD r6, r254, 88a, 8h + LD r7, r254, 72a, 8h + ADD64 r9, r6, r7 + ST r9, r254, 24a, 8h + BMC r8, r2, 16h + LD r3, r254, 8a, 8h + LD r4, r254, 0a, 8h + ADD64 r1, r3, r4 + 1: LD r31, r254, 352a, 88h + ADDI64 r254, r254, 440d + JALA r0, r31, 0a +code size: 1460 +ret: 10 +status: Ok(())