diff --git a/CHANGELOG.md b/CHANGELOG.md index ca1f1f0..c4904fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to this project will be documented in this file. +## [0.1.4] - 2024-10-17 + +### Fixes +- C/CPP Codegen: Fixed bundled output initialization + ## [0.1.3] - 2024-09-11 ### Fixes diff --git a/Cargo.toml b/Cargo.toml index 6210b39..a2c57dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,4 +27,4 @@ strip = true panic = "abort" [workspace.package] -version = "0.1.3" +version = "0.1.4" diff --git a/idlc_codegen_c/src/interface/functions/implementation.rs b/idlc_codegen_c/src/interface/functions/implementation.rs index 9cc76f6..35eb654 100644 --- a/idlc_codegen_c/src/interface/functions/implementation.rs +++ b/idlc_codegen_c/src/interface/functions/implementation.rs @@ -256,7 +256,8 @@ impl idlc_codegen::functions::ParameterVisitor for Implementation { let _idx = self.idx(); self.initializations.push(format!( - r#"{definition} o = {{{initialization}}}; + r#" + {definition} o = {{{initialization}}}; "# )); self.post_call.push(packer.post_bo_assignments()); diff --git a/idlc_codegen_c/src/interface/functions/serialization.rs b/idlc_codegen_c/src/interface/functions/serialization.rs index b40f263..2cc462d 100644 --- a/idlc_codegen_c/src/interface/functions/serialization.rs +++ b/idlc_codegen_c/src/interface/functions/serialization.rs @@ -118,12 +118,29 @@ impl<'a> PackedPrimitives<'a> { embedded_objs } - fn struct_init(s: &idlc_mir::StructInner, initialization: &mut String) { + pub fn struct_init(s: &idlc_mir::StructInner, initialization: &mut String) { initialization.push('{'); for field in &s.fields { - match &field.val.0 { - idlc_mir::Type::Primitive(_) => initialization.push_str("0,"), - idlc_mir::Type::Struct(s) => Self::struct_init(s.as_ref(), initialization), + let (ty, size) = &field.val; + let count = size.get(); + match ty { + idlc_mir::Type::Primitive(_) => { + if count > 1 { + initialization.push_str("{0},"); + } else { + initialization.push_str("0,"); + } + } + idlc_mir::Type::Struct(s) => { + if count > 1 { + initialization.push('{'); + } + Self::struct_init(s.as_ref(), initialization); + if count > 1 { + initialization.pop(); + initialization.push_str("},"); + } + } idlc_mir::Type::Interface(_) => initialization.push_str("Object_NULL,"), _ => unreachable!(), } diff --git a/idlc_codegen_cpp/src/interface/functions/serialization.rs b/idlc_codegen_cpp/src/interface/functions/serialization.rs index 91f42ac..c90d1e9 100644 --- a/idlc_codegen_cpp/src/interface/functions/serialization.rs +++ b/idlc_codegen_cpp/src/interface/functions/serialization.rs @@ -108,20 +108,6 @@ impl<'a> PackedPrimitives<'a> { assignments } - fn struct_init(s: &idlc_mir::StructInner, initialization: &mut String) { - initialization.push('{'); - for field in &s.fields { - match &field.val.0 { - idlc_mir::Type::Primitive(_) => initialization.push_str("0,"), - idlc_mir::Type::Struct(s) => Self::struct_init(s.as_ref(), initialization), - idlc_mir::Type::Interface(_) => initialization.push_str("Object_NULL,"), - _ => unreachable!(), - } - } - initialization.pop(); - initialization.push_str("},"); - } - #[inline] fn generate_struct( pairs: impl Iterator, @@ -142,7 +128,7 @@ impl<'a> PackedPrimitives<'a> { Cow::Borrowed(change_primitive(p)) } Type::SmallStruct(s) => { - Self::struct_init(s, &mut initialization); + idlc_codegen_c::interface::functions::serialization::PackedPrimitives::struct_init(s, &mut initialization); Cow::Owned(s.ident.to_string()) } }; diff --git a/tests/c/header.h b/tests/c/header.h index 62fd633..dd223ee 100644 --- a/tests/c/header.h +++ b/tests/c/header.h @@ -92,6 +92,10 @@ int32_t itest1_primitive_plus_struct_out(struct CTest1 *ctx, SingleEncapsulated *encapsulated_ptr, uint32_t *magic_ptr); +int32_t itest1_primitive_array_in_struct(struct CTest1 *ctx, + ArrInStruct *arr_ptr, + uint32_t *magic_ptr); + int32_t itest1_bundled_with_unbundled(struct CTest1 *ctx, const SingleEncapsulated *bundled_ptr, uint32_t magic_val, diff --git a/tests/c/invoke.c b/tests/c/invoke.c index eb8d0be..89e72ea 100644 --- a/tests/c/invoke.c +++ b/tests/c/invoke.c @@ -157,6 +157,20 @@ int32_t itest1_primitive_plus_struct_out(struct CTest1 *ctx, return Object_OK; } +int32_t itest1_primitive_array_in_struct(struct CTest1 *ctx, + ArrInStruct *arr_ptr, + uint32_t *magic_ptr) { + arr_ptr->a[0] = 7; + arr_ptr->a[1] = 8; + arr_ptr->c[0].a = 9; + arr_ptr->c[0].b = 7; + arr_ptr->c[1].a = 8; + arr_ptr->c[1].b = 9; + arr_ptr->d = SUCCESS_FLAG; + *magic_ptr = SUCCESS_FLAG; + return Object_OK; +} + int32_t itest1_bundled_with_unbundled(struct CTest1 *ctx, const SingleEncapsulated *bundled_ptr, uint32_t magic_val, diff --git a/tests/cpp/main.cpp b/tests/cpp/main.cpp index bd49f90..d05b66c 100644 --- a/tests/cpp/main.cpp +++ b/tests/cpp/main.cpp @@ -87,6 +87,11 @@ class ITest1Impl : public cpp::ITest1ImplBase { return itest1_primitive_plus_struct_out( &this->ctest, (SingleEncapsulated *)&encapsulated_ref, magic_ptr); } + int32_t primitive_array_in_struct(cpp::ArrInStruct &arr_ref, + uint32_t *magic_ptr) { + return itest1_primitive_array_in_struct( + &this->ctest, (ArrInStruct *)&arr_ref, magic_ptr); + } int32_t bundled_with_unbundled(const cpp::SingleEncapsulated &bundled_ref, uint32_t magic_val, const cpp::Collection &unbundled_ref) { diff --git a/tests/idl/ITest.idl b/tests/idl/ITest.idl index 015200d..5ccb089 100644 --- a/tests/idl/ITest.idl +++ b/tests/idl/ITest.idl @@ -22,6 +22,17 @@ struct Collection { uint64 d; }; +struct F2 { + uint8 a; + uint8 b; +}; + +struct ArrInStruct { + uint8[2] a; + F2[2] c; + uint16 d; +}; + const uint32 SUCCESS_FLAG = 0xdead; interface ITest1 { @@ -41,6 +52,7 @@ interface ITest1 { method multiple_primitive(in buffer unused, out buffer unused2, in uint16 input, out uint16 output, in interface unused3, out interface unused4, in uint32 input2, out uint64 output2, out buffer unused5); method primitive_plus_struct_in(in SingleEncapsulated encapsulated, in uint32 magic); method primitive_plus_struct_out(out SingleEncapsulated encapsulated, out uint32 magic); + method primitive_array_in_struct(out ArrInStruct input_a, out uint32 input_b); method bundled_with_unbundled(in SingleEncapsulated bundled, in uint32 magic, in Collection unbundled); method struct_array_in(in Collection[] s_in); method struct_array_out(out Collection[] s_out); diff --git a/tests/src/implementation/test1.rs b/tests/src/implementation/test1.rs index ac3ea43..08dbddc 100644 --- a/tests/src/implementation/test1.rs +++ b/tests/src/implementation/test1.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: BSD-3-Clause use super::{TRUTH, TRUTH2}; -use crate::interfaces::itest::{self, SingleEncapsulated, SUCCESS_FLAG}; +use crate::interfaces::itest::{self, ArrInStruct, SingleEncapsulated, F2, SUCCESS_FLAG}; use crate::interfaces::itest1::{self, IITest1}; use crate::interfaces::itest3::{self, IITest3}; @@ -136,6 +136,17 @@ macro_rules! generate_itest1_impl { )) } + fn r#primitive_array_in_struct(&mut self) -> Result<(ArrInStruct, u32), itest1::Error> { + Ok(( + ArrInStruct { + a: [7, 8], + c: [F2 { a: 9, b: 7 }, F2 { a: 8, b: 9 }], + d: 7, + }, + SUCCESS_FLAG, + )) + } + fn r#bundled_with_unbundled( &mut self, r#bundled: &crate::interfaces::itest::r#SingleEncapsulated, diff --git a/tests/src/object/mod.rs b/tests/src/object/mod.rs index 6f7ca7b..e73364d 100644 --- a/tests/src/object/mod.rs +++ b/tests/src/object/mod.rs @@ -91,7 +91,7 @@ impl Drop for Object { fn drop(&mut self) { if unsafe { self.invoke(OP_RELEASE, core::ptr::null_mut(), 0u32) } != 0 { unreachable!( - "Object drop didn't succeed. This is the result of undefined + "Object drop didn't succeed. This is the result of undefined behaviour, if you believe this is a bug please submit reproduction/fix steps as an issue" );