poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] pkl: add support for integral unions


From: Jose E. Marchesi
Subject: Re: [PATCH] pkl: add support for integral unions
Date: Sat, 24 Sep 2022 16:50:38 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Hi Mohammad.
Thanks for the patch.

> 2022-09-24  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
>
>       * libpoke/pkl-tab.y (tokens): s/token/%token/.
>       * libpoke/pkl-typify.c (pkl_typify1_ps_type_struct): Handle integral 
> unions.
>       * libpoke/pkl-gen.c (pkl_gen_pr_type_struct): Likewise.
>       (pkl_gen_pr_decl): Likewise.
>       (pkl_gen_pr_cast): In cast from an integral type to struct type,
>       add a cast to ITYPE of the struct.
>       * libpoke/pkl-gen.pks (RAS_FUNCTION_UNION_INTEGRATOR): New function.
>       (RAS_FUNCTION_UNION_DEINTEGRATOR): Likewise.
>       (RAS_FUNCTION_STRUCT_INTEGRATOR): Add assertion.
>       (RAS_FUNCTION_STRUCT_DEINTEGRATOR): Likewise.
>       * libpoke/pvm.jitter (rule dup-drop): New rule.
>       (rule dup-nip): Likewise.
>       * doc/poke.texi (Integral Unions): Add new section.
>       * testsuite/poke.pkl/int-union-1.pk: New test.
>       * testsuite/poke.pkl/int-union-2.pk: Likewise.
>       * testsuite/poke.pkl/int-union-3.pk: Likewise.
>       * testsuite/poke.pkl/int-union-4.pk: Likewise.
>       * testsuite/poke.pkl/int-union-5.pk: Likewise.
>       * testsuite/poke.pkl/int-union-6.pk: Likewise.
>       * testsuite/poke.pkl/int-union-7.pk: Likewise.
>       * testsuite/poke.pkl/int-union-8.pk: Likewise.
>       * testsuite/poke.pkl/int-union-9.pk: Likewise.
>       * testsuite/poke.pkl/int-union-10.pk: Likewise.
>       * testsuite/poke.pkl/int-union-11.pk: Likewise.
>       * testsuite/poke.pkl/int-union-12.pk: Likewise.
>       * testsuite/poke.pkl/int-union-13.pk: Likewise.
>       * testsuite/poke.pkl/int-union-14.pk: Likewise.
>       * testsuite/poke.pkl/int-union-15.pk: Likewise.
>       * testsuite/poke.pkl/int-union-16.pk: Likewise.
>       * testsuite/poke.pkl/int-union-17.pk: Likewise.
>       * testsuite/poke.pkl/int-union-18.pk: Likewise.
>       * testsuite/poke.pkl/int-union-19.pk: Likewise.
>       * testsuite/poke.pkl/int-union-20.pk: Likewise.
>       * testsuite/poke.pkl/int-union-21.pk: Likewise.
>       * testsuite/poke.pkl/int-union-22.pk: Likewise.
>       * testsuite/poke.pkl/int-union-23.pk: Likewise.
>       * testsuite/poke.pkl/int-union-24.pk: Likewise.
>       * testsuite/poke.pkl/int-union-25.pk: Likewise.
>       * testsuite/poke.pkl/int-union-26.pk: Likewise.
>       * testsuite/poke.pkl/int-union-27.pk: Likewise.
>       * testsuite/poke.pkl/int-union-28.pk: Likewise.
>       * testsuite/poke.pkl/int-union-29.pk: Likewise.
>       * testsuite/poke.pkl/int-union-30.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-1.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-2.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-3.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-4.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-5.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-6.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-7.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-8.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-9.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-10.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-11.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-12.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-13.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-14.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-15.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-16.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-17.pk: Likewise.
>       * testsuite/poke.pkl/int-union-type-diag-18.pk: Likewise.
>       * testsuite/poke.map/maps-int-union-1.pk: Likewise
>       * testsuite/poke.map/maps-int-union-2.pk: Likewise
>       * testsuite/poke.map/maps-int-union-3.pk: Likewise
>       * testsuite/poke.map/maps-int-union-4.pk: Likewise
>       * testsuite/poke.map/maps-int-union-5.pk: Likewise
>       * testsuite/Makefile.am (EXTRA_DIST): Update.
> ---
>
> Hi Jose.
>
> Please make sure that everything is right in `union_deintegrator` :)
>
>
> Regards,
> Mohammad-Reza
>
>
>  ChangeLog                                     |  70 ++++++
>  doc/poke.texi                                 |  45 ++++
>  libpoke/pkl-gen.c                             |  39 +++-
>  libpoke/pkl-gen.pks                           | 203 ++++++++++++++++++
>  libpoke/pkl-tab.y                             |   2 +-
>  libpoke/pkl-typify.c                          |  56 +++--
>  libpoke/pvm.jitter                            |  10 +
>  testsuite/Makefile.am                         |  54 ++++-
>  testsuite/poke.map/maps-int-union-1.pk        |  17 ++
>  testsuite/poke.map/maps-int-union-2.pk        |  17 ++
>  testsuite/poke.map/maps-int-union-3.pk        |  23 ++
>  testsuite/poke.map/maps-int-union-4.pk        |  23 ++
>  testsuite/poke.map/maps-int-union-5.pk        |  23 ++
>  testsuite/poke.pkl/int-struct-type-diag-11.pk |   6 +-
>  testsuite/poke.pkl/int-struct-type-diag-16.pk |   7 -
>  testsuite/poke.pkl/int-struct-type-diag-17.pk |   8 -
>  testsuite/poke.pkl/int-union-1.pk             |  13 ++
>  testsuite/poke.pkl/int-union-10.pk            |  12 ++
>  testsuite/poke.pkl/int-union-11.pk            |  12 ++
>  testsuite/poke.pkl/int-union-12.pk            |  13 ++
>  testsuite/poke.pkl/int-union-13.pk            |  24 +++
>  testsuite/poke.pkl/int-union-14.pk            |  20 ++
>  testsuite/poke.pkl/int-union-15.pk            |  21 ++
>  testsuite/poke.pkl/int-union-16.pk            |  20 ++
>  testsuite/poke.pkl/int-union-17.pk            |  29 +++
>  testsuite/poke.pkl/int-union-18.pk            |  20 ++
>  testsuite/poke.pkl/int-union-19.pk            |  20 ++
>  testsuite/poke.pkl/int-union-2.pk             |  10 +
>  testsuite/poke.pkl/int-union-20.pk            |  16 ++
>  testsuite/poke.pkl/int-union-21.pk            |  16 ++
>  testsuite/poke.pkl/int-union-22.pk            |  14 ++
>  testsuite/poke.pkl/int-union-23.pk            |  14 ++
>  testsuite/poke.pkl/int-union-24.pk            |  14 ++
>  testsuite/poke.pkl/int-union-25.pk            |  23 ++
>  testsuite/poke.pkl/int-union-26.pk            |  20 ++
>  testsuite/poke.pkl/int-union-27.pk            |  23 ++
>  testsuite/poke.pkl/int-union-28.pk            |  23 ++
>  testsuite/poke.pkl/int-union-29.pk            |  24 +++
>  testsuite/poke.pkl/int-union-3.pk             |   4 +
>  testsuite/poke.pkl/int-union-30.pk            |  26 +++
>  testsuite/poke.pkl/int-union-4.pk             |   9 +
>  testsuite/poke.pkl/int-union-5.pk             |  13 ++
>  testsuite/poke.pkl/int-union-6.pk             |  10 +
>  testsuite/poke.pkl/int-union-7.pk             |   6 +
>  testsuite/poke.pkl/int-union-8.pk             |   9 +
>  testsuite/poke.pkl/int-union-9.pk             |  19 ++
>  testsuite/poke.pkl/int-union-type-diag-1.pk   |   6 +
>  testsuite/poke.pkl/int-union-type-diag-10.pk  |  12 ++
>  testsuite/poke.pkl/int-union-type-diag-11.pk  |   6 +
>  testsuite/poke.pkl/int-union-type-diag-12.pk  |   8 +
>  testsuite/poke.pkl/int-union-type-diag-13.pk  |   8 +
>  testsuite/poke.pkl/int-union-type-diag-14.pk  |   6 +
>  testsuite/poke.pkl/int-union-type-diag-15.pk  |  13 ++
>  testsuite/poke.pkl/int-union-type-diag-16.pk  |  10 +
>  testsuite/poke.pkl/int-union-type-diag-17.pk  |   8 +
>  testsuite/poke.pkl/int-union-type-diag-2.pk   |   6 +
>  testsuite/poke.pkl/int-union-type-diag-3.pk   |   7 +
>  testsuite/poke.pkl/int-union-type-diag-4.pk   |   8 +
>  testsuite/poke.pkl/int-union-type-diag-5.pk   |   7 +
>  testsuite/poke.pkl/int-union-type-diag-6.pk   |   6 +
>  testsuite/poke.pkl/int-union-type-diag-7.pk   |   8 +
>  testsuite/poke.pkl/int-union-type-diag-8.pk   |   7 +
>  testsuite/poke.pkl/int-union-type-diag-9.pk   |  14 ++
>  63 files changed, 1192 insertions(+), 48 deletions(-)
>  create mode 100644 testsuite/poke.map/maps-int-union-1.pk
>  create mode 100644 testsuite/poke.map/maps-int-union-2.pk
>  create mode 100644 testsuite/poke.map/maps-int-union-3.pk
>  create mode 100644 testsuite/poke.map/maps-int-union-4.pk
>  create mode 100644 testsuite/poke.map/maps-int-union-5.pk
>  delete mode 100644 testsuite/poke.pkl/int-struct-type-diag-16.pk
>  delete mode 100644 testsuite/poke.pkl/int-struct-type-diag-17.pk
>  create mode 100644 testsuite/poke.pkl/int-union-1.pk
>  create mode 100644 testsuite/poke.pkl/int-union-10.pk
>  create mode 100644 testsuite/poke.pkl/int-union-11.pk
>  create mode 100644 testsuite/poke.pkl/int-union-12.pk
>  create mode 100644 testsuite/poke.pkl/int-union-13.pk
>  create mode 100644 testsuite/poke.pkl/int-union-14.pk
>  create mode 100644 testsuite/poke.pkl/int-union-15.pk
>  create mode 100644 testsuite/poke.pkl/int-union-16.pk
>  create mode 100644 testsuite/poke.pkl/int-union-17.pk
>  create mode 100644 testsuite/poke.pkl/int-union-18.pk
>  create mode 100644 testsuite/poke.pkl/int-union-19.pk
>  create mode 100644 testsuite/poke.pkl/int-union-2.pk
>  create mode 100644 testsuite/poke.pkl/int-union-20.pk
>  create mode 100644 testsuite/poke.pkl/int-union-21.pk
>  create mode 100644 testsuite/poke.pkl/int-union-22.pk
>  create mode 100644 testsuite/poke.pkl/int-union-23.pk
>  create mode 100644 testsuite/poke.pkl/int-union-24.pk
>  create mode 100644 testsuite/poke.pkl/int-union-25.pk
>  create mode 100644 testsuite/poke.pkl/int-union-26.pk
>  create mode 100644 testsuite/poke.pkl/int-union-27.pk
>  create mode 100644 testsuite/poke.pkl/int-union-28.pk
>  create mode 100644 testsuite/poke.pkl/int-union-29.pk
>  create mode 100644 testsuite/poke.pkl/int-union-3.pk
>  create mode 100644 testsuite/poke.pkl/int-union-30.pk
>  create mode 100644 testsuite/poke.pkl/int-union-4.pk
>  create mode 100644 testsuite/poke.pkl/int-union-5.pk
>  create mode 100644 testsuite/poke.pkl/int-union-6.pk
>  create mode 100644 testsuite/poke.pkl/int-union-7.pk
>  create mode 100644 testsuite/poke.pkl/int-union-8.pk
>  create mode 100644 testsuite/poke.pkl/int-union-9.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-1.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-10.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-11.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-12.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-13.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-14.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-15.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-16.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-17.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-2.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-3.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-4.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-5.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-6.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-7.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-8.pk
>  create mode 100644 testsuite/poke.pkl/int-union-type-diag-9.pk
>
> diff --git a/ChangeLog b/ChangeLog
> index a2a1d027..7fd4baa4 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,73 @@
> +2022-09-24  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
> +
> +     * libpoke/pkl-tab.y (tokens): s/token/%token/.
> +     * libpoke/pkl-typify.c (pkl_typify1_ps_type_struct): Handle integral 
> unions.
> +     * libpoke/pkl-gen.c (pkl_gen_pr_type_struct): Likewise.
> +     (pkl_gen_pr_decl): Likewise.
> +     (pkl_gen_pr_cast): In cast from an integral type to struct type,
> +     add a cast to ITYPE of the struct.
> +     * libpoke/pkl-gen.pks (RAS_FUNCTION_UNION_INTEGRATOR): New function.
> +     (RAS_FUNCTION_UNION_DEINTEGRATOR): Likewise.
> +     (RAS_FUNCTION_STRUCT_INTEGRATOR): Add assertion.
> +     (RAS_FUNCTION_STRUCT_DEINTEGRATOR): Likewise.
> +     * libpoke/pvm.jitter (rule dup-drop): New rule.
> +     (rule dup-nip): Likewise.
> +     * doc/poke.texi (Integral Unions): Add new section.
> +     * testsuite/poke.pkl/int-union-1.pk: New test.
> +     * testsuite/poke.pkl/int-union-2.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-3.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-4.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-5.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-6.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-7.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-8.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-9.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-10.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-11.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-12.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-13.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-14.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-15.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-16.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-17.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-18.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-19.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-20.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-21.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-22.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-23.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-24.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-25.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-26.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-27.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-28.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-29.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-30.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-1.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-2.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-3.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-4.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-5.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-6.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-7.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-8.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-9.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-10.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-11.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-12.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-13.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-14.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-15.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-16.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-17.pk: Likewise.
> +     * testsuite/poke.pkl/int-union-type-diag-18.pk: Likewise.
> +     * testsuite/poke.map/maps-int-union-1.pk: Likewise
> +     * testsuite/poke.map/maps-int-union-2.pk: Likewise
> +     * testsuite/poke.map/maps-int-union-3.pk: Likewise
> +     * testsuite/poke.map/maps-int-union-4.pk: Likewise
> +     * testsuite/poke.map/maps-int-union-5.pk: Likewise
> +     * testsuite/Makefile.am (EXTRA_DIST): Update.
> +
>  2022-09-24  Jose E. Marchesi  <jemarch@gnu.org>
>  
>       BZ 27481
> diff --git a/doc/poke.texi b/doc/poke.texi
> index a36797b9..7f6e156a 100644
> --- a/doc/poke.texi
> +++ b/doc/poke.texi
> @@ -10766,6 +10766,7 @@ They contain heterogeneous collections of values.
>  * Integral Structs::         Composite data stored in integers.
>  * Unions::                   Dealing with conditional data.
>  * Union Constructors::          Constructing union values.
> +* Integral Unions::          Variants of composite data stored in integers.
>  * Optional Fields::          Fields that may or may not exist.
>  * Casting Structs::          Converting structs from one type to another.
>  * Declarations in Structs::  Declaring stuff within a struct.
> @@ -11711,6 +11712,50 @@ Packet @{
>  Therefore the alternative @code{b} is considered invalid (it has to be
>  bigger than 0) and @code{k} is chosen instead.
>  
> +@node Integral Unions
> +@subsection Integral Unions
> +@cindex integral unions
> +
> +Integral unions are useful to cover cases where we have variants of
> +data encoded in integers.  One example could be CPU instructions
> +encoded as 16-bit or 32-bit numbers.
> +
> +@example
> +type InstructionFormat_1 =
> +  struct uint<32>
> +  @{
> +    uint<20> imm31_12;
> +    uint<5>  rd;
> +    uint<7>  opcode : valid_opcode_for_format_1 (opcode);
> +  @};
> +
> +type InstructionFormat_2 =
> +  struct uint<32>
> +  @{
> +    uint<7> funct7;
> +    uint<5> rs2;
> +    uint<5> rs1;
> +    uint<3> funct3;
> +    uint<5>  rd;
> +    uint<7>  opcode : valid_opcode_for_format_2 (opcode);
> +  @};
> +
> +type Instruction =
> +  union uint<32>
> +  @{
> +    InstructionFormat_1 f1;
> +    InstructionFomrat_2 f2;
> +  @};
> +@end example
> +
> +
> +Like integral structs, integral unions can be casted to/from integers;
> +e.g., @code{3211411U as Instruction} will create an @code{Instruction}
> +union.
> +
> +Like integral structs, integral unions can have fields of the following
> +types: integral, offset, integral struct/union.
> +
>  @node Optional Fields
>  @subsection Optional Fields
>  @cindex struct fields
> diff --git a/libpoke/pkl-gen.c b/libpoke/pkl-gen.c
> index 971b8e3c..ba0cd818 100644
> --- a/libpoke/pkl-gen.c
> +++ b/libpoke/pkl-gen.c
> @@ -312,10 +312,14 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_decl)
>                      pvm_val integrator_closure;
>  
>                      PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_INTEGRATOR);
> -                    RAS_FUNCTION_STRUCT_INTEGRATOR (integrator_closure,
> -                                                    type_struct);
> -                    PKL_GEN_POP_CONTEXT;
> +                    if (PKL_AST_TYPE_S_UNION_P (type_struct))
> +                      RAS_FUNCTION_UNION_INTEGRATOR (integrator_closure,
> +                                                     type_struct);
> +                    else
> +                      RAS_FUNCTION_STRUCT_INTEGRATOR (integrator_closure,
> +                                                      type_struct);
>                      PKL_AST_TYPE_S_INTEGRATOR (type_struct) = 
> integrator_closure;
> +                    PKL_GEN_POP_CONTEXT;
>                    }
>  
>                  pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> @@ -328,8 +332,12 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_decl)
>                      pvm_val deintegrator_closure;
>  
>                      PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_DEINTEGRATOR);
> -                    RAS_FUNCTION_STRUCT_DEINTEGRATOR (deintegrator_closure,
> -                                                      type_struct);
> +                    if (PKL_AST_TYPE_S_UNION_P (type_struct))
> +                      RAS_FUNCTION_UNION_DEINTEGRATOR (deintegrator_closure,
> +                                                       type_struct);
> +                    else
> +                      RAS_FUNCTION_STRUCT_DEINTEGRATOR (deintegrator_closure,
> +                                                        type_struct);
>                      PKL_GEN_POP_CONTEXT;
>                      PKL_AST_TYPE_S_DEINTEGRATOR (type_struct) = 
> deintegrator_closure;
>                    }
> @@ -2445,6 +2453,13 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_cast)
>    else if (PKL_AST_TYPE_CODE (to_type) == PKL_TYPE_STRUCT
>             && PKL_AST_TYPE_CODE (from_type) == PKL_TYPE_INTEGRAL)
>      {
> +      pkl_ast_node itype = PKL_AST_TYPE_S_ITYPE (to_type);
> +
> +      /* This is guaranteed as per typify.  */
> +      assert (itype);
> +
> +      pkl_asm_insn (pasm, PKL_INSN_NTON, from_type, itype);
> +      pkl_asm_insn (pasm, PKL_INSN_NIP);
>        PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_DEINTEGRATOR);
>        PKL_PASS_SUBPASS (to_type);
>        PKL_GEN_POP_CONTEXT;
> @@ -3859,7 +3874,12 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_struct)
>        pvm_val integrator_closure = PKL_AST_TYPE_S_INTEGRATOR (type_struct);
>  
>        if (integrator_closure == PVM_NULL)
> -        RAS_FUNCTION_STRUCT_INTEGRATOR (integrator_closure, type_struct);
> +        {
> +          if (PKL_AST_TYPE_S_UNION_P (type_struct))
> +            RAS_FUNCTION_UNION_INTEGRATOR (integrator_closure, type_struct);
> +          else
> +            RAS_FUNCTION_STRUCT_INTEGRATOR (integrator_closure, type_struct);
> +        }
>        pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, integrator_closure);
>        if (!PKL_AST_TYPE_NAME (type_struct))
>          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
> @@ -3873,7 +3893,12 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_struct)
>        pvm_val deintegrator_closure = PKL_AST_TYPE_S_DEINTEGRATOR 
> (type_struct);
>  
>        if (deintegrator_closure == PVM_NULL)
> -        RAS_FUNCTION_STRUCT_DEINTEGRATOR (deintegrator_closure, type_struct);
> +        {
> +          if (PKL_AST_TYPE_S_UNION_P (type_struct))
> +            RAS_FUNCTION_UNION_DEINTEGRATOR (deintegrator_closure, 
> type_struct);
> +          else
> +            RAS_FUNCTION_STRUCT_DEINTEGRATOR (deintegrator_closure, 
> type_struct);
> +        }
>        pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, deintegrator_closure);
>        if (!PKL_AST_TYPE_NAME (type_struct))
>          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
> diff --git a/libpoke/pkl-gen.pks b/libpoke/pkl-gen.pks
> index a60ce55a..ccb8694f 100644
> --- a/libpoke/pkl-gen.pks
> +++ b/libpoke/pkl-gen.pks
> @@ -2060,6 +2060,7 @@
>  ;;; passed in the stack.
>  
>          .function struct_integrator @type_struct
> +  .c    assert (!PKL_AST_TYPE_S_UNION_P (@type_struct));

