poke-devel
[Top][All Lists]
Advanced

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

[COMMITTED 1/3] pkl,pvm: add a ref_type attribute to offset types


From: Jose E. Marchesi
Subject: [COMMITTED 1/3] pkl,pvm: add a ref_type attribute to offset types
Date: Sun, 23 Apr 2023 15:28:06 +0200
User-agent: Gnus/5.13 (Gnus v5.13)

This patch adds a new attribute to offset types: a referred type.
This means that values of this type refer to some other value in an IO
space.  Sort of a pointer.

The syntax is the following:

   offset<uint<64>,B,Foo> pointer_to_foo;

This patch adds the compiler support to recognize such types, and also
the corresponding PVM support code that expands the PVM offset types
at runtime.  The printers (both C and Poke) are also updated
accordingly.

2023-02-12  Jose E. Marchesi  <jemarch@gnu.org>

        * libpoke/pkl-ast.h (struct pkl_ast_type): New field ref_type in
        offset types.
        (PKL_AST_TYPE_O_REF_TYPE): Define.
        * libpoke/pkl-ast.c (pkl_ast_make_offset_type): Get a ref_type
        argument.
        (pkl_ast_node_free_1): Free ref_type.
        (pkl_ast_print_1): Print ref_type.
        (pkl_type_append_to): Include ref_type in printed representation.
        * libpoke/pkl-tab.y (ref_type): New rule.
        * libpoke/pkl-typify.c: Pass ref_type argument to calls to
        pkl_ast_make_offset_type.
        * libpoke/pkl-promo.c (promote_offset): Likewise.
        * libpoke/pkl-trans.c: Likewise.
        * libpoke/pkl-pass.c (pkl_do_pass_1): Traverse ref_type in offset
        type nodes.
        * libpoke/pkl-lex.l: Likewise.
        * libpoke/pkl-gen.c (pkl_gen_pr_type_offset): Use ref_type.
        * libpoke/pkl-rt.pk (_pkl_print_format_any): Print ref_type in
        offset types.
        * libpoke/pvm-val.h (PVM_VAL_TYP_O_REF_TYPE): Define.
        * libpoke/pvm-val.c (pvm_make_offset_type): Get an argument
        ref_type.
        * libpoke/pvm.jitter (mktyor): New instruction.
        (tyogetrt): New instruction.
        * libpoke/pkl-insn.def: New instruction PKL_INSN_TYOGETRT.
        * libpoke/pk-val.c (pk_make_offset_type): Likewise.
---
 ChangeLog                            | 86 ++++++++++++++++++++++++++++
 doc/poke.texi                        | 27 ++++++---
 libpoke/libpoke.h                    |  7 ++-
 libpoke/pk-val.c                     |  6 +-
 libpoke/pkl-ast.c                    | 24 +++++++-
 libpoke/pkl-ast.h                    |  4 +-
 libpoke/pkl-fold.c                   |  4 +-
 libpoke/pkl-gen.c                    | 10 +++-
 libpoke/pkl-insn.def                 |  2 +
 libpoke/pkl-lex.l                    |  2 +-
 libpoke/pkl-pass.c                   |  2 +
 libpoke/pkl-promo.c                  | 49 +++++++++++-----
 libpoke/pkl-rt.pk                    | 18 +++++-
 libpoke/pkl-tab.y                    | 19 ++++--
 libpoke/pkl-trans.c                  |  2 +-
 libpoke/pkl-typify.c                 | 68 ++++++++++++++--------
 libpoke/pkl.c                        |  4 +-
 libpoke/pvm-val.c                    |  3 +-
 libpoke/pvm-val.h                    |  2 +
 libpoke/pvm.h                        |  2 +-
 libpoke/pvm.jitter                   | 47 ++++++++++++---
 testsuite/Makefile.am                |  8 +++
 testsuite/poke.pkl/add-offsets-11.pk | 15 +++++
 testsuite/poke.pkl/bnot-offsets-2.pk | 14 +++++
 testsuite/poke.pkl/div-offsets-5.pk  | 15 +++++
 testsuite/poke.pkl/mod-offsets-6.pk  | 15 +++++
 testsuite/poke.pkl/mul-offsets-12.pk | 15 +++++
 testsuite/poke.pkl/offset-type-2.pk  |  6 ++
 testsuite/poke.pkl/print-any-4.pk    | 11 ++++
 testsuite/poke.pkl/sub-offsets-9.pk  | 15 +++++
 30 files changed, 427 insertions(+), 75 deletions(-)
 create mode 100644 testsuite/poke.pkl/add-offsets-11.pk
 create mode 100644 testsuite/poke.pkl/bnot-offsets-2.pk
 create mode 100644 testsuite/poke.pkl/div-offsets-5.pk
 create mode 100644 testsuite/poke.pkl/mod-offsets-6.pk
 create mode 100644 testsuite/poke.pkl/mul-offsets-12.pk
 create mode 100644 testsuite/poke.pkl/offset-type-2.pk
 create mode 100644 testsuite/poke.pkl/print-any-4.pk
 create mode 100644 testsuite/poke.pkl/sub-offsets-9.pk

