[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 0/2] Add support for integral unions
From: |
Mohammad-Reza Nabipoor |
Subject: |
[PATCH v2 0/2] Add support for integral unions |
Date: |
Mon, 26 Sep 2022 02:49:23 +0330 |
Hi Jose.
I fixed the bug in struct_constructor and struct_deintegrator.
And also fixed your comments.
This is the changes from the previous version:
diff --git a/ChangeLog b/ChangeLog
index 7fd4baa4..a8fd753a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,9 @@
-2022-09-24 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
+2022-09-26 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* libpoke/pkl-tab.y (tokens): s/token/%token/.
- * libpoke/pkl-typify.c (pkl_typify1_ps_type_struct): Handle integral
unions.
+ * libpoke/pkl-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,
@@ -68,6 +70,13 @@
* 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
+ items that are already on the stack because `raise' will restore
+ the height of stack and the caller will see garbage on the stack.
+ (function struct_deintegrator): Likewise.
+
2022-09-24 Jose E. Marchesi <jemarch@gnu.org>
BZ 27481
diff --git a/libpoke/pkl-gen.pks b/libpoke/pkl-gen.pks
index ccb8694f..f1e0c8a0 100644
--- a/libpoke/pkl-gen.pks
+++ b/libpoke/pkl-gen.pks
@@ -1436,6 +1436,7 @@
.function struct_constructor @type_struct
prolog
pushf 5
+ dup ; SCT SCT
regvar $sct ; SCT
;; Initialize $nfield to 0UL
push ulong<64>0
@@ -1452,8 +1453,10 @@
push ulong<64>1
mko
regvar $OFFSET
- ;; The struct is not mapped, so set its bit-offset to 0UL.
- push ulong<64>0 ; 0UL
+ ;; This is the offset of struct (used in mksct instruction at
+ ;; the end of this function), and because the struct is
+ ;; not mapped, set its bit-offset to 0UL.
+ push ulong<64>0 ; SCT 0UL
;; Iterate over the fields of the struct type.
.c size_t vars_registered = 0;
.let @field
@@ -1737,8 +1740,9 @@
.c PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_TYPE);
.c PKL_PASS_SUBPASS (@type_struct);
.c PKL_GEN_POP_CONTEXT;
- ; null [OFF STR VAL]... NMETHOD NFIELD TYP
- mksct ; SCT
+ ; SCT 0UL [OFF STR VAL]... NMETHOD NFIELD TYP
+ mksct ; SCT SCT
+ nip ; SCT
popf 1
return
.end
@@ -2060,7 +2064,6 @@
;;; passed in the stack.
.function struct_integrator @type_struct
- .c assert (!PKL_AST_TYPE_S_UNION_P (@type_struct));
prolog
pushf 2
regvar $sct ; Argument
@@ -2117,7 +2120,6 @@
;;; passed in the stack.
.function union_integrator @type_struct
- .c assert (PKL_AST_TYPE_S_UNION_P (@type_struct));
prolog
pushf 0
.let @itype = PKL_AST_TYPE_S_ITYPE (@type_struct)
@@ -2140,6 +2142,11 @@
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
@@ -2158,10 +2165,6 @@
.c PKL_GEN_POP_CONTEXT;
.let @field_itype = PKL_AST_TYPE_S_ITYPE (@field_type)
nton @field_itype, @itype ; SCT IVAL
- .c }
- .c else
- .c {
- .c assert (0 && "unreachable reached!");
.c }
; VAL IVAL
nip ; IVAL
@@ -2239,7 +2242,6 @@
;;; which convert the integer.
.function struct_deintegrator @type_struct
- .c assert (!PKL_AST_TYPE_S_UNION_P (@type_struct));
prolog
pushf 2
;; Convert the value to deintegrate to an ulong<64> to ease
@@ -2247,9 +2249,15 @@
.let @itype = PKL_AST_TYPE_S_ITYPE (@type_struct)
.let @uint64_type = pkl_ast_make_integral_type (PKL_PASS_AST, 64, 0)
.e zero_extend_64 @itype
- regvar $ival
+ ;; If constraint violation exception happens during the
+ ;; construction of deintegrated struct, this is the right
+ ;; place to restore the stack.
+ push PVM_E_CONSTRAINT
+ pushe .constraint_failed
+ dup ; IVAL IVAL
+ regvar $ival ; IVAL
;; This is the offset argument to the mksct instruction below.
- push ulong<64>0 ; OFF
+ push ulong<64>0 ; IVAL OFF
;; Iterate over the struct named fields creating triplets for the
;; fields, whose value is extracted from IVAL. We know that
;; IVAL has the same width than the struct fields all combined.
@@ -2280,30 +2288,32 @@
.c }
.let #bit_offset = pvm_make_int (bit_offset, 32)
;; Extract the value for this field from IVAL
- pushvar $ival ; IVAL
+ pushvar $ival ; IVAL IVAL
.e deint_extract_field_value @uint64_type, @itype, @field_type,
#bit_offset
;; Create the triplet with the converted value.
.let #field_name = pvm_make_string (PKL_AST_IDENTIFIER_POINTER
(@type_field_name))
.let #field_offset = pvm_make_ulong (bit_offset, 64)
- push #field_offset ; CVAL OFFSET
- push #field_name ; CVAL OFFSET NAME
- rot ; OFFSET NAME CVAL
+ push #field_offset ; IVAL CVAL OFFSET
+ push #field_name ; IVAL CVAL OFFSET NAME
+ rot ; IVAL OFFSET NAME CVAL
.c bit_offset += field_type_size;
.c i++;
.c }
- ; OFF [TRIPLETS...]
+ ; IVAL OFF [TRIPLETS...]
.let #nfields = pvm_make_ulong (i, 64)
- push ulong<64>0 ; OFF [TRIPLETS...] NMETHODS
- push #nfields ; OFF [TRIPLETS...] NMETHODS NFIELDS
+ push ulong<64>0 ; IVAL OFF [TRIPLETS...] NMETHODS
+ push #nfields ; IVAL OFF [TRIPLETS...] NMETHODS NFIELDS
.c PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_TYPE);
.c PKL_PASS_SUBPASS (@type_struct);
.c PKL_GEN_POP_CONTEXT;
- ; OFF [TRIPLETS...] NMETHODS NFIELDS TYPE
+ ; IVAL OFF [TRIPLETS...] NMETHODS NFIELDS TYPE
mksct
.c PKL_GEN_PUSH_SET_CONTEXT (PKL_GEN_CTX_IN_CONSTRUCTOR);
.c PKL_PASS_SUBPASS (@type_struct);
.c PKL_GEN_POP_CONTEXT;
- ; SCT
+ ; IVAL SCT
+ pope
+ nip ; SCT
;; At this point the anonymous fields in the struct created above are
;; all zero. This is because we coudln't include them in the argument
;; to the struct constructor. So now we have to iterate over the
@@ -2342,6 +2352,8 @@
.c }
popf 1
return
+.constraint_failed:
+ raise
.end
;;; RAS_FUNCTION_UNION_DEINTEGRATOR @type_struct
@@ -2358,7 +2370,6 @@
;;; which convert the integer.
.function union_deintegrator @type_struct
- .c assert (PKL_AST_TYPE_S_UNION_P (@type_struct));
prolog
pushf 0
.let @itype = PKL_AST_TYPE_S_ITYPE (@type_struct)
@@ -2368,14 +2379,13 @@
.c @field = PKL_AST_CHAIN (@field))
.c {
.label .alternative_failed
- .label .construction_failed
- .label .deintegration_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
+ dup ; IVAL IVAL
.c if (PKL_AST_TYPE_CODE (@field_type) == PKL_TYPE_INTEGRAL)
.c {
; IVAL NUM
@@ -2395,8 +2405,9 @@
.c }
.c else if (PKL_AST_TYPE_CODE (@field_type) == PKL_TYPE_STRUCT)
.c {
- push PVM_E_GENERIC
- pushe .deintegration_failed
+ ; 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;
@@ -2427,26 +2438,16 @@
push null ; ... OFF OFF STR VAL NMETH NFIELD STR TYP
NFIELD SNAME
mktysct ; ... OFF OFF STR VAL NMETH NFIELD TYP
mksct ; IVAL SCT
- push PVM_E_GENERIC
- pushe .construction_failed
+ 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
-.deintegration_failed:
- ;; HACK
- ;; struct_deintegrator leaves two items on stack (0UL and EXC),
- ;; instead of one item (EXC).
- drop
- ba .alternative_failed
-.construction_failed:
- ;; HACK
- ;; struct_constructor leaves two items on stack (0UL and EXC),
- ;; instead of one item (EXC).
- drop
+.constraint_failed:
+ nip ; IVAL EXC
.alternative_failed:
- ; IVAL EXC
drop ; IVAL
.c }
; IVAL
diff --git a/libpoke/pkl-typify.c b/libpoke/pkl-typify.c
index 6fe8bfa6..516255d2 100644
--- a/libpoke/pkl-typify.c
+++ b/libpoke/pkl-typify.c
@@ -1,4 +1,4 @@
-/* pkl-typify.c - Type handling phases for the poke compiler. */
+/* Pkl-typify.c - Type handling phases for the poke compiler. */
/* Copyright (C) 2019, 2020, 2021, 2022 Jose E. Marchesi */
@@ -477,8 +477,9 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_cast)
INVALID_CAST ("invalid cast to string");
break;
case PKL_TYPE_STRUCT:
- /* We are not supporting casts to unions yet. */
- if (PKL_AST_TYPE_S_UNION_P (to_type))
+ /* We are not supporting casts to non-integral unions yet. */
+ if (PKL_AST_TYPE_S_UNION_P (to_type)
+ && !PKL_AST_TYPE_S_ITYPE (to_type))
INVALID_CAST ("invalid cast to union");
/* Only structs can be casted to regular structs. Integral
@@ -1688,19 +1689,19 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_type_integral)
}
PKL_PHASE_END_HANDLER
-/* The type associated with an integral struct shall be integral.
+/* The type associated with an integral struct/union shall be integral.
- The fields in an integral struct type shall be all of integral or
+ The fields in an integral struct/union type shall be all of integral or
offset types (including other integral structs) and the total int
size shall match the sum of the sizes of all the fields.
- The total size declared in the integral struct should exactly match
+ The total size declared in the integral struct/union should exactly match
the size of all the contained fields.
Pinned unions are not allowed.
- Labels are not allowed in integral structs, pinned structs and unions.
- Optional fields are not allowed in integral structs.
+ Labels are not allowed in integral structs/unions, pinned structs and
+ unions. Optional fields are not allowed in integral structs/unions.
Computed fields should have getter and setter methods defined for
them, and they should handle values of the right type. */
Regards,
Mohammad-Reza
[PATCH v2 1/2] pkl: codegen: make struct_{constructor, deintegrator} exception-safe, Mohammad-Reza Nabipoor, 2022/09/25