poke-devel
[Top][All Lists]
Advanced

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

[PATCH v2 2/2] pkl: add support for integral unions


From: Mohammad-Reza Nabipoor
Subject: [PATCH v2 2/2] pkl: add support for integral unions
Date: Mon, 26 Sep 2022 02:49:25 +0330

2022-09-26  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>

        * libpoke/pkl-tab.y (tokens): s/token/%token/.
        * libpoke/pkl-typify.c (pkl_typify1_ps_cast): Handle integral
        unions.
        (pkl_typify1_ps_type_struct): Likewise.
        * 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.
---
 ChangeLog                                     |  72 +++++++
 doc/poke.texi                                 |  45 +++++
 libpoke/pkl-gen.c                             |  39 +++-
 libpoke/pkl-gen.pks                           | 190 ++++++++++++++++++
 libpoke/pkl-tab.y                             |   2 +-
 libpoke/pkl-typify.c                          |  73 ++++---
 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, 1190 insertions(+), 56 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 62a67838..a8fd753a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,75 @@
+2022-09-26  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
+
+       * libpoke/pkl-tab.y (tokens): s/token/%token/.
+       * libpoke/pkl-typify.c (pkl_typify1_ps_cast): Handle integral
+       unions.
+       (pkl_typify1_ps_type_struct): Likewise.
+       * 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-26  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
 
        * libpoke/pkl-gen.pks (function struct_constructor): Do not alter
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 f3c163b8..f1e0c8a0 100644
--- a/libpoke/pkl-gen.pks
+++ b/libpoke/pkl-gen.pks
@@ -2108,6 +2108,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
+        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)
+        ;; Create the integral value based on the type of field.
+        ;; Due to simplicity of integration of unions (there's only one
+        ;; active field, no anonymous/absent field, etc.), I'm not
+        ;; re-using any code from struct_integrator to keep things
+        ;; simpler and more efficient.
+  .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  }
+                                ; 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 )
 ;;;
@@ -2285,6 +2356,125 @@
         raise
         .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
+        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 .constraint_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  {
+                                ; IVAL IVAL
+        push PVM_E_CONSTRAINT
+        pushe .constraint_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_CONSTRAINT
+        pushe .constraint_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
+.constraint_failed:
+        nip                     ; IVAL EXC
+.alternative_failed:
+        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..516255d2 100644
--- a/libpoke/pkl-typify.c
+++ b/libpoke/pkl-typify.c
@@ -1,4 +1,4 @@
-/* pkl-typify.c - Type handling phases for the poke compiler.  */
+/* Pkl-typify.c - Type handling phases for the poke compiler.  */
 
 /* Copyright (C) 2019, 2020, 2021, 2022 Jose E. Marchesi */
 
@@ -477,8 +477,9 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_cast)
         INVALID_CAST ("invalid cast to string");
       break;
     case PKL_TYPE_STRUCT:
-      /* We are not supporting casts to unions yet.  */
-      if (PKL_AST_TYPE_S_UNION_P (to_type))
+      /* We are not supporting casts to non-integral unions yet.  */
+      if (PKL_AST_TYPE_S_UNION_P (to_type)
+          && !PKL_AST_TYPE_S_ITYPE (to_type))
         INVALID_CAST ("invalid cast to union");
 
       /* Only structs can be casted to regular structs.  Integral
@@ -1688,19 +1689,19 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_integral)
 }
 PKL_PHASE_END_HANDLER
 
-/* The type associated with an integral struct shall be integral.
+/* The type associated with an integral struct/union shall be integral.
 
-   The fields in an integral struct type shall be all of integral or
+   The fields in an integral struct/union type shall be all of integral or
    offset types (including other integral structs) and the total int
    size shall match the sum of the sizes of all the fields.
 
-   The total size declared in the integral struct should exactly match
+   The total size declared in the integral struct/union should exactly match
    the size of all the contained fields.
 
    Pinned unions are not allowed.
 
-   Labels are not allowed in integral structs, pinned structs and unions.
-   Optional fields are not allowed in integral structs.
+   Labels are not allowed in integral structs/unions, pinned structs and
+   unions.  Optional fields are not allowed in integral structs/unions.
 
    Computed fields should have getter and setter methods defined for
    them, and they should handle values of the right type.  */
@@ -1710,6 +1711,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 +1726,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 +1752,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 +1763,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 +1772,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 +1815,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 +1823,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;
+  };
-- 
2.37.3




reply via email to

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