Please get rid of this assert.  It is not really needed.

>          prolog
>          pushf 2
>          regvar $sct             ; Argument
> @@ -2104,6 +2105,77 @@
>          return
>          .end
>  
> +;;; RAS_FUNCTION_UNION_INTEGRATOR @type_struct
> +;;; ( VAL -- IVAL )
> +;;;
> +;;; Assemble a function that, given an integral union, returns
> +;;; its integral value.
> +;;;
> +;;; Macro-arguments:
> +;;;
> +;;; @type_struct is a pkl_ast_node with the type of the struct
> +;;; passed in the stack.
> +
> +        .function union_integrator @type_struct
> +  .c    assert (PKL_AST_TYPE_S_UNION_P (@type_struct));
> +        prolog
> +        pushf 0
> +        .let @itype = PKL_AST_TYPE_S_ITYPE (@type_struct)
> +        .let @field
> +  .c for (@field = PKL_AST_TYPE_S_ELEMS (@type_struct);
> +  .c      @field;
> +  .c      @field = PKL_AST_CHAIN (@field))
> +  .c {
> +  .c  if (PKL_AST_CODE (@field) != PKL_AST_STRUCT_TYPE_FIELD)
> +  .c    continue;
> +        .label .alternative_failed
> +        .let @field_name = PKL_AST_STRUCT_TYPE_FIELD_NAME (@field)
> +        .let #field_name_str \
> +          = pvm_make_string (PKL_AST_IDENTIFIER_POINTER (@field_name))
> +        push PVM_E_ELEM          ; SCT EXC
> +        pushe .alternative_failed ; SCT
> +        ;; Note anonymous members are not allowed in unions.
> +        push #field_name_str     ; SCT FNAME
> +        sref                     ; SCT FNAME VAL
> +        pope
> +        nip2                     ; VAL
> +        .let @field_type = PKL_AST_STRUCT_TYPE_FIELD_TYPE (@field)
> +  .c  if (PKL_AST_TYPE_CODE (@field_type) == PKL_TYPE_INTEGRAL)
> +  .c  {
> +        nton @field_type, @itype ; NUM IVAL
> +  .c  }
> +  .c  else if (PKL_AST_TYPE_CODE (@field_type) == PKL_TYPE_OFFSET)
> +  .c  {
> +        .let @btype = PKL_AST_TYPE_O_BASE_TYPE (@field_type)
> +        ogetm                   ; OFF MAG
> +        nton @btype, @itype     ; OFF MAG IVAL
> +        nip                     ; OFF IVAL
> +  .c  }
> +  .c  else if (PKL_AST_TYPE_CODE (@field_type) == PKL_TYPE_STRUCT)
> +  .c  {
> +  .c    PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_INTEGRATOR);
> +  .c    PKL_PASS_SUBPASS (@field);
> +  .c    PKL_GEN_POP_CONTEXT;
> +        .let @field_itype = PKL_AST_TYPE_S_ITYPE (@field_type)
> +        nton @field_itype, @itype ; SCT IVAL
> +  .c  }
> +  .c  else
> +  .c  {
> +  .c    assert (0 && "unreachable reached!");
> +  .c  }

