poke-devel
[Top][All Lists]
Advanced

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

[PATCH v3] pkl: add support for integral unions


From: Mohammad-Reza Nabipoor
Subject: [PATCH v3] pkl: add support for integral unions
Date: Mon, 26 Sep 2022 16:03:22 +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.
        * 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.

Changes from v2:

```
diff --git a/ChangeLog b/ChangeLog
index a8fd753a..42b3c2ec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,8 +12,6 @@
        (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.
diff --git a/doc/poke.texi b/doc/poke.texi
index 7f6e156a..cad2e397 100644
--- a/doc/poke.texi
+++ b/doc/poke.texi
@@ -11754,7 +11754,7 @@ 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.
+types: integral, offset, integral struct or union.
 
 @node Optional Fields
 @subsection Optional Fields
diff --git a/libpoke/pkl-typify.c b/libpoke/pkl-typify.c
index 516255d2..8b73c671 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 */
 
@@ -1689,19 +1689,19 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_integral)
 }
 PKL_PHASE_END_HANDLER
 
-/* The type associated with an integral struct/union shall be integral.
+/* The type associated with an integral struct or union shall be integral.
 
-   The fields in an integral struct/union type shall be all of integral or
+   The fields in an integral struct or 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/union should exactly match
-   the size of all the contained fields.
+   The total size declared in the integral struct or union should exactly
+   match the size of all the contained fields.
 
    Pinned unions are not allowed.
 
-   Labels are not allowed in integral structs/unions, pinned structs and
-   unions.  Optional fields are not allowed in integral structs/unions.
+   Labels are not allowed in integral structs or unions, pinned structs and
+   unions.  Optional fields are not allowed in integral structs or unions.
 
    Computed fields should have getter and setter methods defined for
    them, and they should handle values of the right type.  */
@@ -1753,7 +1753,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_struct)
 
                   PKL_ERROR (PKL_AST_LOC (field),
                              "invalid field in integral %s\n"
-                             "expected integral, offset or integral 
struct/union, got %s",
+                             "expected integral, offset, integral struct or "
+                             "union, got %s",
                              is_union_p ? "union" : "struct", type_str);
                   free (type_str);
                   PKL_TYPIFY_PAYLOAD->errors++;
diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
index dc28f101..7c2bc821 100644
--- a/libpoke/pvm.jitter
+++ b/libpoke/pvm.jitter
@@ -6631,13 +6631,3 @@ 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
```


Regards,
Mohammad-Reza




 ChangeLog                                     |  70 +++++++
 doc/poke.texi                                 |  45 +++++
 libpoke/pkl-gen.c                             |  39 +++-
 libpoke/pkl-gen.pks                           | 190 ++++++++++++++++++
 libpoke/pkl-tab.y                             |   2 +-
 libpoke/pkl-typify.c                          |  74 ++++---
 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 ++
 62 files changed, 1179 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..42b3c2ec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,73 @@
+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.
+       * 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..cad2e397 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 or 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..8b73c671 100644
--- a/libpoke/pkl-typify.c
+++ b/libpoke/pkl-typify.c
@@ -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 or union shall be integral.
 
-   The fields in an integral struct type shall be all of integral or
+   The fields in an integral struct or 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 size of all the contained fields.
+   The total size declared in the integral struct or 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 or unions, pinned structs and
+   unions.  Optional fields are not allowed in integral structs or 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,10 @@ 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, integral struct or "
+                             "union, got %s",
+                             is_union_p ? "union" : "struct", type_str);
                   free (type_str);
                   PKL_TYPIFY_PAYLOAD->errors++;
                   PKL_PASS_ERROR;
@@ -1769,7 +1764,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 +1773,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 +1816,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 +1824,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/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]