diff --git a/compiler/gen_dev/src/generic64/mod.rs b/compiler/gen_dev/src/generic64/mod.rs index cedaf86244..e88cf49d09 100644 --- a/compiler/gen_dev/src/generic64/mod.rs +++ b/compiler/gen_dev/src/generic64/mod.rs @@ -523,19 +523,29 @@ impl< ) -> Result<(), String> { if let Layout::Struct(field_layouts) = layout { let struct_size = layout.stack_size(PTR_SIZE); - let offset = self.increase_stack_size(struct_size)?; - self.symbol_storage_map - .insert(*sym, SymbolStorage::Base(offset)); + if struct_size > 0 { + let offset = self.increase_stack_size(struct_size)?; + self.symbol_storage_map + .insert(*sym, SymbolStorage::Base(offset)); - let mut current_offset = offset; - for (field, field_layout) in fields.iter().zip(field_layouts.iter()) { - self.copy_symbol_to_stack_offset(current_offset, field, field_layout)?; - let field_size = field_layout.stack_size(PTR_SIZE); - current_offset += field_size as i32; + let mut current_offset = offset; + for (field, field_layout) in fields.iter().zip(field_layouts.iter()) { + self.copy_symbol_to_stack_offset(current_offset, field, field_layout)?; + let field_size = field_layout.stack_size(PTR_SIZE); + current_offset += field_size as i32; + } + } else { + self.symbol_storage_map.insert(*sym, SymbolStorage::Base(0)); } Ok(()) } else { - Err(format!("struct has invalid layout: {:?}", layout)) + // This is a single element struct. Just copy the single field to the stack. + let struct_size = layout.stack_size(PTR_SIZE); + let offset = self.increase_stack_size(struct_size)?; + self.symbol_storage_map + .insert(*sym, SymbolStorage::Base(offset)); + self.copy_symbol_to_stack_offset(offset, &fields[0], layout)?; + Ok(()) } } @@ -615,6 +625,41 @@ impl< ASM::mov_freg64_base32(&mut self.buf, CC::FLOAT_RETURN_REGS[0], *offset); Ok(()) } + Layout::Struct( + &[Layout::Builtin(Builtin::Int64), Layout::Builtin(Builtin::Int64)], + ) => { + if let Some(SymbolStorage::Base(struct_offset)) = + self.symbol_storage_map.get(sym) + { + ASM::mov_reg64_base32( + &mut self.buf, + CC::GENERAL_RETURN_REGS[0], + *struct_offset, + ); + ASM::mov_reg64_base32( + &mut self.buf, + CC::GENERAL_RETURN_REGS[1], + *struct_offset + 8, + ); + Ok(()) + } else { + Err(format!("unknown struct: {:?}", sym)) + } + } + Layout::Struct(_field_layouts) => { + let struct_size = layout.stack_size(PTR_SIZE); + if struct_size > 0 { + // Need at actually dispatch to call conv here since struct return is specific to that. + // CC::return_struct() + Err(format!( + "Returning struct with layout, {:?}, is not yet implemented", + layout + )) + } else { + // Nothing to do for empty struct + Ok(()) + } + } x => Err(format!( "returning symbol with layout, {:?}, is not yet implemented", x diff --git a/compiler/gen_dev/tests/gen_records.rs b/compiler/gen_dev/tests/gen_records.rs index f93a89fe69..6c49b776da 100644 --- a/compiler/gen_dev/tests/gen_records.rs +++ b/compiler/gen_dev/tests/gen_records.rs @@ -221,19 +221,19 @@ mod gen_record { ); } - // #[test] - // fn when_on_record() { - // assert_evals_to!( - // indoc!( - // r#" - // when { x: 0x2 } is - // { x } -> x + 3 - // "# - // ), - // 5, - // i64 - // ); - // } + #[test] + fn when_on_record() { + assert_evals_to!( + indoc!( + r#" + when { x: 0x2 } is + { x } -> x + 3 + "# + ), + 5, + i64 + ); + } #[test] fn when_record_with_guard_pattern() { @@ -293,32 +293,46 @@ mod gen_record { i64 ); } - // #[test] - // fn empty_record() { - // assert_evals_to!( - // indoc!( - // r#" - // v = {} + #[test] + fn empty_record() { + assert_evals_to!( + indoc!( + r#" + v = {} - // v - // "# - // ), - // (), - // () - // ); - // } - // #[test] - // fn i64_record2_literal() { - // assert_evals_to!( - // indoc!( - // r#" - // { x: 3, y: 5 } - // "# - // ), - // (3, 5), - // (i64, i64) - // ); - // } + v + "# + ), + (), + () + ); + } + + #[test] + fn i64_record1_literal() { + assert_evals_to!( + indoc!( + r#" + { x: 3 } + "# + ), + 3, + i64 + ); + } + + #[test] + fn i64_record2_literal() { + assert_evals_to!( + indoc!( + r#" + { x: 3, y: 5 } + "# + ), + (3, 5), + (i64, i64) + ); + } // // #[test] // // fn i64_record3_literal() { @@ -430,22 +444,6 @@ mod gen_record { // ); // } - // #[test] - // fn return_record() { - // assert_evals_to!( - // indoc!( - // r#" - // x = 4 - // y = 3 - - // { x, y } - // "# - // ), - // (4, 3), - // (i64, i64) - // ); - // } - // #[test] // fn optional_field_when_use_default() { // assert_evals_to!( diff --git a/compiler/gen_dev/tests/helpers/eval.rs b/compiler/gen_dev/tests/helpers/eval.rs index 9adda23d8c..49b72d6469 100644 --- a/compiler/gen_dev/tests/helpers/eval.rs +++ b/compiler/gen_dev/tests/helpers/eval.rs @@ -67,19 +67,17 @@ pub fn helper<'a>( .. } = loaded; - /* - println!("=========== Procedures =========="); - println!("{:?}", procedures); - println!("=================================\n"); + // println!("=========== Procedures =========="); + // println!("{:?}", procedures); + // println!("=================================\n"); - println!("=========== Interns =========="); - println!("{:?}", interns); - println!("=================================\n"); + // println!("=========== Interns =========="); + // println!("{:?}", interns); + // println!("=================================\n"); - println!("=========== Exposed =========="); - println!("{:?}", exposed_to_host); - println!("=================================\n"); - */ + // println!("=========== Exposed =========="); + // println!("{:?}", exposed_to_host); + // println!("=================================\n"); debug_assert_eq!(exposed_to_host.len(), 1); let main_fn_symbol = exposed_to_host.keys().copied().next().unwrap();