Likewise.  Do like in struct_field_inserter and be confident in the
compiler :)

BTW, I guess you are not using struct_field_inserter for performance
reasons.  A comment in that regard would be useful to have in case some
reader wonders about it.

> +                                ; VAL IVAL
> +        nip                     ; IVAL
> +        ba .done
> +.alternative_failed:
> +                                ; SCT EXC
> +        drop
> +  .c }
> +        ;; Impossible to reach here!
> +.done:
> +        popf 1
> +        return
> +        .end
> +
>  ;;; RAS_MACRO_DEINT_EXTRACT_FIELD_VALUE @uint64_type @itype @field_type 
> #bit_offset
>  ;;; ( IVAL -- EVAL )
>  ;;;
> @@ -2167,6 +2239,7 @@
>  ;;; which convert the integer.
>  
>          .function struct_deintegrator @type_struct
> +  .c    assert (!PKL_AST_TYPE_S_UNION_P (@type_struct));
>          prolog
>          pushf 2
>          ;; Convert the value to deintegrate to an ulong<64> to ease
> @@ -2271,6 +2344,136 @@
>          return
>          .end
>  
> +;;; RAS_FUNCTION_UNION_DEINTEGRATOR @type_struct
> +;;; ( IVAL -- VAL )
> +;;;
> +;;; Assemble a function that, given an integral value, transforms it
> +;;; into an equivalent integral union with the given type.  The
> +;;; integral value in the stack should be the same as the integral
> +;;; type of TYPE_STRUCT.
> +;;;
> +;;; Macro-arguments:
> +;;;
> +;;; @type_struct is a pkl_ast_node with the type of the union to
> +;;; which convert the integer.
> +
> +        .function union_deintegrator @type_struct
> +  .c    assert (PKL_AST_TYPE_S_UNION_P (@type_struct));
> +        prolog
> +        pushf 0
> +        .let @itype = PKL_AST_TYPE_S_ITYPE (@type_struct)
> +        .let @field
> +  .c  for (@field = PKL_AST_TYPE_S_ELEMS (@type_struct);
> +  .c       @field;
> +  .c       @field = PKL_AST_CHAIN (@field))
> +  .c  {
> +        .label .alternative_failed
> +        .label .construction_failed
> +        .label .deintegration_failed
> +  .c  if (PKL_AST_CODE (@field) != PKL_AST_STRUCT_TYPE_FIELD)
> +  .c  {
> +  .c    continue;
> +  .c  }
> +        .let @field_type = PKL_AST_STRUCT_TYPE_FIELD_TYPE (@field)
> +        dup                       ; IVAL IVAL
> +  .c  if (PKL_AST_TYPE_CODE (@field_type) == PKL_TYPE_INTEGRAL)
> +  .c  {
> +                                ; IVAL NUM
> +        nton @itype, @field_type
> +        nip                     ; IVAL NUM
> +  .c  }
> +  .c  else if (PKL_AST_TYPE_CODE (@field_type) == PKL_TYPE_OFFSET)
> +  .c  {
> +                                ; IVAL MAG
> +        .let @btype = PKL_AST_TYPE_O_BASE_TYPE (@field_type)
> +        nton @itype, @btype
> +        nip                     ; IVAL NUM
> +        .let @ounit = PKL_AST_TYPE_O_UNIT (@field_type)
> +        .let #unit = pvm_make_ulong (PKL_AST_INTEGER_VALUE (@ounit), 64)
> +        push #unit              ; IVAL MAG UNIT
> +        mko                     ; IVAL OFF
> +  .c  }
> +  .c  else if (PKL_AST_TYPE_CODE (@field_type) == PKL_TYPE_STRUCT)
> +  .c  {
> +        push PVM_E_GENERIC
> +        pushe .deintegration_failed
> +  .c    PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_DEINTEGRATOR);
> +  .c    PKL_PASS_SUBPASS (@field_type);
> +  .c    PKL_GEN_POP_CONTEXT;
> +                                ; IVAL SCT
> +        pope
> +  .c  }
> +        ;; Create a PVM type for field type
> +  .c    PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_TYPE);
> +  .c    PKL_PASS_SUBPASS (@field_type);
> +  .c    PKL_GEN_POP_CONTEXT;
> +        tor                    ; IVAL VAL [TYP]
> +        tor                    ; IVAL [TYP VAL]
> +        ;; Let's create the PVM struct from which final union will be
> +        ;; constructed.
> +        .let @field_name = PKL_AST_STRUCT_TYPE_FIELD_NAME (@field)
> +        .let #field_name_str \
> +          = pvm_make_string (PKL_AST_IDENTIFIER_POINTER (@field_name))
> +        push null              ; ... OFF
> +        push null              ; ... OFF OFF
> +        push #field_name_str   ; ... OFF OFF STR
> +        fromr                  ; ... OFF OFF STR VAL
> +        push ulong<64>0        ; ... OFF OFF STR VAL NMETH
> +        push ulong<64>1        ; ... OFF OFF STR VAL NMETH NFIELD
> +        ;; Now we have to create the PVM type for struct
> +        push #field_name_str   ; ... OFF OFF STR VAL NMETH NFIELD STR
> +        fromr                  ; ... OFF OFF STR VAL NMETH NFIELD STR TYP
> +        push ulong<64>1        ; ... OFF OFF STR VAL NMETH NFIELD STR TYP 
> NFIELD
> +        push null              ; ... OFF OFF STR VAL NMETH NFIELD STR TYP 
> NFIELD SNAME
> +        mktysct                ; ... OFF OFF STR VAL NMETH NFIELD TYP
> +        mksct                  ; IVAL SCT
> +        push PVM_E_GENERIC
> +        pushe .construction_failed
> +  .c    PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_CONSTRUCTOR);
> +  .c    PKL_PASS_SUBPASS (@type_struct);
> +  .c    PKL_GEN_POP_CONTEXT;
> +        pope
> +        ba .done
> +.deintegration_failed:
> +        ;; HACK
> +        ;; struct_deintegrator leaves two items on stack (0UL and EXC),
> +        ;; instead of one item (EXC).
> +        drop
> +        ba .alternative_failed
> +.construction_failed:
> +        ;; HACK
> +        ;; struct_constructor leaves two items on stack (0UL and EXC),
> +        ;; instead of one item (EXC).
> +        drop


