diff --git a/compiler/gen_dev/src/generic64/mod.rs b/compiler/gen_dev/src/generic64/mod.rs index 3feae69b4d..cedaf86244 100644 --- a/compiler/gen_dev/src/generic64/mod.rs +++ b/compiler/gen_dev/src/generic64/mod.rs @@ -639,6 +639,25 @@ impl< CC: CallConv, > Backend64Bit<'a, GeneralReg, FloatReg, ASM, CC> { + fn get_tmp_general_reg(&mut self) -> Result { + if !self.general_free_regs.is_empty() { + let free_reg = *self + .general_free_regs + .get(self.general_free_regs.len() - 1) + .unwrap(); + if CC::general_callee_saved(&free_reg) { + self.general_used_callee_saved_regs.insert(free_reg); + } + Ok(free_reg) + } else if !self.general_used_regs.is_empty() { + let (reg, sym) = self.general_used_regs.remove(0); + self.free_to_stack(&sym)?; + Ok(reg) + } else { + Err("completely out of general purpose registers".to_string()) + } + } + fn claim_general_reg(&mut self, sym: &Symbol) -> Result { let reg = if !self.general_free_regs.is_empty() { let free_reg = self.general_free_regs.pop().unwrap(); @@ -793,16 +812,33 @@ impl< fn copy_symbol_to_stack_offset( &mut self, - offset: i32, + to_offset: i32, sym: &Symbol, layout: &Layout<'a>, ) -> Result<(), String> { match layout { Layout::Builtin(Builtin::Int64) => { let reg = self.load_to_general_reg(sym)?; - ASM::mov_base32_reg64(&mut self.buf, offset, reg); + ASM::mov_base32_reg64(&mut self.buf, to_offset, reg); Ok(()) } + Layout::Builtin(Builtin::Float64) => { + let reg = self.load_to_float_reg(sym)?; + ASM::mov_base32_freg64(&mut self.buf, to_offset, reg); + Ok(()) + } + Layout::Struct(_) if layout.safe_to_memcpy() => { + let tmp_reg = self.get_tmp_general_reg()?; + if let Some(SymbolStorage::Base(from_offset)) = self.symbol_storage_map.get(sym) { + for i in 0..layout.stack_size(PTR_SIZE) as i32 { + ASM::mov_reg64_base32(&mut self.buf, tmp_reg, from_offset + i); + ASM::mov_base32_reg64(&mut self.buf, to_offset + i, tmp_reg); + } + Ok(()) + } else { + Err(format!("unknown struct: {:?}", sym)) + } + } x => Err(format!( "copying data to the stack with layout, {:?}, not implemented yet", x diff --git a/compiler/gen_dev/tests/gen_records.rs b/compiler/gen_dev/tests/gen_records.rs index ffaa8bf764..65d706b14a 100644 --- a/compiler/gen_dev/tests/gen_records.rs +++ b/compiler/gen_dev/tests/gen_records.rs @@ -39,44 +39,97 @@ mod gen_record { ); } - // #[test] - // fn f64_record() { - // assert_evals_to!( - // indoc!( - // r#" - // rec = { y: 17.2, x: 15.1, z: 19.3 } + #[test] + fn nested_record() { + assert_evals_to!( + indoc!( + r#" + { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.x + "# + ), + 15, + i64 + ); - // rec.x - // "# - // ), - // 15.1, - // f64 - // ); + assert_evals_to!( + indoc!( + r#" + { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.y.a + "# + ), + 12, + i64 + ); - // assert_evals_to!( - // indoc!( - // r#" - // rec = { y: 17.2, x: 15.1, z: 19.3 } + assert_evals_to!( + indoc!( + r#" + { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.y.b + "# + ), + 15, + i64 + ); - // rec.y - // "# - // ), - // 17.2, - // f64 - // ); + assert_evals_to!( + indoc!( + r#" + { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.y.c + "# + ), + 2, + i64 + ); - // assert_evals_to!( - // indoc!( - // r#" - // rec = { y: 17.2, x: 15.1, z: 19.3 } + assert_evals_to!( + indoc!( + r#" + { x: 15, y: { a: 12, b: 15, c: 2}, z: 19 }.z + "# + ), + 19, + i64 + ); + } - // rec.z - // "# - // ), - // 19.3, - // f64 - // ); - // } + #[test] + fn f64_record() { + assert_evals_to!( + indoc!( + r#" + rec = { y: 17.2, x: 15.1, z: 19.3 } + + rec.x + "# + ), + 15.1, + f64 + ); + + assert_evals_to!( + indoc!( + r#" + rec = { y: 17.2, x: 15.1, z: 19.3 } + + rec.y + "# + ), + 17.2, + f64 + ); + + assert_evals_to!( + indoc!( + r#" + rec = { y: 17.2, x: 15.1, z: 19.3 } + + rec.z + "# + ), + 19.3, + f64 + ); + } // #[test] // fn fn_record() {