diff --git a/ChangeLog b/ChangeLog
index 61128120..c7da75de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,89 @@
+2023-02-12  Jose E. Marchesi  <jemarch@gnu.org>
+
+       * libpoke/pkl-ast.h (struct pkl_ast_type): New field ref_type in
+       offset types.
+       (PKL_AST_TYPE_O_REF_TYPE): Define.
+       * libpoke/pkl-ast.c (pkl_ast_make_offset_type): Get a ref_type
+       argument.
+       (pkl_ast_node_free_1): Free ref_type.
+       (pkl_ast_print_1): Print ref_type.
+       (pkl_type_append_to): Include ref_type in printed representation.
+       (pkl_ast_type_equal_p): Handle referred types.
+       * libpoke/pkl-tab.y (ref_type): New rule.
+       * libpoke/pkl-typify.c: Pass ref_type argument to calls to
+       pkl_ast_make_offset_type.
+       * libpoke/pkl-promo.c (promote_offset): Likewise.
+       * libpoke/pkl-trans.c: Likewise.
+       * libpoke/pkl-promo.c (promote_offset): Handle ref_type.
+       (promote_node): Likewise.
+       * libpoke/pkl-pass.c (pkl_do_pass_1): Traverse ref_type in offset
+       type nodes.
+       * libpoke/pkl-lex.l: Likewise.
+       * libpoke/pkl-gen.c (pkl_gen_pr_type_offset): Use ref_type.
+       * libpoke/pkl-rt.pk (_pkl_print_format_any): Print ref_type in
+       offset types.
+       * libpoke/pvm-val.h (PVM_VAL_TYP_O_REF_TYPE): Define.
+       * libpoke/pvm-val.c (pvm_make_offset_type): Get an argument
+       ref_type.
+       * libpoke/pvm.jitter (tyosetrt): New instruction.
+       (tyogetrt): Likewise.
+       * libpoke/pkl-insn.def: New instructions PKL_INSN_TYOSETRT and
+       PKL_INSN_TYOGETRT.
+       * libpoke/pk-val.c (pk_make_offset_type): Likewise.
+       * doc/poke.texi (Offset Types): Document referred types in offset
+       types.
+       * testsuite/poke.pkl/offset-type-2.pk: New test.
+       * testsuite/poke.pkl/print-any-4.pk: Likewise.
+       * testsuite/poke.pkl/add-offset-11.pk: Likewise.
+       * testsuite/poke.pkl/sub-offsets-9.pk: Likewise.
+       * testsuite/poke.pkl/mul-offsets-12.pk: Likewise.
+       * testsuite/poke.pkl/div-offsets-5.pk: Likewise.
+       * testsuite/poke.pkl/bnot-offsets-2.pk: Likewise.
+       * testsuite/Makefile.am (EXTRA_DIST): Add new tests.
+
+2023-02-12  Jose E. Marchesi  <jemarch@gnu.org>
+
+       * libpoke/pkl-ast.h (struct pkl_ast_type): New field ref_type in
+       offset types.
+       (PKL_AST_TYPE_O_REF_TYPE): Define.
+       * libpoke/pkl-ast.c (pkl_ast_make_offset_type): Get a ref_type
+       argument.
+       (pkl_ast_node_free_1): Free ref_type.
+       (pkl_ast_print_1): Print ref_type.
+       (pkl_type_append_to): Include ref_type in printed representation.
+       (pkl_ast_type_equal_p): Handle referred types.
+       * libpoke/pkl-tab.y (ref_type): New rule.
+       * libpoke/pkl-typify.c: Pass ref_type argument to calls to
+       pkl_ast_make_offset_type.
+       * libpoke/pkl-promo.c (promote_offset): Likewise.
+       * libpoke/pkl-trans.c: Likewise.
+       * libpoke/pkl-promo.c (promote_offset): Handle ref_type.
+       (promote_node): Likewise.
+       * libpoke/pkl-pass.c (pkl_do_pass_1): Traverse ref_type in offset
+       type nodes.
+       * libpoke/pkl-lex.l: Likewise.
+       * libpoke/pkl-gen.c (pkl_gen_pr_type_offset): Use ref_type.
+       * libpoke/pkl-rt.pk (_pkl_print_format_any): Print ref_type in
+       offset types.
+       * libpoke/pvm-val.h (PVM_VAL_TYP_O_REF_TYPE): Define.
+       * libpoke/pvm-val.c (pvm_make_offset_type): Get an argument
+       ref_type.
+       * libpoke/pvm.jitter (tyosetrt): New instruction.
+       (tyogetrt): Likewise.
+       * libpoke/pkl-insn.def: New instructions PKL_INSN_TYOSETRT and
+       PKL_INSN_TYOGETRT.
+       * libpoke/pk-val.c (pk_make_offset_type): Likewise.
+       * doc/poke.texi (Offset Types): Document referred types in offset
+       types.
+       * testsuite/poke.pkl/offset-type-2.pk: New test.
+       * testsuite/poke.pkl/print-any-4.pk: Likewise.
+       * testsuite/poke.pkl/add-offset-11.pk: Likewise.
+       * testsuite/poke.pkl/sub-offsets-9.pk: Likewise.
+       * testsuite/poke.pkl/mul-offsets-11.pk: Likewise.
+       * testsuite/poke.pkl/div-offsets-5.pk: Likewise.
+       * testsuite/poke.pkl/bnot-offsets-2.pk: Likewise.
+       * testsuite/Makefile.am (EXTRA_DIST): Add new tests.
+
 2023-04-21  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
 
        * libpoke/pkl-tab.y (primary): Add new rule for `format' with no
diff --git a/doc/poke.texi b/doc/poke.texi
index ef7f8d77..c054bd71 100644
--- a/doc/poke.texi
+++ b/doc/poke.texi
@@ -9950,9 +9950,11 @@ entirely.  To denote one kilobyte, for example, we can 
write
 @node Offset Types
 @subsection Offset Types
 
-Offset types are denoted as @code{offset<@var{base_type},@var{unit}>},
-where @var{base_type} is an integer type and @var{unit} the
-specification of an unit.
+Offset types are denoted as
+@code{offset<@var{base_type},@var{unit}[,@var{ref_type}]>}, where
+@var{base_type} is an integer type, @var{unit} the specification of an
+unit, and @var{ref_type} is an optional type of a @dfn{referred
+value}.
 
 The offset base type is the type of the magnitude part of the united
 value.  It can be any integer type, signed or unsigned, of any size.
@@ -9961,6 +9963,10 @@ The unit specification should be one of the unit 
identifiers that are
 allowed in offset literals (see above), a constant positive integer or
 the name of a Poke type whose size is known at compile time.
 
+If a referred type is specified, this tells poke that the offset may
+be used in order to refer to a value stored on some IO space.  This is
+similar to the notion of a pointer in other programming languages.
+
 @cindex kilobits
 Let's see some examples.  A signed 32-bit offset expressed in bytes
 has type @code{offset<int<32>,B>}.  An unsigned 12-bit offset
@@ -9970,6 +9976,10 @@ type can also be written using an explicit integer unit 
like in
 of ``packets'', where a packet is denoted with a Poke type
 @code{Packet} has type @code{offset<uint<64>,Packet>}.
 
+An offset whose purpose is to refer to some data structure of type
+@code{Packet} stored in some IO space could have type
+@code{offset<uint<64>,B,Packet>}.
+
 @node Casting Offsets
 @subsection Casting Offsets
 @cindex casts
@@ -10014,7 +10024,7 @@ Examples:
 @end example
 
 The unit of the result is the greatest common divisor of the units of
-the operands.
+the operands.  The result offset is not a referring offset.
 
 The operators @code{++} and @code{--}, in their prefix and suffix
 versions, can be applied to offsets as well.  The step used in the
@@ -10032,8 +10042,8 @@ Examples:
 0#MB
 @end example
 
-The unit of the result is the same as the unit of the offset
-operand.
+The unit of the result is the same as the unit of the offset operand.
+The result offset is not a referring offset.
 
 Note that multiplying two offsets is not supported.  This makes sense,
 since computer memory is linear, and therefore it wouldn't make any
@@ -10081,6 +10091,9 @@ Dividing an offset by an integer gives you an offset.  
Example:
 4#B
 @end example
 
+The unit of the result is the unit of the offset operand.  The result
+offset is not a referring offset.
+
 @subsubsection Modulus
 @cindex modulus
 The modulus of two offsets gives you another offset with the expected
@@ -10094,7 +10107,7 @@ semantics.  Examples:
 @end example
 
 The unit of the result is the greatest common divisor of the units of
-the operands.
+the operands.  The result offset is not a referring offset.
 
 @node Offset Attributes
 @subsection Offset Attributes
diff --git a/libpoke/libpoke.h b/libpoke/libpoke.h
index 32cba115..7732f96c 100644
--- a/libpoke/libpoke.h
+++ b/libpoke/libpoke.h
@@ -966,9 +966,12 @@ pk_val pk_make_any_type (void) LIBPOKE_API;
    of the offset.
 
    UNIT is an uint<64> with the unit of the offset type.  The unit is
-   a multiple of the base unit, which is the bit.  */
+   a multiple of the base unit, which is the bit.
 
-pk_val pk_make_offset_type (pk_val base_type, pk_val unit) LIBPOKE_API;
+   REF_TYPE is either PK_NULL or the type of the referenced type if the
+   offset is also a reference or pointer.  */
+
+pk_val pk_make_offset_type (pk_val base_type, pk_val unit, pk_val ref_type) 
LIBPOKE_API;
 
 /* Get the base type of a given offset type.  */
 
diff --git a/libpoke/pk-val.c b/libpoke/pk-val.c
index 9605eefe..5bafce8f 100644
--- a/libpoke/pk-val.c
+++ b/libpoke/pk-val.c
@@ -94,7 +94,7 @@ pk_make_offset (pk_val magnitude, pk_val unit)
   else
     {
       pvm_val type = pvm_make_offset_type (pvm_typeof (magnitude),
-                                           unit);
+                                           unit, PVM_NULL /* ref_type */);
       return pvm_make_offset (magnitude, type);
     }
 }
@@ -385,9 +385,9 @@ pk_make_string_type (void)
 }
 
 pk_val
-pk_make_offset_type (pk_val base_type, pk_val unit)
+pk_make_offset_type (pk_val base_type, pk_val unit, pk_val ref_type)
 {
-  return pvm_make_offset_type (base_type, unit);
+  return pvm_make_offset_type (base_type, unit, ref_type);
 }
 
 pk_val
diff --git a/libpoke/pkl-ast.c b/libpoke/pkl-ast.c
index 123c8f65..16133544 100644
--- a/libpoke/pkl-ast.c
+++ b/libpoke/pkl-ast.c
@@ -448,7 +448,8 @@ pkl_ast_make_void_type (pkl_ast ast)
 pkl_ast_node
 pkl_ast_make_offset_type (pkl_ast ast,
                           pkl_ast_node base_type,
-                          pkl_ast_node unit)
+                          pkl_ast_node unit,
+                          pkl_ast_node ref_type)
 {
   pkl_ast_node type = pkl_ast_make_type (ast);
 
@@ -459,6 +460,8 @@ pkl_ast_make_offset_type (pkl_ast ast,
     = PKL_AST_TYPE_COMPLETE_YES;
   PKL_AST_TYPE_O_UNIT (type) = ASTREF (unit);
   PKL_AST_TYPE_O_BASE_TYPE (type) = ASTREF (base_type);
+  if (ref_type)
+    PKL_AST_TYPE_O_REF_TYPE (type) = ASTREF (ref_type);
 
   return type;
 }
@@ -933,6 +936,8 @@ pkl_ast_type_equal_p (pkl_ast_node a, pkl_ast_node b)
       {
         pkl_ast_node a_unit = PKL_AST_TYPE_O_UNIT (a);
         pkl_ast_node b_unit = PKL_AST_TYPE_O_UNIT (b);
+        pkl_ast_node a_ref_type = PKL_AST_TYPE_O_REF_TYPE (a);
+        pkl_ast_node b_ref_type = PKL_AST_TYPE_O_REF_TYPE (b);
 
         /* If the units of the types are not known yet (because they
            are identifiers, or whatever then we cannot guarantee the
@@ -941,6 +946,14 @@ pkl_ast_type_equal_p (pkl_ast_node a, pkl_ast_node b)
             || PKL_AST_CODE (b_unit) != PKL_AST_INTEGER)
           return 0;
 
+        /* Offset types having different referred types are not
+           equal.  */
+        if (!((a_ref_type == NULL && b_ref_type == NULL)
+              || (a_ref_type
+                  && b_ref_type
+                  && pkl_ast_type_equal_p (a_ref_type, b_ref_type))))
+          return 0;
+
         return (PKL_AST_INTEGER_VALUE (a_unit) == PKL_AST_INTEGER_VALUE 
(b_unit)
                   && pkl_ast_type_equal_p (PKL_AST_TYPE_O_BASE_TYPE (a),
                                            PKL_AST_TYPE_O_BASE_TYPE (b)));
@@ -1531,6 +1544,13 @@ pkl_type_append_to (pkl_ast_node type, int 
use_given_name,
         else
           PK_UNREACHABLE ();
 
+        if (PKL_AST_TYPE_O_REF_TYPE (type))
+          {
+            sb_append (buffer, ",");
+            pkl_type_append_to (PKL_AST_TYPE_O_REF_TYPE (type), 1,
+                                buffer);
+          }
+
         sb_append (buffer, ">");
         break;
       }
@@ -2392,6 +2412,7 @@ pkl_ast_node_free_1 (gl_set_t visitations, pkl_ast_node 
ast)
         case PKL_TYPE_OFFSET:
           PKL_AST_NODE_FREE (PKL_AST_TYPE_O_UNIT (ast));
           PKL_AST_NODE_FREE (PKL_AST_TYPE_O_BASE_TYPE (ast));
+          PKL_AST_NODE_FREE (PKL_AST_TYPE_O_REF_TYPE (ast));
           break;
         case PKL_TYPE_INTEGRAL:
         case PKL_TYPE_STRING:
@@ -3292,6 +3313,7 @@ pkl_ast_print_1 (FILE *fp, pkl_ast_node ast, int indent)
             case PKL_TYPE_OFFSET:
               PRINT_AST_SUBAST (base_type, TYPE_O_BASE_TYPE);
               PRINT_AST_SUBAST (unit, TYPE_O_UNIT);
+              PRINT_AST_SUBAST (ref_type, TYPE_O_REF_TYPE);
               break;
             case PKL_TYPE_STRING:
             case PKL_TYPE_ANY:
diff --git a/libpoke/pkl-ast.h b/libpoke/pkl-ast.h
index dc357850..41c5b317 100644
--- a/libpoke/pkl-ast.h
+++ b/libpoke/pkl-ast.h
@@ -964,6 +964,7 @@ pkl_ast_node pkl_ast_make_func_type_arg (pkl_ast ast,
 #define PKL_AST_TYPE_S_ITYPE(AST) ((AST)->type.val.sct.itype)
 #define PKL_AST_TYPE_O_UNIT(AST) ((AST)->type.val.off.unit)
 #define PKL_AST_TYPE_O_BASE_TYPE(AST) ((AST)->type.val.off.base_type)
+#define PKL_AST_TYPE_O_REF_TYPE(AST) ((AST)->type.val.off.ref_type)
 #define PKL_AST_TYPE_F_RTYPE(AST) ((AST)->type.val.fun.rtype)
 #define PKL_AST_TYPE_F_NARG(AST) ((AST)->type.val.fun.narg)
 #define PKL_AST_TYPE_F_ARGS(AST) ((AST)->type.val.fun.args)
@@ -1020,6 +1021,7 @@ struct pkl_ast_type
     {
       union pkl_ast_node *unit;
       union pkl_ast_node *base_type;
+      union pkl_ast_node *ref_type;
     } off;
 
     struct
@@ -1051,7 +1053,7 @@ pkl_ast_node pkl_ast_make_struct_type (pkl_ast ast, 
size_t nelem, size_t nfield,
                                        int pinned_p, int union_p);
 
 pkl_ast_node pkl_ast_make_offset_type (pkl_ast ast, pkl_ast_node base_type,
-                                       pkl_ast_node unit);
+                                       pkl_ast_node unit, pkl_ast_node 
ref_type);
 
 pkl_ast_node pkl_ast_make_function_type (pkl_ast ast, pkl_ast_node rtype,
                                          size_t narg, pkl_ast_node args);
diff --git a/libpoke/pkl-fold.c b/libpoke/pkl-fold.c
index fe1d7692..e7c1c3df 100644
--- a/libpoke/pkl-fold.c
+++ b/libpoke/pkl-fold.c
@@ -1130,10 +1130,12 @@ PKL_PHASE_BEGIN_HANDLER (pkl_fold_ps_cast)
       pkl_ast_node to_unit = PKL_AST_TYPE_O_UNIT (to_type);
       pkl_ast_node from_base_type = PKL_AST_TYPE_O_BASE_TYPE (from_type);
       pkl_ast_node to_base_type = PKL_AST_TYPE_O_BASE_TYPE (to_type);
+      pkl_ast_node to_ref_type = PKL_AST_TYPE_O_REF_TYPE (to_type);
 
       if (PKL_AST_CODE (magnitude) != PKL_AST_INTEGER
           || PKL_AST_CODE (unit) != PKL_AST_INTEGER
-          || PKL_AST_CODE (to_unit) != PKL_AST_INTEGER)
+          || PKL_AST_CODE (to_unit) != PKL_AST_INTEGER
+          || to_ref_type != NULL) /* XXX why?? */
         /* We can't fold this cast.  */
         PKL_PASS_DONE;
 
diff --git a/libpoke/pkl-gen.c b/libpoke/pkl-gen.c
index 9e4d837d..8ed59586 100644
--- a/libpoke/pkl-gen.c
+++ b/libpoke/pkl-gen.c
@@ -2236,8 +2236,14 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_offset)
     {
     /* Just build an offset type.  */
       PKL_PASS_SUBPASS (PKL_AST_TYPE_O_BASE_TYPE (PKL_PASS_NODE)); /* 
BASE_TYPE */
-      PKL_PASS_SUBPASS (PKL_AST_TYPE_O_UNIT (PKL_PASS_NODE));      /* UNIT */
-      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MKTYO);
+      PKL_PASS_SUBPASS (PKL_AST_TYPE_O_UNIT (PKL_PASS_NODE));      /* 
BASE_TYPE UNIT */
+      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MKTYO);                  /* TYPE */
+      if (PKL_AST_TYPE_O_REF_TYPE (PKL_PASS_NODE))
+        {
+          PKL_PASS_SUBPASS (PKL_AST_TYPE_O_REF_TYPE (PKL_PASS_NODE));  /* TYPE 
REF_TYPE */
+          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_TYOSETRT);               /* TYPE 
*/
+        }
+
       PKL_PASS_BREAK;
     }
 
diff --git a/libpoke/pkl-insn.def b/libpoke/pkl-insn.def
index 94a0a06b..71bf71e5 100644
--- a/libpoke/pkl-insn.def
+++ b/libpoke/pkl-insn.def
@@ -367,6 +367,8 @@ PKL_DEF_INSN(PKL_INSN_TYISS,"","tyiss")
 PKL_DEF_INSN(PKL_INSN_MKTYO,"","mktyo")
 PKL_DEF_INSN(PKL_INSN_TYOGETM,"","tyogetm")
 PKL_DEF_INSN(PKL_INSN_TYOGETU,"","tyogetu")
+PKL_DEF_INSN(PKL_INSN_TYOGETRT,"","tyogetrt")
+PKL_DEF_INSN(PKL_INSN_TYOSETRT,"","tyosetrt")
 PKL_DEF_INSN(PKL_INSN_TYISO,"","tyiso")
 
 PKL_DEF_INSN(PKL_INSN_MKTYC,"","mktyc")
diff --git a/libpoke/pkl-lex.l b/libpoke/pkl-lex.l
index 7494f024..e64462c3 100644
--- a/libpoke/pkl-lex.l
+++ b/libpoke/pkl-lex.l
@@ -458,7 +458,7 @@ S ::
             /* Build the offset value itself.  */
             offset_type = pkl_ast_make_offset_type (yyextra->ast,
                                                     magnitude_type,
-                                                    unit);
+                                                    unit, NULL /* ref_type */);
             yylval->ast = pkl_ast_make_offset (yyextra->ast,
                                                magnitude, unit);
             PKL_AST_TYPE (yylval->ast) = ASTREF (offset_type);
diff --git a/libpoke/pkl-pass.c b/libpoke/pkl-pass.c
index 29274a7e..c4148dfc 100644
--- a/libpoke/pkl-pass.c
+++ b/libpoke/pkl-pass.c
@@ -447,6 +447,8 @@ pkl_do_pass_1 (pkl_compiler compiler,
           case PKL_TYPE_OFFSET:
             PKL_PASS (PKL_AST_TYPE_O_BASE_TYPE (node));
             PKL_PASS (PKL_AST_TYPE_O_UNIT (node));
+            if (PKL_AST_TYPE_O_REF_TYPE (node))
+              PKL_PASS (PKL_AST_TYPE_O_REF_TYPE (node));
 
             break;
           case PKL_TYPE_INTEGRAL:
diff --git a/libpoke/pkl-promo.c b/libpoke/pkl-promo.c
index 5f239fcf..113febab 100644
--- a/libpoke/pkl-promo.c
+++ b/libpoke/pkl-promo.c
@@ -96,6 +96,7 @@ static int
 promote_offset (pkl_ast ast,
                 size_t size, int sign,
                 pkl_ast_node unit,
+                pkl_ast_node ref_type,
                 pkl_ast_node *a,
                 int *restart)
 {
@@ -111,6 +112,7 @@ promote_offset (pkl_ast ast,
       int a_type_base_type_sign = PKL_AST_TYPE_I_SIGNED_P (a_type_base_type);
 
       int different_units = 1;
+      int different_ref_types = 1;
 
       /* If the offset units happen to be integer nodes, we can
          determine whether they are equal right away.  */
@@ -120,9 +122,19 @@ promote_offset (pkl_ast ast,
               == PKL_AST_INTEGER_VALUE (unit)))
         different_units = 0;
 
+      /* Determine whether both offset types do not have a referred
+         type, or if the referred type is the same.  */
+      if ((!PKL_AST_TYPE_O_REF_TYPE (a_type) && !ref_type)
+          || (ref_type
+              && PKL_AST_TYPE_O_REF_TYPE (a_type)
+              && !pkl_ast_type_equal_p (PKL_AST_TYPE_O_REF_TYPE (a_type),
+                                        ref_type)))
+        different_ref_types = 0;
+
       if (a_type_base_type_size != size
           || a_type_base_type_sign != sign
-          || different_units)
+          || different_units
+          || different_ref_types)
         {
           pkl_ast_loc loc = PKL_AST_LOC (*a);
           pkl_ast_node base_type
@@ -130,7 +142,7 @@ promote_offset (pkl_ast ast,
           pkl_ast_node unit_type
             = pkl_ast_make_integral_type (ast, 64, 0);
           pkl_ast_node type
-            = pkl_ast_make_offset_type (ast, base_type, unit);
+            = pkl_ast_make_offset_type (ast, base_type, unit, NULL /* ref_type 
*/);
 
           PKL_AST_TYPE (unit) = ASTREF (unit_type);
           PKL_AST_LOC (base_type) = loc;
@@ -238,12 +250,13 @@ promote_node (pkl_ast ast,
           {
             pkl_ast_node base_type = PKL_AST_TYPE_O_BASE_TYPE (type);
             pkl_ast_node unit = PKL_AST_TYPE_O_UNIT (type);
+            pkl_ast_node ref_type = PKL_AST_TYPE_O_REF_TYPE (type);
 
             size_t size = PKL_AST_TYPE_I_SIZE (base_type);
             int signed_p = PKL_AST_TYPE_I_SIGNED_P (base_type);
 
             if (!promote_offset (ast,
-                                 size, signed_p, unit,
+                                 size, signed_p, unit, ref_type,
                                  node,
                                  restart))
               goto error;
@@ -341,12 +354,12 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_op_div)
             PKL_AST_LOC (unit_bit) = PKL_AST_LOC (exp);
 
             if (!promote_offset (PKL_PASS_AST,
-                                 size, signed_p, unit_bit,
+                                 size, signed_p, unit_bit, NULL /* ref_type */,
                                  &PKL_AST_EXP_OPERAND (exp, 0), &restart1))
               goto error;
 
             if (!promote_offset (PKL_PASS_AST,
-                                 size, signed_p, unit_bit,
+                                 size, signed_p, unit_bit, NULL /* ref_type */,
                                  &PKL_AST_EXP_OPERAND (exp, 1), &restart2))
               goto error;
 
@@ -356,16 +369,22 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_op_div)
           }
         else
           {
-            int restart;
+            int restart1, restart2;
             pkl_ast_node op1_base_type = PKL_AST_TYPE_O_BASE_TYPE (op1_type);
 
+            if (!promote_node (PKL_PASS_AST,
+                               &PKL_AST_EXP_OPERAND (exp, 0),
+                               PKL_AST_TYPE (PKL_PASS_NODE),
+                               &restart1))
+              goto error;
+
             if (!promote_node (PKL_PASS_AST,
                                &PKL_AST_EXP_OPERAND (exp, 1),
                                op1_base_type,
-                               &restart))
+                               &restart2))
               goto error;
 
-            PKL_PASS_RESTART = restart;
+            PKL_PASS_RESTART = restart1 || restart2;
           }
         break;
       }
@@ -695,12 +714,12 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_op_rela)
         PKL_AST_LOC (unit_bit) = PKL_AST_LOC (exp);
 
         if (!promote_offset (PKL_PASS_AST,
-                             size, signed_p, unit_bit,
+                             size, signed_p, unit_bit, NULL /* ref_type */,
                              &PKL_AST_EXP_OPERAND (exp, 0), &restart1))
           goto error;
 
         if (!promote_offset (PKL_PASS_AST,
-                             size, signed_p, unit_bit,
+                             size, signed_p, unit_bit, NULL /* ref_type */,
                              &PKL_AST_EXP_OPERAND (exp, 1), &restart2))
           goto error;
 
@@ -774,7 +793,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_op_bshiftpow)
         int signed_p = PKL_AST_TYPE_I_SIGNED_P (base_type);
 
         if (!promote_offset (PKL_PASS_AST,
-                             size, signed_p, unit,
+                             size, signed_p, unit, NULL /* ref_type */,
                              &PKL_AST_EXP_OPERAND (exp, 0), &restart1)
             || !promote_integral (PKL_PASS_AST, 32, 0,
                                   &PKL_AST_EXP_OPERAND (exp, 1), &restart2))
@@ -890,7 +909,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_indexer)
       pkl_ast_node unit_bit = pkl_ast_make_integer (PKL_PASS_AST, 1);
       unit_bit = ASTREF (unit_bit);
 
-      if (!promote_offset (PKL_PASS_AST, 64, 0, unit_bit,
+      if (!promote_offset (PKL_PASS_AST, 64, 0, unit_bit, NULL /* ref_type */,
                            &PKL_AST_INDEXER_INDEX (node), &restart))
         {
           PKL_ICE (PKL_AST_LOC (node),
@@ -995,7 +1014,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_type_array)
         unit_bit = ASTREF (unit_bit);
 
         if (!promote_offset (PKL_PASS_AST,
-                             64, 0, unit_bit,
+                             64, 0, unit_bit, NULL /* ref_type */,
                              &PKL_AST_TYPE_A_BOUND (array_type), &restart))
           {
             PKL_ICE (PKL_AST_LOC (bound),
@@ -1331,7 +1350,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_map)
   unit_bit = ASTREF (unit_bit);
 
   if (!promote_offset (PKL_PASS_AST,
-                       64, 0, unit_bit,
+                       64, 0, unit_bit, NULL /* ref_type */,
                        &PKL_AST_MAP_OFFSET (map),
                        &restart))
     {
@@ -1532,7 +1551,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_struct_type_field)
           pkl_ast_node unit_bit = pkl_ast_make_integer (PKL_PASS_AST, 1);
 
           if (!promote_offset (PKL_PASS_AST,
-                               64, 0, unit_bit,
+                               64, 0, unit_bit, NULL /* ref_type */,
                                &PKL_AST_STRUCT_TYPE_FIELD_LABEL (elem),
                                &restart))
             {
diff --git a/libpoke/pkl-rt.pk b/libpoke/pkl-rt.pk
index be60948c..290d4acb 100644
--- a/libpoke/pkl-rt.pk
+++ b/libpoke/pkl-rt.pk
@@ -1298,7 +1298,8 @@ immutable type _Pkl_Print_Format_Ctx =
 immutable fun _pkl_print_format_any = (any val,
                                        _Pkl_Print_Format_Ctx ctx,
                                        int<32> depth,
-                                       int<32> obase = vm_obase) void:
+                                       int<32> obase = vm_obase,
+                                       int<32> only_struct_type_name = 0) void:
 {
   fun lutos = (uint<64> i, int<32> base, int<32> padbits = 0) string:
   {
@@ -1329,6 +1330,7 @@ immutable fun _pkl_print_format_any = (any val,
 
     return s;
   }
+
   fun handle_type = void:
   {
     ctx.begin_class ("type");
@@ -1349,10 +1351,17 @@ immutable fun _pkl_print_format_any = (any val,
       {
         var base_type = asm any: ("tyogetm; nip" : val),
             unit_in_bits = asm uint<64>: ("tyogetu; nip" : val);
+        var ref_type = asm any: ("tyogetrt; nip" : val);
 
         ctx.emit ("offset<");
         _pkl_print_format_any (base_type, ctx, depth);
-        ctx.emit ("," + lutos (unit_in_bits, 10) + ">");
+        ctx.emit ("," + lutos (unit_in_bits, 10));
+        if (asm int<32>: ("nn; nip" : ref_type))
+          {
+            ctx.emit (",");
+            _pkl_print_format_any (ref_type, ctx, depth, obase, 1);
+          }
+        ctx.emit (">");
       }
     else if (asm int<32>: ("tyiss; nip" : val))
       ctx.emit ("string");
@@ -1377,6 +1386,11 @@ immutable fun _pkl_print_format_any = (any val,
         var nfields = asm uint<64>: ("tysctgetnf; nip" : val);
 
         ctx.emit (name);
+        if (name != "struct" && only_struct_type_name)
+          {
+            ctx.end_class ("type");
+            return;
+          }
         ctx.emit (" {");
         for (var i = 0UL; i < nfields; ++i)
           {
diff --git a/libpoke/pkl-tab.y b/libpoke/pkl-tab.y
index 47023cc2..2fe17b65 100644
--- a/libpoke/pkl-tab.y
+++ b/libpoke/pkl-tab.y
@@ -566,7 +566,7 @@ load_module (struct pkl_parser *parser,
 %type <ast> typename type_specifier simple_type_specifier cons_type_specifier
 %type <ast> integral_type_specifier offset_type_specifier array_type_specifier
 %type <ast> function_type_specifier function_type_arg_list function_type_arg
-%type <ast> struct_type_specifier string_type_specifier
+%type <ast> struct_type_specifier string_type_specifier ref_type
 %type <ast> struct_type_elem_list struct_type_field 
struct_type_field_identifier
 %type <ast> struct_type_field_label struct_type_computed_field
 %type <field_const_init> struct_type_field_constraint_and_init
@@ -1596,8 +1596,13 @@ integral_type_sign:
         | UINTCONSTR        { $$ = 0; }
         ;
 
+ref_type:
+          %empty                      { $$ = NULL; }
+        | ',' simple_type_specifier { $$ = $2; }
+        ;
+
 offset_type_specifier:
-          OFFSETCONSTR simple_type_specifier ',' identifier '>'
+          OFFSETCONSTR simple_type_specifier ',' identifier ref_type '>'
                 {
                   pkl_ast_node decl
                     = pkl_env_lookup (pkl_parser->env,
@@ -1623,15 +1628,16 @@ offset_type_specifier:
 
                   $$ = pkl_ast_make_offset_type (pkl_parser->ast,
                                                  $2,
-                                                 PKL_AST_DECL_INITIAL (decl));
+                                                 PKL_AST_DECL_INITIAL (decl),
+                                                 $5);
 
                   $4 = ASTREF ($4); pkl_ast_node_free ($4);
                   PKL_AST_LOC ($$) = @$;
                 }
-        | OFFSETCONSTR simple_type_specifier ',' integer '>'
+        | OFFSETCONSTR simple_type_specifier ',' integer ref_type '>'
                 {
                     $$ = pkl_ast_make_offset_type (pkl_parser->ast,
-                                                   $2, $4);
+                                                   $2, $4, $5);
                     PKL_AST_LOC (PKL_AST_TYPE ($4)) = @4;
                     PKL_AST_LOC ($4) = @4;
                     PKL_AST_LOC ($$) = @$;
@@ -1757,7 +1763,8 @@ struct_type_specifier:
                                                   offset_unit);
                     type = pkl_ast_make_offset_type (pkl_parser->ast,
                                                      type,
-                                                     offset_unit);
+                                                     offset_unit,
+                                                     NULL /* ref_type */);
                     PKL_AST_TYPE (offset) = ASTREF (type);
 
                     decl = pkl_ast_make_decl (pkl_parser->ast,
diff --git a/libpoke/pkl-trans.c b/libpoke/pkl-trans.c
index 27c4554f..b8184557 100644
--- a/libpoke/pkl-trans.c
+++ b/libpoke/pkl-trans.c
@@ -1973,7 +1973,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans3_ps_op_sizeof)
 
     offset_type = pkl_ast_make_offset_type (PKL_PASS_AST,
                                             PKL_AST_TYPE (magnitude),
-                                            unit);
+                                            unit, NULL /* ref_type */);
     PKL_AST_TYPE (offset) = ASTREF (offset_type);
   }
 
diff --git a/libpoke/pkl-typify.c b/libpoke/pkl-typify.c
index 98342992..d81dfdc8 100644
--- a/libpoke/pkl-typify.c
+++ b/libpoke/pkl-typify.c
@@ -338,6 +338,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_neg_pos_bnot)
   pkl_ast_node exp = PKL_PASS_NODE;
   pkl_ast_node op1 = PKL_AST_EXP_OPERAND (exp, 0);
   pkl_ast_node op1_type = PKL_AST_TYPE (op1);
+  pkl_ast_node type = NULL;
 
   /* Handle an integral struct operand.  */
   if (PKL_AST_TYPE_CODE (op1_type) == PKL_TYPE_STRUCT
@@ -347,13 +348,22 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_neg_pos_bnot)
   switch (PKL_AST_TYPE_CODE (op1_type))
     {
     case PKL_TYPE_INTEGRAL:
+      type = op1_type;
+      break;
     case PKL_TYPE_OFFSET:
+      /* The type of the result has the same magnitude and unit
+         than the operand, but some attributes of the type are
+         not propagated.  */
+      type = pkl_ast_make_offset_type (PKL_PASS_AST,
+                                       PKL_AST_TYPE_O_BASE_TYPE (op1_type),
+                                       PKL_AST_TYPE_O_UNIT (op1_type),
+                                       NULL /* ref_type */);
       break;
     default:
       INVALID_OPERAND (op1, "expected integral or offset");
     }
 
-  PKL_AST_TYPE (exp) = ASTREF (op1_type);
+  PKL_AST_TYPE (exp) = ASTREF (type);
 }
 PKL_PHASE_END_HANDLER
 
@@ -601,20 +611,24 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_bin)
               INVALID_OPERAND (op2, "expected integral or offset");
 
             /* For OFFSET / INTEGRAL the type of the result is the
-               type of the first operand.  */
+               type of the first operand.  But note that ref_type is
+               not propagated.  */
             if (op2_type_code == PKL_TYPE_INTEGRAL)
               {
-                type = op1_type;
-                break;
+                type = pkl_ast_make_offset_type (PKL_PASS_AST,
+                                                 PKL_AST_TYPE_O_BASE_TYPE 
(op1_type),
+                                                 PKL_AST_TYPE_O_UNIT 
(op1_type),
+                                                 NULL /* ref_type */);
+              }
+            else
+              {
+                /* For OFFSET / OFFSET the type of the result is an
+                   integral as promoted by the base types of the
+                   offset operands.  */
+                type = pkl_type_integral_promote (PKL_PASS_AST,
+                                                  PKL_AST_TYPE_O_BASE_TYPE 
(op1_type),
+                                                  PKL_AST_TYPE_O_BASE_TYPE 
(op2_type));
               }
-
-            /* For OFFSET / OFFSET the type of the result is an
-               integral as promoted by the base types of the offset
-               operands.  */
-
-            type = pkl_type_integral_promote (PKL_PASS_AST,
-                                              PKL_AST_TYPE_O_BASE_TYPE 
(op1_type),
-                                              PKL_AST_TYPE_O_BASE_TYPE 
(op2_type));
             break;
           case PKL_AST_OP_MOD:
             {
@@ -646,7 +660,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_bin)
               PKL_AST_TYPE (unit) = ASTREF (unit_type);
 
               type = pkl_ast_make_offset_type (PKL_PASS_AST,
-                                               base_type_1, unit);
+                                               base_type_1, unit,
+                                               NULL /* ref_type */);
               break;
             }
           default:
@@ -687,7 +702,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_bin)
               PKL_AST_TYPE (unit) = ASTREF (unit_type);
               type = pkl_ast_make_offset_type (PKL_PASS_AST,
                                                base_type,
-                                               unit);
+                                               unit, NULL /* ref_type */);
               break;
             }
           }
@@ -776,7 +791,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_bshift_pow)
         pkl_ast_node unit = PKL_AST_TYPE_O_UNIT (op1_type);
 
         type = pkl_ast_make_offset_type (PKL_PASS_AST,
-                                         base_type, unit);
+                                         base_type, unit, NULL /* ref_type */);
         break;
       }
     default:
@@ -846,7 +861,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_mul)
                                                    op2_type);
         type = pkl_ast_make_offset_type (PKL_PASS_AST,
                                          res_base_type,
-                                         PKL_AST_TYPE_O_UNIT (op1_type));
+                                         PKL_AST_TYPE_O_UNIT (op1_type),
+                                         NULL /* ref_type */);
         break;
       }
     case PKL_TYPE_INTEGRAL:
@@ -867,7 +883,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_mul)
                                            op1_type);
             type = pkl_ast_make_offset_type (PKL_PASS_AST,
                                              res_base_type,
-                                             PKL_AST_TYPE_O_UNIT (op2_type));
+                                             PKL_AST_TYPE_O_UNIT (op2_type),
+                                             NULL /* ref_type */);
             break;
           }
         default:
@@ -986,7 +1003,7 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_op_sizeof)
     = pkl_ast_make_integer (PKL_PASS_AST, PKL_AST_OFFSET_UNIT_BITS);
 
   pkl_ast_node type
-    = pkl_ast_make_offset_type (PKL_PASS_AST, itype, unit);
+    = pkl_ast_make_offset_type (PKL_PASS_AST, itype, unit, NULL /* ref_type 
*/);
 
   PKL_AST_TYPE (unit) = ASTREF (itype);
   PKL_AST_TYPE (PKL_PASS_NODE) = ASTREF (type);
@@ -1045,7 +1062,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_offset)
     }
 
   type = pkl_ast_make_offset_type (PKL_PASS_AST,
-                                   magnitude_type, unit);
+                                   magnitude_type, unit,
+                                   NULL /* ref_type */);
   PKL_AST_TYPE (offset) = ASTREF (type);
 }
 PKL_PHASE_END_HANDLER
@@ -2560,7 +2578,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_attr)
       PKL_AST_TYPE (offset_unit) = ASTREF (offset_unit_type);
 
       exp_type = pkl_ast_make_integral_type (PKL_PASS_AST, 64, 0);
-      exp_type = pkl_ast_make_offset_type (PKL_PASS_AST, exp_type, 
offset_unit);
+      exp_type = pkl_ast_make_offset_type (PKL_PASS_AST, exp_type, offset_unit,
+                                           NULL /* ref_type */);
 
       PKL_AST_TYPE (exp) = ASTREF (exp_type);
       break;
@@ -2611,7 +2630,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_attr)
       PKL_AST_TYPE (offset_unit) = ASTREF (offset_unit_type);
 
       exp_type = pkl_ast_make_integral_type (PKL_PASS_AST, 64, 0);
-      exp_type = pkl_ast_make_offset_type (PKL_PASS_AST, exp_type, 
offset_unit);
+      exp_type = pkl_ast_make_offset_type (PKL_PASS_AST, exp_type, offset_unit,
+                                           NULL /* ref_type */);
 
       PKL_AST_TYPE (exp) = ASTREF (exp_type);
       break;
@@ -2678,7 +2698,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_attr)
             PKL_AST_TYPE (offset_unit) = ASTREF (offset_unit_type);
 
             exp_type = pkl_ast_make_integral_type (PKL_PASS_AST, 64, 0);
-            exp_type = pkl_ast_make_offset_type (PKL_PASS_AST, exp_type, 
offset_unit);
+            exp_type = pkl_ast_make_offset_type (PKL_PASS_AST, exp_type, 
offset_unit,
+                                                 NULL /* ref_type */);
           }
 
         PKL_AST_TYPE (exp) = ASTREF (exp_type);
@@ -2886,7 +2907,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_struct_type_field)
       pkl_ast_node offset_type
         = pkl_ast_make_offset_type (PKL_PASS_AST,
                                     pkl_ast_make_integral_type (PKL_PASS_AST, 
64, 0),
-                                    pkl_ast_make_integer (PKL_PASS_AST, 1));
+                                    pkl_ast_make_integer (PKL_PASS_AST, 1),
+                                    NULL /* ref_type */);
 
 
       if (!pkl_ast_type_promoteable_p (label_type, offset_type,
diff --git a/libpoke/pkl.c b/libpoke/pkl.c
index a067c7e0..0f781e8c 100644
--- a/libpoke/pkl.c
+++ b/libpoke/pkl.c
@@ -823,8 +823,10 @@ pvm_type_to_ast_type (pkl_ast ast, pvm_val type)
           = pvm_type_to_ast_type (ast, PVM_VAL_TYP_O_BASE_TYPE (type));
         pkl_ast_node unit
           = pkl_ast_make_integer (ast, PVM_VAL_ULONG (PVM_VAL_TYP_O_UNIT 
(type)));
+        pkl_ast_node ref_type
+          = pvm_type_to_ast_type (ast, PVM_VAL_TYP_O_REF_TYPE (type));
 
-        return pkl_ast_make_offset_type (ast, base_type, unit);
+        return pkl_ast_make_offset_type (ast, base_type, unit, ref_type);
         break;
       }
     case PVM_TYPE_VOID:
diff --git a/libpoke/pvm-val.c b/libpoke/pvm-val.c
index 21c114e9..2d93720b 100644
--- a/libpoke/pvm-val.c
+++ b/libpoke/pvm-val.c
@@ -517,12 +517,13 @@ pvm_make_void_type (void)
 }
 
 pvm_val
-pvm_make_offset_type (pvm_val base_type, pvm_val unit)
+pvm_make_offset_type (pvm_val base_type, pvm_val unit, pvm_val ref_type)
 {
   pvm_val otype = pvm_make_type (PVM_TYPE_OFFSET);
 
   PVM_VAL_TYP_O_BASE_TYPE (otype) = base_type;
   PVM_VAL_TYP_O_UNIT (otype) = unit;
+  PVM_VAL_TYP_O_REF_TYPE (otype) = ref_type;
   return otype;
 }
 
diff --git a/libpoke/pvm-val.h b/libpoke/pvm-val.h
index 192a5741..b4cf1861 100644
--- a/libpoke/pvm-val.h
+++ b/libpoke/pvm-val.h
@@ -433,6 +433,7 @@ typedef struct pvm_struct *pvm_struct;
 #define PVM_VAL_TYP_S_FTYPE(V,I) (PVM_VAL_TYP_S_FTYPES((V))[(I)])
 #define PVM_VAL_TYP_O_UNIT(V) (PVM_VAL_TYP((V))->val.off.unit)
 #define PVM_VAL_TYP_O_BASE_TYPE(V) (PVM_VAL_TYP((V))->val.off.base_type)
+#define PVM_VAL_TYP_O_REF_TYPE(V) (PVM_VAL_TYP((V))->val.off.ref_type)
 #define PVM_VAL_TYP_C_RETURN_TYPE(V) (PVM_VAL_TYP((V))->val.cls.return_type)
 #define PVM_VAL_TYP_C_NARGS(V) (PVM_VAL_TYP((V))->val.cls.nargs)
 #define PVM_VAL_TYP_C_ATYPES(V) (PVM_VAL_TYP((V))->val.cls.atypes)
@@ -479,6 +480,7 @@ struct pvm_type
     {
       pvm_val base_type;
       pvm_val unit;
+      pvm_val ref_type;
     } off;
 
     struct
diff --git a/libpoke/pvm.h b/libpoke/pvm.h
index 44a0d11c..1c000d3b 100644
--- a/libpoke/pvm.h
+++ b/libpoke/pvm.h
@@ -303,7 +303,7 @@ pvm_val pvm_make_array_type (pvm_val type, pvm_val bound);
 pvm_val pvm_make_struct_type (pvm_val nfields, pvm_val name,
                               pvm_val *fnames, pvm_val *ftypes);
 
-pvm_val pvm_make_offset_type (pvm_val base_type, pvm_val unit);
+pvm_val pvm_make_offset_type (pvm_val base_type, pvm_val unit, pvm_val 
ref_type);
 pvm_val pvm_make_closure_type (pvm_val rtype, pvm_val nargs,
                                pvm_val *atypes);
 
diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
index d42b69bd..61d4ee16 100644
--- a/libpoke/pvm.jitter
+++ b/libpoke/pvm.jitter
@@ -1630,7 +1630,7 @@ instruction iosize ()
       {
         pvm_val magnitude = PVM_MAKE_ULONG (ios_size (io), 64);
         pvm_val type = pvm_make_offset_type (pvm_typeof (magnitude),
-                                             PVM_MAKE_ULONG (8, 64));
+                                             PVM_MAKE_ULONG (8, 64), PVM_NULL 
/* ref_type */);
         JITTER_PUSH_STACK (pvm_make_offset (PVM_MAKE_ULONG (ios_size (io), 
64), type));
       }
   end
@@ -1733,7 +1733,7 @@ instruction iogetb ()
       unit = PVM_MAKE_ULONG (1, 64);
     }
 
-    type = pvm_make_offset_type (pvm_typeof (magnitude), unit);
+    type = pvm_make_offset_type (pvm_typeof (magnitude), unit, PVM_NULL /* 
ref_type */);
     JITTER_PUSH_STACK (pvm_make_offset (magnitude, type));
   end
 end
@@ -5524,7 +5524,7 @@ end
 instruction mkoq ()
   code
    pvm_val type = pvm_make_offset_type (pvm_typeof (JITTER_UNDER_TOP_STACK ()),
-                                        JITTER_TOP_STACK ());
+                                        JITTER_TOP_STACK (), PVM_NULL /* 
ref_type */);
    pvm_val res = pvm_make_offset (JITTER_UNDER_TOP_STACK (), type);
    JITTER_DROP_STACK ();
    JITTER_TOP_STACK () = res;
@@ -6192,10 +6192,14 @@ end
 
 instruction mktyo ()
   code
-#define F(res, a, b) \
-  { res = pvm_make_offset_type (a, b); }
-    JITTER_BINARY_STACK(F);
-#undef F
+    pvm_val base_type, unit;
+
+    unit = JITTER_TOP_STACK ();
+    base_type = JITTER_UNDER_TOP_STACK ();
+    JITTER_DROP_STACK ();
+    JITTER_DROP_STACK ();
+    JITTER_PUSH_STACK (pvm_make_offset_type (base_type, unit,
+                                             PVM_NULL /* ref_type */));
   end
 end
 
@@ -6223,6 +6227,35 @@ instruction tyogetu ()
   end
 end
 
+# Instruction: tyogetrt
+#
+# Given an offset type, push the referred type to the stack.
+# This can be PVM_NULL if the offset type isn't a reference.
+#
+# Stack: ( OTYPE -- OTYPE TYPE )
+
+instruction tyogetrt ()
+  code
+    JITTER_PUSH_STACK (PVM_VAL_TYP_O_REF_TYPE (JITTER_TOP_STACK ()));
+  end
+end
+
+# Instruction: tyosetrt
+#
+# Given an offset type and a referred type, make the offset type
+# a referring type.  The referred type can be PVM_NULL.  In this
+# case the resulting offset type is not a referring offset type.
+#
+# Stack: ( OTYPE TYPE -- OTYPE )
+
+instruction tyosetrt ()
+  code
+    PVM_VAL_TYP_O_REF_TYPE (JITTER_UNDER_TOP_STACK ())
+      = JITTER_TOP_STACK ();
+    JITTER_DROP_STACK ();
+  end
+end
+
 # Instruction: mktya
 #
 # Given an elements type and a bounder closure, build an array type
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index a9c9a560..99d28d8d 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -706,6 +706,7 @@ EXTRA_DIST = \
   poke.pkl/add-offsets-9.pk \
   poke.pkl/add-offsets-diag-1.pk \
   poke.pkl/add-offsets-10.pk \
+  poke.pkl/add-offsets-11.pk \
   poke.pkl/add-strings-1.pk \
   poke.pkl/add-strings-diag-1.pk \
   poke.pkl/adda-int-1.pk \
@@ -1031,6 +1032,7 @@ EXTRA_DIST = \
   poke.pkl/bnot-integers-4.pk \
   poke.pkl/bnot-int-struct-1.pk \
   poke.pkl/bnot-offsets-1.pk \
+  poke.pkl/bnot-offsets-2.pk \
   poke.pkl/break-diag-1.pk \
   poke.pkl/break-for-1.pk \
   poke.pkl/break-while-1.pk \
@@ -1257,6 +1259,7 @@ EXTRA_DIST = \
   poke.pkl/div-offsets-2.pk \
   poke.pkl/div-offsets-3.pk \
   poke.pkl/div-offsets-4.pk \
+  poke.pkl/div-offsets-5.pk \
   poke.pkl/div-offsets-diag-1.pk \
   poke.pkl/div-offsets-diag-2.pk \
   poke.pkl/div-offsets-diag-3.pk \
@@ -1813,6 +1816,7 @@ EXTRA_DIST = \
   poke.pkl/mod-offsets-3.pk \
   poke.pkl/mod-offsets-4.pk \
   poke.pkl/mod-offsets-5.pk \
+  poke.pkl/mod-offsets-6.pk \
   poke.pkl/mod-offsets-diag-1.pk \
   poke.pkl/mod-offsets-diag-2.pk \
   poke.pkl/moda-int-1.pk \
@@ -1845,6 +1849,7 @@ EXTRA_DIST = \
   poke.pkl/mul-offsets-9.pk \
   poke.pkl/mul-offsets-10.pk \
   poke.pkl/mul-offsets-11.pk \
+  poke.pkl/mul-offsets-12.pk \
   poke.pkl/mul-strings-1.pk \
   poke.pkl/mul-strings-2.pk \
   poke.pkl/mul-strings-3.pk \
@@ -1913,6 +1918,7 @@ EXTRA_DIST = \
   poke.pkl/offset-arg-2.pk \
   poke.pkl/offset-diag-1.pk \
   poke.pkl/offset-type-1.pk \
+  poke.pkl/offset-type-2.pk \
   poke.pkl/offset-type-diag-1.pk \
   poke.pkl/offset-type-diag-2.pk \
   poke.pkl/offset-type-diag-3.pk \
@@ -2038,6 +2044,7 @@ EXTRA_DIST = \
   poke.pkl/print-any-1.pk \
   poke.pkl/print-any-2.pk \
   poke.pkl/print-any-3.pk \
+  poke.pkl/print-any-4.pk \
   poke.pkl/print-diag-1.pk \
   poke.pkl/preincr-field-1.pk \
   poke.pkl/preincr-diag-2.pk \
@@ -2535,6 +2542,7 @@ EXTRA_DIST = \
   poke.pkl/sub-offsets-6.pk \
   poke.pkl/sub-offsets-7.pk \
   poke.pkl/sub-offsets-8.pk \
+  poke.pkl/sub-offsets-9.pk \
   poke.pkl/suba-int-1.pk \
   poke.pkl/suba-offset-1.pk \
   poke.pkl/term-class-1.pk \
diff --git a/testsuite/poke.pkl/add-offsets-11.pk 
b/testsuite/poke.pkl/add-offsets-11.pk
new file mode 100644
index 00000000..714e08e5
--- /dev/null
+++ b/testsuite/poke.pkl/add-offsets-11.pk
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+
+/* The ref_type attribute of offset types must not be propagated
+   in add expressions.  */
+
+type Pointer_To_Exception = offset<int<32>,B,Exception>;
+var a = 1#B as Pointer_To_Exception;
+var b = 2*8#b as Pointer_To_Exception;
+
+/* { dg-command { asm any: ("typof; nip" : a + b) } } */
+/* { dg-output "offset<int<32>,8>" } */
+
+/* For constant folding: */
+/* { dg-command { asm any: ("typof; nip" : 1#B as Pointer_To_Exception + 2*8#b 
as Pointer_To_Exception) } } */
+/* { dg-output "\noffset<int<32>,8>" } */
diff --git a/testsuite/poke.pkl/bnot-offsets-2.pk 
b/testsuite/poke.pkl/bnot-offsets-2.pk
new file mode 100644
index 00000000..f1bb8eab
--- /dev/null
+++ b/testsuite/poke.pkl/bnot-offsets-2.pk
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+
+/* The ref_type attribute of offset types must not be propagated
+   in bnot expressions.  */
+
+type Pointer_To_Exception = offset<int<32>,B,Exception>;
+var a = 1#B as Pointer_To_Exception;
+
+/* { dg-command { asm any: ("typof; nip" : ~a) } } */
+/* { dg-output "offset<int<32>,8>" } */
+
+/* For constant folding: */
+/* { dg-command { asm any: ("typof; nip" : ~(1#B as Pointer_To_Exception)) } } 
*/
+/* { dg-output "\noffset<int<32>,8>" } */
diff --git a/testsuite/poke.pkl/div-offsets-5.pk 
b/testsuite/poke.pkl/div-offsets-5.pk
new file mode 100644
index 00000000..07bc9a82
--- /dev/null
+++ b/testsuite/poke.pkl/div-offsets-5.pk
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+
+/* The ref_type attribute of offset types must not be propagated
+   in div expressions.  */
+
+type Pointer_To_Exception = offset<int<32>,B,Exception>;
+var a = 1#B as Pointer_To_Exception;
+var b = 2;
+
+/* { dg-command { asm any: ("typof; nip" : a / b) } } */
+/* { dg-output "offset<int<32>,8>" } */
+
+/* For constant folding: */
+/* { dg-command { asm any: ("typof; nip" : 1#B as Pointer_To_Exception / 2) } 
} */
+/* { dg-output "\noffset<int<32>,8>" } */
diff --git a/testsuite/poke.pkl/mod-offsets-6.pk 
b/testsuite/poke.pkl/mod-offsets-6.pk
new file mode 100644
index 00000000..5715f799
--- /dev/null
+++ b/testsuite/poke.pkl/mod-offsets-6.pk
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+
+/* The ref_type attribute of offset types must not be propagated
+   in mod expressions.  */
+
+type Pointer_To_Exception = offset<int<32>,B,Exception>;
+var a = 1#B as Pointer_To_Exception;
+var b = 2#b;
+
+/* { dg-command { asm any: ("typof; nip" : a % b) } } */
+/* { dg-output "offset<int<32>,1>" } */
+
+/* For constant folding: */
+/* { dg-command { asm any: ("typof; nip" : 1#B as Pointer_To_Exception % 2#b) 
} } */
+/* { dg-output "\noffset<int<32>,1>" } */
diff --git a/testsuite/poke.pkl/mul-offsets-12.pk 
b/testsuite/poke.pkl/mul-offsets-12.pk
new file mode 100644
index 00000000..aba452ef
--- /dev/null
+++ b/testsuite/poke.pkl/mul-offsets-12.pk
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+
+/* The ref_type attribute of offset types must not be propagated
+   in mul expressions.  */
+
+type Pointer_To_Exception = offset<int<32>,B,Exception>;
+var a = 1#B as Pointer_To_Exception;
+var b = 2;
+
+/* { dg-command { asm any: ("typof; nip" : a * b) } } */
+/* { dg-output "offset<int<32>,8>" } */
+
+/* For constant folding: */
+/* { dg-command { asm any: ("typof; nip" : 1#B as Pointer_To_Exception * 2) } 
} */
+/* { dg-output "\noffset<int<32>,8>" } */
diff --git a/testsuite/poke.pkl/offset-type-2.pk 
b/testsuite/poke.pkl/offset-type-2.pk
new file mode 100644
index 00000000..e76f3e78
--- /dev/null
+++ b/testsuite/poke.pkl/offset-type-2.pk
@@ -0,0 +1,6 @@
+/* {dg-do run } */
+
+type Pointer_To_Exception = offset<int<32>,B,Exception>;
+
+/* { dg-command {23*8#b as Pointer_To_Exception} } */
+/* { dg-output {23#B} } */
diff --git a/testsuite/poke.pkl/print-any-4.pk 
b/testsuite/poke.pkl/print-any-4.pk
new file mode 100644
index 00000000..3a21c8aa
--- /dev/null
+++ b/testsuite/poke.pkl/print-any-4.pk
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+
+type Pointer_To_Exception = offset<int<32>,B,Exception>;
+var x = 23#B;
+
+/* { dg-command {asm any: ("typof; nip" : x as Pointer_To_Exception)} } */
+/* { dg-output "offset<int<32>,8,Exception>" } */
+
+/* For constant folding: */
+/* { dg-command {asm any: ("typof; nip" : 23#B as Pointer_To_Exception)} } */
+/* { dg-output "\noffset<int<32>,8,Exception>" } */
diff --git a/testsuite/poke.pkl/sub-offsets-9.pk 
b/testsuite/poke.pkl/sub-offsets-9.pk
new file mode 100644
index 00000000..f060ebd3
--- /dev/null
+++ b/testsuite/poke.pkl/sub-offsets-9.pk
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+
+/* The ref_type attribute of offset types must not be propagated
+   in sub expressions.  */
+
+type Pointer_To_Exception = offset<int<32>,B,Exception>;
+var a = 1#B as Pointer_To_Exception;
+var b = 2*8#b as Pointer_To_Exception;
+
+/* { dg-command { asm any: ("typof; nip" : a - b) } } */
+/* { dg-output "offset<int<32>,8>" } */
+
+/* For constant folding: */
+/* { dg-command { asm any: ("typof; nip" : 1#B as Pointer_To_Exception - 2*8#b 
as Pointer_To_Exception) } } */
+/* { dg-output "\noffset<int<32>,8>" } */
-- 
2.30.2




reply via email to

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