Are you sure this is the case?  Isn't that 0UL yours?

I am asking because in pkl_gen_pr_cast the struct deintegrator is used
like:

  else if (PKL_AST_TYPE_CODE (to_type) == PKL_TYPE_STRUCT
           && PKL_AST_TYPE_CODE (from_type) == PKL_TYPE_INTEGRAL)
    {
      PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_DEINTEGRATOR);
      PKL_PASS_SUBPASS (to_type);
      PKL_GEN_POP_CONTEXT;
    }

And the result of the cast is expected to be just one element in the
stack.  Since that works, I am wondering what is going on ;)

> +.alternative_failed:
> +                                ; IVAL EXC
> +        drop                    ; IVAL
> +  .c  }
> +                                ; IVAL
> +        drop
> +        push PVM_E_CONSTRAINT
> +        push "msg"
> +        .let @uname = PKL_AST_TYPE_NAME (@type_struct)
> +  .c if (@uname)
> +  .c {
> +  .c    char *msg = pk_str_concat ("no valid alternative found for union ", \
> +                                   PKL_AST_IDENTIFIER_POINTER (@uname), 
> NULL);
> +        .let #msg = pvm_make_string (msg)
> +  .c    free (msg);
> +        push #msg
> +  .c }
> +  .c else
> +  .c {
> +        push "no valid alternative found for union"
> +  .c }
> +        sset
> +        raise
> +.done:
> +        nip
> +        popf 1
> +        return
> +        .end
> +
>  ;;; RAS_MACRO_COMPLEX_LMAP @type #writer
>  ;;; ( VAL IOS BOFF -- )
>  ;;;
> diff --git a/libpoke/pkl-tab.y b/libpoke/pkl-tab.y
> index 04b1c0a7..b8d9b5ea 100644
> --- a/libpoke/pkl-tab.y
> +++ b/libpoke/pkl-tab.y
> @@ -390,7 +390,7 @@ load_module (struct pkl_parser *parser,
>  %token ENUM              _("keyword `enum'")
>  %token <integer> PINNED  _("keyword `pinned'")
>  %token STRUCT            _("keyword `struct'")
> -token <integer> UNION    _("keyword `union'")
> +%token <integer> UNION   _("keyword `union'")
>  %token CONST             _("keyword `const'")
>  %token CONTINUE          _("keyword `continue'")
>  %token ELSE              _("keyword `else'")
> diff --git a/libpoke/pkl-typify.c b/libpoke/pkl-typify.c
> index aa53ee61..6fe8bfa6 100644
> --- a/libpoke/pkl-typify.c
> +++ b/libpoke/pkl-typify.c
> @@ -1710,6 +1710,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_struct)
>    pkl_ast_node struct_type = PKL_PASS_NODE;
>    pkl_ast_node struct_type_itype = PKL_AST_TYPE_S_ITYPE (struct_type);
>    pkl_ast_node field;
> +  int is_union_p = PKL_AST_TYPE_S_UNION_P (struct_type);
>  
>    if (struct_type_itype)
>      {
> @@ -1724,22 +1725,14 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_struct)
>            char *type_str = pkl_type_str (struct_type_itype, 1);
>  
>            PKL_ERROR (PKL_AST_LOC (struct_type_itype),
> -                     "invalid type specifier in integral struct\n"
> +                     "invalid type specifier in integral %s\n"
>                       "expected integral, got %s",
> -                     type_str);
> +                     is_union_p ? "union" : "struct", type_str);
>            free (type_str);
>            PKL_TYPIFY_PAYLOAD->errors++;
>            PKL_PASS_ERROR;
>          }
>  
> -      if (PKL_AST_TYPE_S_UNION_P (struct_type))
> -        {
> -          PKL_ERROR (PKL_AST_LOC (struct_type),
> -                     "unions can't be integral");
> -          PKL_TYPIFY_PAYLOAD->errors++;
> -          PKL_PASS_ERROR;
> -        }
> -
>        for (field = PKL_AST_TYPE_S_ELEMS (struct_type);
>             field;
>             field = PKL_AST_CHAIN (field))
> @@ -1758,9 +1751,9 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_struct)
>                    char *type_str = pkl_type_str (ftype, 1);
>  
>                    PKL_ERROR (PKL_AST_LOC (field),
> -                             "invalid field in integral struct\n"
> -                             "expected integral, offset or integral struct, 
> got %s",
> -                             type_str);
> +                             "invalid field in integral %s\n"
> +                             "expected integral, offset or integral 
> struct/union, got %s",
> +                             is_union_p ? "union" : "struct", type_str);
>                    free (type_str);
>                    PKL_TYPIFY_PAYLOAD->errors++;
>                    PKL_PASS_ERROR;
> @@ -1769,7 +1762,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_struct)
>                if (PKL_AST_STRUCT_TYPE_FIELD_LABEL (field))
>                  {
>                    PKL_ERROR (PKL_AST_LOC (field),
> -                             "labels are not allowed in integral structs");
> +                             "labels are not allowed in integral %ss",
> +                             is_union_p ? "union" : "struct");
>                    PKL_TYPIFY_PAYLOAD->errors++;
>                    PKL_PASS_ERROR;
>                  }
> @@ -1777,20 +1771,42 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_struct)
>                if (PKL_AST_STRUCT_TYPE_FIELD_OPTCOND (field))
>                  {
>                    PKL_ERROR (PKL_AST_LOC (field),
> -                             "optional fields are not allowed in integral 
> structs");
> +                             "optional fields are not allowed in integral 
> %ss",
> +                             is_union_p ? "union" : "struct");
>                    PKL_TYPIFY_PAYLOAD->errors++;
>                    PKL_PASS_ERROR;
>                  }
>  
> -              fields_int_size += pkl_ast_sizeof_integral_type (ftype);
> +              {
> +                int fsize = pkl_ast_sizeof_integral_type (ftype);
> +
> +                if (is_union_p)
> +                  {
> +                    if (fsize != PKL_AST_TYPE_I_SIZE (struct_type_itype))
> +                      {
> +                        PKL_ERROR (PKL_AST_LOC (field),
> +                                   "invalid field size in integral union 
> type\n"
> +                                   "expected %" PRIu64 " bits, got %" PRId32 
> " bits",
> +                                   (uint64_t) PKL_AST_TYPE_I_SIZE 
> (struct_type_itype),
> +                                   fsize);
> +                        PKL_TYPIFY_PAYLOAD->errors++;
> +                        PKL_PASS_ERROR;
> +                      }
> +                    if (fields_int_size == 0)
> +                      fields_int_size = fsize;
> +                  }
> +                else
> +                  fields_int_size += fsize;
> +              }
>              }
>          }
>  
>        if (fields_int_size != PKL_AST_TYPE_I_SIZE (struct_type_itype))
>          {
>            PKL_ERROR (PKL_AST_LOC (struct_type_itype),
> -                     "invalid total size in integral struct type\n"
> +                     "invalid total size in integral %s type\n"
>                       "expected %" PRIu64 " bits, got %" PRId32 " bits",
> +                     is_union_p ? "union" : "struct",
>                       (uint64_t) PKL_AST_TYPE_I_SIZE (struct_type_itype),
>                       fields_int_size);
>            PKL_TYPIFY_PAYLOAD->errors++;
> @@ -1798,8 +1814,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_struct)
>          }
>      }
>  
> -  if (PKL_AST_TYPE_S_PINNED_P (struct_type)
> -      && PKL_AST_TYPE_S_UNION_P (struct_type))
> +  if (PKL_AST_TYPE_S_PINNED_P (struct_type) && is_union_p)
>      {
>        PKL_ERROR (PKL_AST_LOC (struct_type),
>                   "unions are not allowed to be pinned");
> @@ -1807,8 +1822,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_struct)
>        PKL_PASS_ERROR;
>      }
>  
> -  if (PKL_AST_TYPE_S_PINNED_P (struct_type)
> -      || PKL_AST_TYPE_S_UNION_P (struct_type))
> +  if (PKL_AST_TYPE_S_PINNED_P (struct_type) || is_union_p)
>      {
>        for (field = PKL_AST_TYPE_S_ELEMS (struct_type);
>             field;
> diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
> index 7c2bc821..dc28f101 100644
> --- a/libpoke/pvm.jitter
> +++ b/libpoke/pvm.jitter
> @@ -6631,3 +6631,13 @@ rule push-drop-to-nop rewrite
>    push $a; drop
>  into
>  end
> +
> +rule dup-drop rewrite
> +  dup; drop
> +into
> +end
> +
> +rule dup-nip rewrite
> +  dup; nip
> +into
> +end
> diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
> index 3089bcc3..d1b5b9e9 100644
> --- a/testsuite/Makefile.am
> +++ b/testsuite/Makefile.am
> @@ -285,6 +285,11 @@ EXTRA_DIST = \
>    poke.map/maps-int-structs-27.pk \
>    poke.map/maps-int-structs-28.pk \
>    poke.map/maps-int-structs-29.pk \
> +  poke.map/maps-int-union-1.pk \
> +  poke.map/maps-int-union-2.pk \
> +  poke.map/maps-int-union-4.pk \
> +  poke.map/maps-int-union-3.pk \
> +  poke.map/maps-int-union-5.pk \
>    poke.map/maps-ios-1.pk \
>    poke.map/maps-ios-2.pk \
>    poke.map/maps-ios-3.pk \
> @@ -1434,11 +1439,56 @@ EXTRA_DIST = \
>    poke.pkl/int-struct-type-diag-13.pk \
>    poke.pkl/int-struct-type-diag-14.pk \
>    poke.pkl/int-struct-type-diag-15.pk \
> -  poke.pkl/int-struct-type-diag-16.pk \
> -  poke.pkl/int-struct-type-diag-17.pk \
>    poke.pkl/int-type-diag-1.pk \
>    poke.pkl/int-type-diag-2.pk \
>    poke.pkl/int-type.pk \
> +  poke.pkl/int-union-1.pk \
> +  poke.pkl/int-union-2.pk \
> +  poke.pkl/int-union-3.pk \
> +  poke.pkl/int-union-4.pk \
> +  poke.pkl/int-union-5.pk \
> +  poke.pkl/int-union-6.pk \
> +  poke.pkl/int-union-7.pk \
> +  poke.pkl/int-union-8.pk \
> +  poke.pkl/int-union-9.pk \
> +  poke.pkl/int-union-10.pk \
> +  poke.pkl/int-union-11.pk \
> +  poke.pkl/int-union-12.pk \
> +  poke.pkl/int-union-13.pk \
> +  poke.pkl/int-union-14.pk \
> +  poke.pkl/int-union-15.pk \
> +  poke.pkl/int-union-16.pk \
> +  poke.pkl/int-union-17.pk \
> +  poke.pkl/int-union-18.pk \
> +  poke.pkl/int-union-19.pk \
> +  poke.pkl/int-union-20.pk \
> +  poke.pkl/int-union-21.pk \
> +  poke.pkl/int-union-22.pk \
> +  poke.pkl/int-union-23.pk \
> +  poke.pkl/int-union-24.pk \
> +  poke.pkl/int-union-25.pk \
> +  poke.pkl/int-union-26.pk \
> +  poke.pkl/int-union-27.pk \
> +  poke.pkl/int-union-28.pk \
> +  poke.pkl/int-union-29.pk \
> +  poke.pkl/int-union-30.pk \
> +  poke.pkl/int-union-type-diag-1.pk \
> +  poke.pkl/int-union-type-diag-2.pk \
> +  poke.pkl/int-union-type-diag-3.pk \
> +  poke.pkl/int-union-type-diag-4.pk \
> +  poke.pkl/int-union-type-diag-5.pk \
> +  poke.pkl/int-union-type-diag-6.pk \
> +  poke.pkl/int-union-type-diag-7.pk \
> +  poke.pkl/int-union-type-diag-8.pk \
> +  poke.pkl/int-union-type-diag-9.pk \
> +  poke.pkl/int-union-type-diag-10.pk \
> +  poke.pkl/int-union-type-diag-11.pk \
> +  poke.pkl/int-union-type-diag-12.pk \
> +  poke.pkl/int-union-type-diag-13.pk \
> +  poke.pkl/int-union-type-diag-14.pk \
> +  poke.pkl/int-union-type-diag-15.pk \
> +  poke.pkl/int-union-type-diag-16.pk \
> +  poke.pkl/int-union-type-diag-17.pk \
>    poke.pkl/integers-1.pk \
>    poke.pkl/integers-2.pk \
>    poke.pkl/integers-3.pk \
> diff --git a/testsuite/poke.map/maps-int-union-1.pk 
> b/testsuite/poke.map/maps-int-union-1.pk
> new file mode 100644
> index 00000000..2ec32f28
> --- /dev/null
> +++ b/testsuite/poke.map/maps-int-union-1.pk
> @@ -0,0 +1,17 @@
> +/* { dg-do run } */
> +/* { dg-data {c*} {0x10 0x20 0x30} } */
> +
> +type U = union uint<16>
> +  {
> +    int<16> a : a < 0;
> +    uint<16> b;
> +  };
> +
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set endian big} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {U @ 1#B } } */
> +/* { dg-output "U {b=0x2030UH}" } */
> +/* { dg-command {+(U @ 1#B)} } */
> +/* { dg-output "\\n0x2030UH" } */
> diff --git a/testsuite/poke.map/maps-int-union-2.pk 
> b/testsuite/poke.map/maps-int-union-2.pk
> new file mode 100644
> index 00000000..2f52b0a3
> --- /dev/null
> +++ b/testsuite/poke.map/maps-int-union-2.pk
> @@ -0,0 +1,17 @@
> +/* { dg-do run } */
> +/* { dg-data {c*} {0x10 0xde 0xba 0xbe} } */
> +
> +type U = union uint<16>
> +  {
> +    int<16> a : a < 0;
> +    uint<16> b;
> +  };
> +
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set endian big} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {U @ 2#B } } */
> +/* { dg-output "U {a=0xbabeH}" } */
> +/* { dg-command {+(U @ 2#B)} } */
> +/* { dg-output "\\n0xbabeUH" } */
> diff --git a/testsuite/poke.map/maps-int-union-3.pk 
> b/testsuite/poke.map/maps-int-union-3.pk
> new file mode 100644
> index 00000000..22a6334a
> --- /dev/null
> +++ b/testsuite/poke.map/maps-int-union-3.pk
> @@ -0,0 +1,23 @@
> +/* { dg-do run } */
> +/* { dg-data {c*} {0x10 0x20 0x30 0x40 0x50} } */
> +
> +type S = struct uint<32>
> +  {
> +    bit sign;
> +    uint<31> mag;
> +  };
> +
> +type U = union uint<32>
> +  {
> +    S a : a.sign == 1;
> +    S b;
> +  };
> +
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set endian big} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {U @ 1#B } } */
> +/* { dg-output "U {b=S {sign=\\(uint<1>\\) 0x0,mag=\\(uint<31>\\) 
> 0x20304050}}" } */
> +/* { dg-command {+(U @ 1#B)} } */
> +/* { dg-output "\\n0x20304050U" } */
> diff --git a/testsuite/poke.map/maps-int-union-4.pk 
> b/testsuite/poke.map/maps-int-union-4.pk
> new file mode 100644
> index 00000000..401fef79
> --- /dev/null
> +++ b/testsuite/poke.map/maps-int-union-4.pk
> @@ -0,0 +1,23 @@
> +/* { dg-do run } */
> +/* { dg-data {c*} {0x10 0x20 0x30 0x40 0x50} } */
> +
> +type S = struct uint<32>
> +  {
> +    bit sign;
> +    uint<31> mag;
> +  };
> +
> +type U = union int<32>
> +  {
> +    S a : a.sign == 1;
> +    S b;
> +  };
> +
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set endian big} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {U @ 1#B } } */
> +/* { dg-output "U {b=S {sign=\\(uint<1>\\) 0x0,mag=\\(uint<31>\\) 
> 0x20304050}}" } */
> +/* { dg-command {+(U @ 1#B)} } */
> +/* { dg-output "\\n0x20304050" } */
> diff --git a/testsuite/poke.map/maps-int-union-5.pk 
> b/testsuite/poke.map/maps-int-union-5.pk
> new file mode 100644
> index 00000000..666825e8
> --- /dev/null
> +++ b/testsuite/poke.map/maps-int-union-5.pk
> @@ -0,0 +1,23 @@
> +/* { dg-do run } */
> +/* { dg-data {c*} {0x10 0x20 0x30 0x40 0x50} } */
> +
> +type S = struct uint<32>
> +  {
> +    bit sign;
> +    uint<31>;
> +  };
> +
> +type U = union int<32>
> +  {
> +    S a : a.sign == 1;
> +    S b;
> +  };
> +
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set endian big} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {U @ 1#B } } */
> +/* { dg-output "U {b=S {sign=\\(uint<1>\\) 0x0,\\(uint<31>\\) 0x20304050}}" 
> } */
> +/* { dg-command {+(U @ 1#B)} } */
> +/* { dg-output "\\n0x20304050" } */
> diff --git a/testsuite/poke.pkl/int-struct-type-diag-11.pk 
> b/testsuite/poke.pkl/int-struct-type-diag-11.pk
> index 497e53b1..60e52c69 100644
> --- a/testsuite/poke.pkl/int-struct-type-diag-11.pk
> +++ b/testsuite/poke.pkl/int-struct-type-diag-11.pk
> @@ -1,6 +1,8 @@
>  /* { dg-do compile } */
>  
> -type Foo =  /* { dg-error "integral" } */
> -  union int<32>
> +type Foo =
> +  struct int<32>
>    {
> +    int a;
> +    string s; /* { dg-error "invalid field.*\n.*expected integral, offset or 
> integral struct" } */
>    };
> diff --git a/testsuite/poke.pkl/int-struct-type-diag-16.pk 
> b/testsuite/poke.pkl/int-struct-type-diag-16.pk
> deleted file mode 100644
> index 7ea3f43e..00000000
> --- a/testsuite/poke.pkl/int-struct-type-diag-16.pk
> +++ /dev/null
> @@ -1,7 +0,0 @@
> -/* { dg-do compile } */
> -
> -type Foo =  /* { dg-error "unions can't be integral" } */
> -  union int<32>
> -  {
> -    int a;
> -  };
> diff --git a/testsuite/poke.pkl/int-struct-type-diag-17.pk 
> b/testsuite/poke.pkl/int-struct-type-diag-17.pk
> deleted file mode 100644
> index 60e52c69..00000000
> --- a/testsuite/poke.pkl/int-struct-type-diag-17.pk
> +++ /dev/null
> @@ -1,8 +0,0 @@
> -/* { dg-do compile } */
> -
> -type Foo =
> -  struct int<32>
> -  {
> -    int a;
> -    string s; /* { dg-error "invalid field.*\n.*expected integral, offset or 
> integral struct" } */
> -  };
> diff --git a/testsuite/poke.pkl/int-union-1.pk 
> b/testsuite/poke.pkl/int-union-1.pk
> new file mode 100644
> index 00000000..a6ef6639
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-1.pk
> @@ -0,0 +1,13 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union uint<32>
> +  {
> +    int<32> a : a > 0;
> +    uint<32> b : b < 128;
> +    struct int<32>
> +    {
> +      uint<16> hi;
> +      uint<16> lo;
> +    } c;
> +  };
> diff --git a/testsuite/poke.pkl/int-union-10.pk 
> b/testsuite/poke.pkl/int-union-10.pk
> new file mode 100644
> index 00000000..87461e00
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-10.pk
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +
> +type U = union uint
> +  {
> +    offset<int,B> a : a < 0#B;
> +    uint b : b < 10;
> +  };
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {1 as U} } */
> +/* { dg-output "U {b=1U}" } */
> diff --git a/testsuite/poke.pkl/int-union-11.pk 
> b/testsuite/poke.pkl/int-union-11.pk
> new file mode 100644
> index 00000000..2b2072d7
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-11.pk
> @@ -0,0 +1,12 @@
> +/* { dg-do run } */
> +
> +type U = union uint
> +  {
> +    offset<int,B> a : a < 0#B;
> +    uint b : b < 10;
> +  };
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {(-1) as U} } */
> +/* { dg-output "U {a=-1#B}" } */
> diff --git a/testsuite/poke.pkl/int-union-12.pk 
> b/testsuite/poke.pkl/int-union-12.pk
> new file mode 100644
> index 00000000..0fcedf27
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-12.pk
> @@ -0,0 +1,13 @@
> +/* { dg-do run } */
> +
> +type U = union uint
> +  {
> +    offset<int,B> a : a < 0#B;
> +    uint b : b < 10;
> +  };
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {var x = -1} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "U {a=-1#B}" } */
> diff --git a/testsuite/poke.pkl/int-union-13.pk 
> b/testsuite/poke.pkl/int-union-13.pk
> new file mode 100644
> index 00000000..84bc24f0
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-13.pk
> @@ -0,0 +1,24 @@
> +/* { dg-do run } */
> +
> +type U = union uint
> +  {
> +    offset<int,B> a : a < 0#B;
> +    uint b : b < 10;
> +  };
> +
> +var s = "bad",
> +    x = 10;
> +try
> +  {
> +    x as U;
> +    s = "ugly";
> +  }
> +catch if E_constraint
> +  {
> +    s = "good";
> +  }
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {s} } */
> +/* { dg-output "good" } */
> diff --git a/testsuite/poke.pkl/int-union-14.pk 
> b/testsuite/poke.pkl/int-union-14.pk
> new file mode 100644
> index 00000000..c51a2030
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-14.pk
> @@ -0,0 +1,20 @@
> +/* { dg-do run } */
> +
> +type T = struct uint
> +  {
> +    int16 a;
> +    int16 b;
> +  };
> +
> +type U = union int
> +  {
> +    T a : a.a < 0;
> +    uint b : b < 10;
> +  };
> +
> +var x = -1;
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "U {a=T {a=-1H,b=-1H}}" } */
> diff --git a/testsuite/poke.pkl/int-union-15.pk 
> b/testsuite/poke.pkl/int-union-15.pk
> new file mode 100644
> index 00000000..06cadf2b
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-15.pk
> @@ -0,0 +1,21 @@
> +/* { dg-do run } */
> +
> +type T = struct uint
> +  {
> +    int16 a;
> +    int16 b;
> +  };
> +
> +type U = union int
> +  {
> +    T a : a.a < 0;
> +    uint b : b < 10;
> +  };
> +
> +var x = 0xabcdef12;
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {.set endian little} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "U {a=T {a=0xabcdH,b=0xef12H}}" } */
> diff --git a/testsuite/poke.pkl/int-union-16.pk 
> b/testsuite/poke.pkl/int-union-16.pk
> new file mode 100644
> index 00000000..b7da110a
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-16.pk
> @@ -0,0 +1,20 @@
> +/* { dg-do run } */
> +
> +type T = struct uint
> +  {
> +    int16 a;
> +    int16 b;
> +  };
> +
> +type U = union int
> +  {
> +    T a : a.a < 0;
> +    uint b : b < 10;
> +  };
> +
> +var x = 1;
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "U {b=1U}" } */
> diff --git a/testsuite/poke.pkl/int-union-17.pk 
> b/testsuite/poke.pkl/int-union-17.pk
> new file mode 100644
> index 00000000..e88fbb34
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-17.pk
> @@ -0,0 +1,29 @@
> +/* { dg-do run } */
> +
> +type T = struct uint
> +  {
> +    int16 a;
> +    int16 b;
> +  };
> +
> +type U = union int
> +  {
> +    T a : a.a < 0;
> +    uint b : b < 10;
> +  };
> +
> +var s = "bad",
> +    x = 10;
> +try
> +  {
> +    x as U;
> +    s = "ugly";
> +  }
> +catch if E_constraint
> +  {
> +    s = "good";
> +  }
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {s} } */
> +/* { dg-output "good" } */
> diff --git a/testsuite/poke.pkl/int-union-18.pk 
> b/testsuite/poke.pkl/int-union-18.pk
> new file mode 100644
> index 00000000..dd490c4d
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-18.pk
> @@ -0,0 +1,20 @@
> +/* { dg-do run } */
> +
> +type U = union int
> +  {
> +    struct int
> +    {
> +      struct int
> +      {
> +        uint<16> a : a != 0;
> +        uint<16> b;
> +      } x;
> +    } y;
> +  };
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {.set endian little} } */
> +/* { dg-command {var x = 0xdeadbeef} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "U {y=struct {x=struct {a=0xdeadUH,b=0xbeefUH}}}" } */
> diff --git a/testsuite/poke.pkl/int-union-19.pk 
> b/testsuite/poke.pkl/int-union-19.pk
> new file mode 100644
> index 00000000..fcb8a050
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-19.pk
> @@ -0,0 +1,20 @@
> +/* { dg-do run } */
> +
> +type U = union int
> +  {
> +    struct int
> +    {
> +      struct int
> +      {
> +        uint<16> a : a == 0;
> +        offset<int<16>,KB> b;
> +      } x;
> +    } y;
> +  };
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {.set endian little} } */
> +/* { dg-command {var x = 0xdead} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "U {y=struct {x=struct {a=0x0UH,b=0xdeadH#KB}}}" } */
> diff --git a/testsuite/poke.pkl/int-union-2.pk 
> b/testsuite/poke.pkl/int-union-2.pk
> new file mode 100644
> index 00000000..192132b3
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-2.pk
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +
> +type MyInt = uint<41>;
> +
> +type Foo =
> +  union MyInt
> +  {
> +    int<41> a : a > 0;
> +    uint<41> b;
> +  };
> diff --git a/testsuite/poke.pkl/int-union-20.pk 
> b/testsuite/poke.pkl/int-union-20.pk
> new file mode 100644
> index 00000000..96aad6f4
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-20.pk
> @@ -0,0 +1,16 @@
> +/* { dg-do run } */
> +
> +type U = union int
> +  {
> +    int a : a < 0;
> +    uint b;
> +  };
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {var x = 1} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "U {b=1U}" } */
> +/* { dg-command {var x = -1} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "\\nU {a=-1}" } */
> diff --git a/testsuite/poke.pkl/int-union-21.pk 
> b/testsuite/poke.pkl/int-union-21.pk
> new file mode 100644
> index 00000000..042d164a
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-21.pk
> @@ -0,0 +1,16 @@
> +/* { dg-do run } */
> +
> +type U = union int
> +  {
> +    int a : a < 0;
> +    uint b;
> +  };
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {var x = 1UL} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "U {b=1U}" } */
> +/* { dg-command {var x = 0xffff_ffffUL} } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "\\nU {a=-1}" } */
> diff --git a/testsuite/poke.pkl/int-union-22.pk 
> b/testsuite/poke.pkl/int-union-22.pk
> new file mode 100644
> index 00000000..e1431e12
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-22.pk
> @@ -0,0 +1,14 @@
> +/* { dg-do run } */
> +
> +type U = union uint
> +  {
> +    offset<int,B> a : a < 0#B;
> +    uint b : b < 10;
> +  };
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {var x = U {b=5}} } */
> +/* { dg-command {+x} } */
> +/* { dg-output "5U" } */
> +/* { dg-command {x as int} } */
> +/* { dg-output "\\n5" } */
> diff --git a/testsuite/poke.pkl/int-union-23.pk 
> b/testsuite/poke.pkl/int-union-23.pk
> new file mode 100644
> index 00000000..ff520714
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-23.pk
> @@ -0,0 +1,14 @@
> +/* { dg-do run } */
> +
> +type U = union uint
> +  {
> +    offset<int,B> a : a < 0#B;
> +    uint b : b < 10;
> +  };
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {var x = U {a=-20#B}} } */
> +/* { dg-command {+x} } */
> +/* { dg-output "0xffffffecU" } */
> +/* { dg-command {x as ulong} } */
> +/* { dg-output "\\n0xffffffecUL" } */
> diff --git a/testsuite/poke.pkl/int-union-24.pk 
> b/testsuite/poke.pkl/int-union-24.pk
> new file mode 100644
> index 00000000..204d9b0f
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-24.pk
> @@ -0,0 +1,14 @@
> +/* { dg-do run } */
> +
> +type U = union int
> +  {
> +    offset<int,B> a : a < 0#B;
> +    uint b : b < 10;
> +  };
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {var x = U {a=-20#B}} } */
> +/* { dg-command {+x} } */
> +/* { dg-output "0xffffffec" } */
> +/* { dg-command {x as ulong} } */
> +/* { dg-output "\\n0xffffffffffffffecUL" } */
> diff --git a/testsuite/poke.pkl/int-union-25.pk 
> b/testsuite/poke.pkl/int-union-25.pk
> new file mode 100644
> index 00000000..47ec64f5
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-25.pk
> @@ -0,0 +1,23 @@
> +/* { dg-do run } */
> +
> +type S = struct long
> +  {
> +    int16 x;
> +    int32 y : y < 0;
> +    int16 z;
> +  };
> +
> +type U = union long
> +  {
> +    S a;
> +    ulong b;
> +  };
> +
> +var s = S{ x=0xdead, y=0x87654321U as int, z=0xbeef };
> +var u = U { a=s };
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {+s} } */
> +/* { dg-output "0xdead87654321beefL" } */
> +/* { dg-command {+u} } */
> +/* { dg-output "\\n0xdead87654321beefL" } */
> diff --git a/testsuite/poke.pkl/int-union-26.pk 
> b/testsuite/poke.pkl/int-union-26.pk
> new file mode 100644
> index 00000000..b34eee1a
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-26.pk
> @@ -0,0 +1,20 @@
> +/* { dg-do run } */
> +
> +type S = struct long
> +  {
> +    int16 x;
> +    int32 y : y < 0;
> +    int16 z;
> +  };
> +
> +type U = union long
> +  {
> +    S a;
> +    ulong b;
> +  };
> +
> +var u = U { b=0xdead12345678beefUL };
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {+u} } */
> +/* { dg-output "0xdead12345678beefL" } */
> diff --git a/testsuite/poke.pkl/int-union-27.pk 
> b/testsuite/poke.pkl/int-union-27.pk
> new file mode 100644
> index 00000000..d4c8ac9f
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-27.pk
> @@ -0,0 +1,23 @@
> +/* { dg-do run } */
> +
> +type S = struct uint
> +  {
> +    int16 a;
> +    int16 b;
> +  };
> +
> +type U = union int
> +  {
> +    S a : a.a < 0;
> +    uint b : b < 10;
> +  };
> +
> +var s = S { a=0xabcd, b=0xef12 };
> +var u = U { a = s };
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set endian little} } */
> +/* { dg-command {+s} } */
> +/* { dg-output "0xabcdef12U" } */
> +/* { dg-command {+u} } */
> +/* { dg-output "\\n0xabcdef12" } */
> diff --git a/testsuite/poke.pkl/int-union-28.pk 
> b/testsuite/poke.pkl/int-union-28.pk
> new file mode 100644
> index 00000000..83d204a3
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-28.pk
> @@ -0,0 +1,23 @@
> +/* { dg-do run } */
> +
> +type S = struct uint
> +  {
> +    int16 a;
> +    offset<int16,b> b;
> +  };
> +
> +type U = union int
> +  {
> +    S a : a.a < 0;
> +    uint b : b < 10;
> +  };
> +
> +var s = S { a=0xabcd, b=0xef12H#b };
> +var u = U { a = s };
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set endian little} } */
> +/* { dg-command {+s} } */
> +/* { dg-output "0xabcdef12U" } */
> +/* { dg-command {+u} } */
> +/* { dg-output "\\n0xabcdef12" } */
> diff --git a/testsuite/poke.pkl/int-union-29.pk 
> b/testsuite/poke.pkl/int-union-29.pk
> new file mode 100644
> index 00000000..ed5503db
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-29.pk
> @@ -0,0 +1,24 @@
> +/* { dg-do run } */
> +
> +type U = union int
> +  {
> +    struct uint
> +    {
> +      struct int
> +      {
> +        uint<16> a : a == 0;
> +        offset<int<16>,KB> b;
> +      } x;
> +    } y;
> +  };
> +
> +var x = 0xdead;
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set endian little} } */
> +/* { dg-command {+U{}} } */
> +/* { dg-output "0x0" } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "\\nU {y=struct {x=struct {a=0x0UH,b=0xdeadH#KB}}}" } */
> +/* { dg-command {+(x as U)} } */
> +/* { dg-output "\\n0xdead" } */
> diff --git a/testsuite/poke.pkl/int-union-3.pk 
> b/testsuite/poke.pkl/int-union-3.pk
> new file mode 100644
> index 00000000..1b66d27e
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-3.pk
> @@ -0,0 +1,4 @@
> +/* { dg-do compile } */
> +
> +type Bar = union int<8> { int<8> a : a > 10; int<8> b; };
> +type Foo = union int<8> { Bar la; struct int<8> { int<6> c; int<2> d; } e; };
> diff --git a/testsuite/poke.pkl/int-union-30.pk 
> b/testsuite/poke.pkl/int-union-30.pk
> new file mode 100644
> index 00000000..5908da9a
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-30.pk
> @@ -0,0 +1,26 @@
> +/* { dg-do run } */
> +
> +type U = union int
> +  {
> +    struct int
> +    {
> +      uint<16> a : a == 0;
> +      offset<int<16>,KB> b;
> +    } x;
> +    struct uint
> +    {
> +      uint<16> a : a != 0;
> +      offset<int<16>,KB> b;
> +    } y;
> +  };
> +
> +var x = 0xdeadbeef;
> +
> +/* { dg-command {.set obase 16} } */
> +/* { dg-command {.set endian little} } */
> +/* { dg-command {+U{}} } */
> +/* { dg-output "0x0" } */
> +/* { dg-command {x as U} } */
> +/* { dg-output "\\nU {y=struct {a=0xdeadUH,b=0xbeefH#KB}}" } */
> +/* { dg-command {+(x as U)} } */
> +/* { dg-output "\\n0xdeadbeef" } */
> diff --git a/testsuite/poke.pkl/int-union-4.pk 
> b/testsuite/poke.pkl/int-union-4.pk
> new file mode 100644
> index 00000000..3f8fbc2d
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-4.pk
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +
> +
> +type Foo =
> +  union int<16>
> +  {
> +    union int<16> { int<16> a : a < 0; uint<16> b; } la;
> +    int<16> c;
> +  };
> diff --git a/testsuite/poke.pkl/int-union-5.pk 
> b/testsuite/poke.pkl/int-union-5.pk
> new file mode 100644
> index 00000000..11f00fc1
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-5.pk
> @@ -0,0 +1,13 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union uint<32>
> +  {
> +    int<32> a : a > 0;
> +    offset<uint<32>,B> b : b < 128#B;
> +    struct int<32>
> +    {
> +      offset<uint<16>,KiB> hi;
> +      uint<16> lo;
> +    } c;
> +  };
> diff --git a/testsuite/poke.pkl/int-union-6.pk 
> b/testsuite/poke.pkl/int-union-6.pk
> new file mode 100644
> index 00000000..7457b638
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-6.pk
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +
> +type MyInt = uint<41>;
> +
> +type Foo =
> +  union MyInt
> +  {
> +    int<41> a : a > 0;
> +    offset<uint<41>,b> b;
> +  };
> diff --git a/testsuite/poke.pkl/int-union-7.pk 
> b/testsuite/poke.pkl/int-union-7.pk
> new file mode 100644
> index 00000000..ed6e3086
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-7.pk
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +
> +type Bar = union int<8>
> +  { offset<int<8>,b> a : a > 10#B; offset<int<8>,B> b; };
> +type Foo = union int<8>
> +  { Bar la; struct int<8> { int<6> c; offset<int<2>,KB> d; } e; };
> diff --git a/testsuite/poke.pkl/int-union-8.pk 
> b/testsuite/poke.pkl/int-union-8.pk
> new file mode 100644
> index 00000000..eef1cba8
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-8.pk
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +
> +
> +type Foo =
> +  union int<16>
> +  {
> +    union int<16> { int<16> a : a < 0; offset<uint<16>,B> b; } la;
> +    offset<int<16>,MiB> c;
> +  };
> diff --git a/testsuite/poke.pkl/int-union-9.pk 
> b/testsuite/poke.pkl/int-union-9.pk
> new file mode 100644
> index 00000000..4b500064
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-9.pk
> @@ -0,0 +1,19 @@
> +/* { dg-do compile } */
> +
> +
> +type Foo =
> +  union int<16>
> +  {
> +    union int<16> { int<16> a : a < 0; offset<uint<16>,B> b; } la;
> +    offset<int<16>,MiB> c;
> +
> +    method _print = void:
> +      {
> +        if (!(la.a ?! E_elem))
> +          printf "%v", la.a;
> +        if (!(la.b ?! E_elem))
> +          printf "%v\n", la.b;
> +        if (!(c ?! E_elem))
> +          printf "%v\n", c;
> +      }
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-1.pk 
> b/testsuite/poke.pkl/int-union-type-diag-1.pk
> new file mode 100644
> index 00000000..ea35a167
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-1.pk
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union int<0> /* { dg-error "" } */
> +  {
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-10.pk 
> b/testsuite/poke.pkl/int-union-type-diag-10.pk
> new file mode 100644
> index 00000000..a3e75a20
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-10.pk
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union uint<33>
> +  {
> +    struct int<33>
> +    {
> +      int<17> x;
> +      int<16> y;
> +    } b;
> +    int<33> c @ 0#B; /* { dg-error "labels are not allowed" } */
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-11.pk 
> b/testsuite/poke.pkl/int-union-type-diag-11.pk
> new file mode 100644
> index 00000000..1d1f10e5
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-11.pk
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union int<32> /* { dg-error "invalid total size.*\n.*expected 32.*got 0" } 
> */
> +  {
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-12.pk 
> b/testsuite/poke.pkl/int-union-type-diag-12.pk
> new file mode 100644
> index 00000000..ff665746
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-12.pk
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union uint<32>
> +  {
> +    int<32> a;
> +    offset<int<31>,B> b; /* { dg-error "invalid field size.*\n.*expected 32" 
> } */
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-13.pk 
> b/testsuite/poke.pkl/int-union-type-diag-13.pk
> new file mode 100644
> index 00000000..8b713067
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-13.pk
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union uint<32>
> +  {
> +    int<32> a;
> +    offset<int<32>,B> b if a == 2; /* { dg-error "optional.*allowed" } */
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-14.pk 
> b/testsuite/poke.pkl/int-union-type-diag-14.pk
> new file mode 100644
> index 00000000..cc702688
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-14.pk
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union string /* { dg-error "invalid type.*\n.*expected integral" } */
> +  {
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-15.pk 
> b/testsuite/poke.pkl/int-union-type-diag-15.pk
> new file mode 100644
> index 00000000..d344230b
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-15.pk
> @@ -0,0 +1,13 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union int<16>
> +  {
> +    struct int<10>  /* { dg-error "invalid total size.*\n.*expected 10" } */
> +    {
> +      byte a;
> +      byte b;
> +    } la;
> +
> +   uint<16> le;
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-16.pk 
> b/testsuite/poke.pkl/int-union-type-diag-16.pk
> new file mode 100644
> index 00000000..7b364024
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-16.pk
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union uint<32>
> +  {
> +    int<16> a : a > 0; /* { dg-error "invalid field size.*\n.*expected 32" } 
> */
> +    uint<8> b : b < 128;
> +    uint<4> c : a + b > 255;
> +    int<32>  d;
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-17.pk 
> b/testsuite/poke.pkl/int-union-type-diag-17.pk
> new file mode 100644
> index 00000000..e28460c7
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-17.pk
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union int<32>
> +  {
> +    int a;
> +    byte[4] b; /* { dg-error "invalid field.*\n.*expected integral, offset 
> or integral struct/union" } */
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-2.pk 
> b/testsuite/poke.pkl/int-union-type-diag-2.pk
> new file mode 100644
> index 00000000..09335dcd
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-2.pk
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union int<65> /* { dg-error "" } */
> +  {
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-3.pk 
> b/testsuite/poke.pkl/int-union-type-diag-3.pk
> new file mode 100644
> index 00000000..4d002336
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-3.pk
> @@ -0,0 +1,7 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union int<32>
> +  {
> +    string je; /* { dg-error "invalid field.*\n.*expected integral, offset 
> or integral struct/union" } */
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-4.pk 
> b/testsuite/poke.pkl/int-union-type-diag-4.pk
> new file mode 100644
> index 00000000..5a38bd1b
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-4.pk
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union int<32>
> +  {
> +    int<32> i;
> +    int<32>[] je; /* { dg-error "invalid field.*\n.*expected integral, 
> offset or integral struct/union" } */
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-5.pk 
> b/testsuite/poke.pkl/int-union-type-diag-5.pk
> new file mode 100644
> index 00000000..fdd3d9fd
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-5.pk
> @@ -0,0 +1,7 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union int<32>
> +  {
> +    int<32> foo; union {} bar; /* { dg-error "invalid field.*\n.*expected 
> integral, offset or integral struct/union" } */
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-6.pk 
> b/testsuite/poke.pkl/int-union-type-diag-6.pk
> new file mode 100644
> index 00000000..784dcdd3
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-6.pk
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union uint<32> /* { dg-error "invalid total size.*\n.*expected 32" } */
> +  {
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-7.pk 
> b/testsuite/poke.pkl/int-union-type-diag-7.pk
> new file mode 100644
> index 00000000..abddffba
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-7.pk
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union uint<32>
> +  {
> +    int<32> a;
> +    int<17> b; /* { dg-error "invalid field size.*\n.*expected 32" } */
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-8.pk 
> b/testsuite/poke.pkl/int-union-type-diag-8.pk
> new file mode 100644
> index 00000000..6daa94fd
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-8.pk
> @@ -0,0 +1,7 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union uint<32>
> +  {
> +    int<33> a; /* { dg-error "invalid field size.*\n.*expected 32" } */
> +  };
> diff --git a/testsuite/poke.pkl/int-union-type-diag-9.pk 
> b/testsuite/poke.pkl/int-union-type-diag-9.pk
> new file mode 100644
> index 00000000..4ff576b2
> --- /dev/null
> +++ b/testsuite/poke.pkl/int-union-type-diag-9.pk
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +
> +type Foo =
> +  union int<33>
> +  {
> +    /* FIXME due to a bug in parser, I have to put the dg error thing in
> +       previous line.  */
> +    uint<33> le;/* { dg-error "invalid field size.*\n.*expected 33" } */
> +    struct int<32>
> +    {
> +      int16 a;
> +      int16 b;
> +    } la;
> +  };



reply via email to

[Prev in Thread] Current Thread [Next in Thread]