From 3f497c54330c39f0d54508b1e2086de27c3f4ddb Mon Sep 17 00:00:00 2001 From: Kevin Dinkel <1225857+dinkelk@users.noreply.github.com> Date: Mon, 7 Oct 2024 09:03:29 -0600 Subject: [PATCH 1/2] Update C packed record conversions This allows the record conversions to work for types that previously failed compilation checks due to alignment constraints of aliased fields. This allows any packed record to produce a valid U_C type with conversion to U. In addition, new conversion functions have been added to convert directly from U_C to T and/or T_Le and back. --- gen/generators/packed_types.py | 1 + gen/templates/record/name-c.adb | 95 +++++++++++++++++++++++++++++++++ gen/templates/record/name-c.ads | 22 ++++---- 3 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 gen/templates/record/name-c.adb diff --git a/gen/generators/packed_types.py b/gen/generators/packed_types.py index 9305f87f..20449466 100644 --- a/gen/generators/packed_types.py +++ b/gen/generators/packed_types.py @@ -14,6 +14,7 @@ "record/name-assertion.ads", "record/name-assertion.adb", "record/name-c.ads", + "record/name-c.adb", "record/name.py", "record/name_type_ranges.adb", ] diff --git a/gen/templates/record/name-c.adb b/gen/templates/record/name-c.adb new file mode 100644 index 00000000..0dbf7f2d --- /dev/null +++ b/gen/templates/record/name-c.adb @@ -0,0 +1,95 @@ +-------------------------------------------------------------------------------- +-- {{ formatType(model_name) }} {{ formatType(model_type) }} C/C++ Interface Body +-- +-- Generated from {{ filename }} on {{ time }}. +-------------------------------------------------------------------------------- + +package body {{ name }}.C is + + function To_Ada (Src : in U_C) return U is + begin + return ( +{% for field in fields.values() %} +{% if field.is_packed_type %} + {{ field.name }} => {{ field.type_package }}.C.To_Ada (Src.{{ field.name }}){{ "," if not loop.last }} +{% else %} + {{ field.name }} => Src.{{ field.name }}{{ "," if not loop.last }} +{% endif %} +{% endfor %} + ); + end To_Ada; + + function To_C (Src : in U) return U_C is + begin + return ( +{% for field in fields.values() %} +{% if field.is_packed_type %} + {{ field.name }} => {{ field.type_package }}.C.To_C (Src.{{ field.name }}){{ "," if not loop.last }} +{% else %} + {{ field.name }} => Src.{{ field.name }}{{ "," if not loop.last }} +{% endif %} +{% endfor %} + ); + end To_C; + +{% if endianness in ["either", "big"] %} + function Pack (Src : in U_C) return T is + begin + return ( +{% for field in fields.values() %} +{% if field.is_packed_type %} + {{ field.name }} => {{ field.type_package }}.C.Pack (Src.{{ field.name }}){{ "," if not loop.last }} +{% else %} + {{ field.name }} => Src.{{ field.name }}{{ "," if not loop.last }} +{% endif %} +{% endfor %} + ); + end Pack; + +{% endif %} +{% if endianness in ["either", "little"] %} + function Pack (Src : in U_C) return T_Le is + begin + return ( +{% for field in fields.values() %} +{% if field.is_packed_type %} + {{ field.name }} => {{ field.type_package }}.C.Pack (Src.{{ field.name }}){{ "," if not loop.last }} +{% else %} + {{ field.name }} => Src.{{ field.name }}{{ "," if not loop.last }} +{% endif %} +{% endfor %} + ); + end Pack; + +{% endif %} +{% if endianness in ["either", "big"] %} + function Unpack (Src : in T) return U_C is + begin + return ( +{% for field in fields.values() %} +{% if field.is_packed_type %} + {{ field.name }} => {{ field.type_package }}.C.Unpack (Src.{{ field.name }}){{ "," if not loop.last }} +{% else %} + {{ field.name }} => Src.{{ field.name }}{{ "," if not loop.last }} +{% endif %} +{% endfor %} + ); + end Unpack; + +{% endif %} +{% if endianness in ["either", "little"] %} + function Unpack (Src : in T_Le) return U_C is + begin + return ( +{% for field in fields.values() %} +{% if field.is_packed_type %} + {{ field.name }} => {{ field.type_package }}.C.Unpack (Src.{{ field.name }}){{ "," if not loop.last }} +{% else %} + {{ field.name }} => Src.{{ field.name }}{{ "," if not loop.last }} +{% endif %} +{% endfor %} + ); + end Unpack; +{% endif %} + +end {{ name }}.C; diff --git a/gen/templates/record/name-c.ads b/gen/templates/record/name-c.ads index c1034250..17b02bec 100644 --- a/gen/templates/record/name-c.ads +++ b/gen/templates/record/name-c.ads @@ -3,9 +3,6 @@ -- -- Generated from {{ filename }} on {{ time }}. -------------------------------------------------------------------------------- - --- Standard Includes: -with Ada.Unchecked_Conversion; {% if type_includes %} -- Record Component Includes: @@ -37,12 +34,17 @@ package {{ name }}.C is -- Access type for U_C. type U_C_Access is access all U_C; - -- Functions for converting between the Ada and C version of the packed type: - function To_Ada is new Ada.Unchecked_Conversion (Source => U_C, Target => U); - function To_C is new Ada.Unchecked_Conversion (Source => U, Target => U_C); - - -- The .C package is not supported for all Adamant packed records. We do not allow compilation in - -- these cases. - pragma Compile_Time_Error ({{ name }}.U'Size /= U_C'Size, "C type size not compatible with Ada type size."); + -- Functions for converting between the Ada and C version of the + -- unpacked and packed types: + function To_Ada (Src : in U_C) return U; + function To_C (Src : in U) return U_C; +{% if endianness in ["either", "big"] %} + function Pack (Src : in U_C) return T; + function Unpack (Src : in T) return U_C; +{% endif %} +{% if endianness in ["either", "little"] %} + function Pack (Src : in U_C) return T_Le; + function Unpack (Src : in T_Le) return U_C; +{% endif %} end {{ name }}.C; From a6fa2e5ed0d8e1940f6564e18b94375de3e40bc5 Mon Sep 17 00:00:00 2001 From: Kevin Dinkel <1225857+dinkelk@users.noreply.github.com> Date: Mon, 7 Oct 2024 09:25:15 -0600 Subject: [PATCH 2/2] Update C packed array conversions --- gen/generators/packed_types.py | 1 + gen/templates/array/name-c.adb | 72 ++++++++++++++++++++++++++++++++++ gen/templates/array/name-c.ads | 24 ++++++------ 3 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 gen/templates/array/name-c.adb diff --git a/gen/generators/packed_types.py b/gen/generators/packed_types.py index 20449466..e9382db8 100644 --- a/gen/generators/packed_types.py +++ b/gen/generators/packed_types.py @@ -28,6 +28,7 @@ "array/name-validation.adb", "array/name-assertion.ads", "array/name-c.ads", + "array/name-c.adb", "array/name.py", "array/name_type_ranges.adb", ] diff --git a/gen/templates/array/name-c.adb b/gen/templates/array/name-c.adb new file mode 100644 index 00000000..191c83b1 --- /dev/null +++ b/gen/templates/array/name-c.adb @@ -0,0 +1,72 @@ +-------------------------------------------------------------------------------- +-- {{ formatType(model_name) }} {{ formatType(model_type) }} C/C++ Interface Body +-- +-- Generated from {{ filename }} on {{ time }}. +-------------------------------------------------------------------------------- + +package body {{ name }}.C is + + function To_Ada (Src : in U_C) return U is + begin +{% if element.is_packed_type %} + return [for J in Src'Range => {{ element.type_package }}.C.To_Ada (Src (J))]; +{% else %} + return [for J in Src'Range => Src (J)]; +{% endif %} + end To_Ada; + + function To_C (Src : in U) return U_C is + begin +{% if element.is_packed_type %} + return [for J in Src'Range => {{ element.type_package }}.C.To_C (Src (J))]; +{% else %} + return [for J in Src'Range => Src (J)]; +{% endif %} + end To_C; + +{% if endianness in ["either", "big"] %} + function Pack (Src : in U_C) return T is + begin +{% if element.is_packed_type %} + return [for J in Src'Range => {{ element.type_package }}.C.Pack (Src (J))]; +{% else %} + return [for J in Src'Range => Src (J)]; +{% endif %} + end Pack; + +{% endif %} +{% if endianness in ["either", "little"] %} + function Pack (Src : in U_C) return T_Le is + begin +{% if element.is_packed_type %} + return [for J in Src'Range => {{ element.type_package }}.C.Pack (Src (J))]; +{% else %} + return [for J in Src'Range => Src (J)]; +{% endif %} + end Pack; + +{% endif %} +{% if endianness in ["either", "big"] %} + function Unpack (Src : in T) return U_C is + begin +{% if element.is_packed_type %} + return [for J in Src'Range => {{ element.type_package }}.C.Unpack (Src (J))]; +{% else %} + return [for J in Src'Range => Src (J)]; +{% endif %} + end Unpack; + +{% endif %} +{% if endianness in ["either", "little"] %} + function Unpack (Src : in T_Le) return U_C is + begin +{% if element.is_packed_type %} + return [for J in Src'Range => {{ element.type_package }}.C.Unpack (Src (J))]; +{% else %} + return [for J in Src'Range => Src (J)]; +{% endif %} + end Unpack; + +{% endif %} + +end {{ name }}.C; diff --git a/gen/templates/array/name-c.ads b/gen/templates/array/name-c.ads index 21d8453b..e35681ef 100644 --- a/gen/templates/array/name-c.ads +++ b/gen/templates/array/name-c.ads @@ -3,9 +3,6 @@ -- -- Generated from {{ filename }} on {{ time }}. -------------------------------------------------------------------------------- - --- Standard Includes: -with Ada.Unchecked_Conversion; {% if type_includes %} -- Record Component Includes: @@ -29,17 +26,22 @@ package {{ name }}.C is {% endif %} -- Unpacked array type: - subtype U_C is Unconstrained{% if length %} (Constrained_Index_Type){% endif %}; + subtype U_C is Unconstrained_C{% if length %} (Constrained_Index_Type){% endif %}; -- Access type for U type U_C_Access is access all U_C; - -- Functions for converting between the Ada and C version of the packed type: - function To_Ada is new Ada.Unchecked_Conversion (Source => U_C, Target => U); - function To_C is new Ada.Unchecked_Conversion (Source => U, Target => U_C); - - -- The .C package is not supported for all Adamant packed records. We do not allow compilation in - -- these cases. - pragma Compile_Time_Error ({{ name }}.U'Size /= U_C'Size, "C type size not compatible with Ada type size."); + -- Functions for converting between the Ada and C version of the + -- unpacked and packed types: + function To_Ada (Src : in U_C) return U; + function To_C (Src : in U) return U_C; +{% if endianness in ["either", "big"] %} + function Pack (Src : in U_C) return T; + function Unpack (Src : in T) return U_C; +{% endif %} +{% if endianness in ["either", "little"] %} + function Pack (Src : in U_C) return T_Le; + function Unpack (Src : in T_Le) return U_C; +{% endif %} end {{ name }}.C;