[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 3/5] pkl: Fix pkl_ast_{sizeof_type,is_complete}
From: |
Mohammad-Reza Nabipoor |
Subject: |
[PATCH 3/5] pkl: Fix pkl_ast_{sizeof_type,is_complete} |
Date: |
Sat, 22 Jan 2022 23:37:40 +0330 |
2022-01-22 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* libpoke/pkl-ast.h (pkl_ast_struct_type_field): Add `size` field.
(PKL_AST_STRUCT_TYPE_FIELD_SIZE): New accessor macro.
* libpoke/pkl-ast.c (pkl_ast_dup_type): Add support for `size`
field.
(pkl_ast_node_free): Likewise.
(pkl_ast_print_1): Likewise.
(pkl_ast_sizeof_type): Fix to the right thing for pinned structs,
arrays with offset bounds, structs with labels.
(pkl_ast_type_is_complete): Fix the logic for structs. Add support
for unions. Fix the logic for arrays to support offsets as bounds
as well as check for completeness of element type.
* libpoke/pkl-pass.c (pkl_do_pass_1): Add support for `size` field.
* libpoke/pkl-trans.c (pkl_trans2_ps_struct_type_field): New
phase to calculate the size of fields of struct if they are complete.
(struct pkl_phase_trans2): Register new phase.
---
ChangeLog | 18 +++++
libpoke/pkl-ast.c | 185 +++++++++++++++++++++++++++++++-------------
libpoke/pkl-ast.h | 4 +
libpoke/pkl-pass.c | 2 +
libpoke/pkl-trans.c | 17 ++++
5 files changed, 171 insertions(+), 55 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 6c540dda..b3c9f9bd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2022-01-22 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
+
+ * libpoke/pkl-ast.h (pkl_ast_struct_type_field): Add `size` field.
+ (PKL_AST_STRUCT_TYPE_FIELD_SIZE): New accessor macro.
+ * libpoke/pkl-ast.c (pkl_ast_dup_type): Add support for `size`
+ field.
+ (pkl_ast_node_free): Likewise.
+ (pkl_ast_print_1): Likewise.
+ (pkl_ast_sizeof_type): Fix to the right thing for pinned structs,
+ arrays with offset bounds, structs with labels.
+ (pkl_ast_type_is_complete): Fix the logic for structs. Add support
+ for unions. Fix the logic for arrays to support offsets as bounds
+ as well as check for completeness of element type.
+ * libpoke/pkl-pass.c (pkl_do_pass_1): Add support for `size` field.
+ * libpoke/pkl-trans.c (pkl_trans2_ps_struct_type_field): New
+ phase to calculate the size of fields of struct if they are complete.
+ (struct pkl_phase_trans2): Register new phase.
+
2022-01-22 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* libpoke/pkl-ast.c (pkl_ast_make_offset): An offset value
diff --git a/libpoke/pkl-ast.c b/libpoke/pkl-ast.c
index 0bb9389f..41097826 100644
--- a/libpoke/pkl-ast.c
+++ b/libpoke/pkl-ast.c
@@ -591,6 +591,7 @@ pkl_ast_dup_type (pkl_ast_node type)
{
pkl_ast_node struct_type_elem_name;
pkl_ast_node struct_type_elem_type;
+ pkl_ast_node struct_type_elem_size;
pkl_ast_node struct_type_elem_constraint;
pkl_ast_node struct_type_elem_initializer;
pkl_ast_node struct_type_elem_label;
@@ -606,6 +607,7 @@ pkl_ast_dup_type (pkl_ast_node type)
struct_type_elem_name = PKL_AST_STRUCT_TYPE_FIELD_NAME (t);
struct_type_elem_type = PKL_AST_STRUCT_TYPE_FIELD_TYPE (t);
+ struct_type_elem_size = PKL_AST_STRUCT_TYPE_FIELD_SIZE (t);
struct_type_elem_constraint = PKL_AST_STRUCT_TYPE_FIELD_CONSTRAINT
(t);
struct_type_elem_initializer = PKL_AST_STRUCT_TYPE_FIELD_INITIALIZER
(t);
struct_type_elem_label = PKL_AST_STRUCT_TYPE_FIELD_LABEL (t);
@@ -627,6 +629,8 @@ pkl_ast_dup_type (pkl_ast_node type)
struct_type_elem_endian,
struct_type_elem_optcond);
+ PKL_AST_STRUCT_TYPE_FIELD_SIZE (struct_type_elem)
+ = ASTREF (struct_type_elem_size);
PKL_AST_TYPE_S_ELEMS (new)
= pkl_ast_chainon (PKL_AST_TYPE_S_ELEMS (new),
struct_type_elem);
@@ -1024,12 +1028,27 @@ pkl_ast_sizeof_type (pkl_ast ast, pkl_ast_node type)
}
case PKL_TYPE_ARRAY:
{
+ pkl_ast_node bound = PKL_AST_TYPE_A_BOUND (type);
+ pkl_ast_node bound_type = PKL_AST_TYPE (bound);
pkl_ast_node sizeof_etype
= pkl_ast_sizeof_type (ast,
PKL_AST_TYPE_A_ETYPE (type));
- res= pkl_ast_make_binary_exp (ast, PKL_AST_OP_MUL,
- PKL_AST_TYPE_A_BOUND (type),
- sizeof_etype);
+
+ if (PKL_AST_TYPE_CODE (bound_type) == PKL_TYPE_INTEGRAL)
+ res = pkl_ast_make_binary_exp (ast, PKL_AST_OP_MUL,
+ bound, sizeof_etype);
+ else if (PKL_AST_TYPE_CODE (bound_type) == PKL_TYPE_OFFSET)
+ {
+ pkl_ast_node mag, unit;
+
+ mag = PKL_AST_OFFSET_MAGNITUDE (bound);
+ unit = PKL_AST_OFFSET_UNIT (bound);
+ res = pkl_ast_make_integer (ast,
+ PKL_AST_INTEGER_VALUE (mag)
+ * PKL_AST_INTEGER_VALUE (unit));
+ }
+ else
+ assert (0);
PKL_AST_TYPE (res) = ASTREF (res_type);
break;
}
@@ -1042,51 +1061,73 @@ pkl_ast_sizeof_type (pkl_ast ast, pkl_ast_node type)
for (t = PKL_AST_TYPE_S_ELEMS (type); t; t = PKL_AST_CHAIN (t))
{
- if (PKL_AST_CODE (t) == PKL_AST_STRUCT_TYPE_FIELD)
+ pkl_ast_node field_label;
+ pkl_ast_node elem_type_size;
+
+ if (PKL_AST_CODE (t) != PKL_AST_STRUCT_TYPE_FIELD)
+ continue;
+
+ field_label = PKL_AST_STRUCT_TYPE_FIELD_LABEL (t);
+ elem_type_size = PKL_AST_STRUCT_TYPE_FIELD_SIZE (t);
+
+ assert (elem_type_size != NULL);
+
+ /* Struct fields with non-constant labels are not
+ expected, as these cannot appear in complete struct
+ types. Ditto for optional fields. */
+ assert (field_label == NULL
+ || PKL_AST_CODE (field_label) == PKL_AST_OFFSET);
+ assert (PKL_AST_STRUCT_TYPE_FIELD_OPTCOND (t) == NULL);
+
+ /* If struct is pinned, the new size is
+ `max (size, elem_type_size)`.
+ Otherwise if the field has a constant label, the new size
+ is `max (size, label_in_bits + elem_type_size)'.
+ Otherwise, it is `size + elem_type_size'. */
+ if (PKL_AST_TYPE_S_PINNED_P (type))
{
- pkl_ast_node elem_type;
- pkl_ast_node field_label = PKL_AST_STRUCT_TYPE_FIELD_LABEL (t);
-
- /* Struct fields with non-constant labels are not
- expected, as these cannot appear in complete struct
- types. Ditto for optional fields. */
- assert (field_label == NULL
- || PKL_AST_CODE (field_label) == PKL_AST_OFFSET);
- assert (PKL_AST_STRUCT_TYPE_FIELD_OPTCOND (t) == NULL);
-
- /* If the field has a constant label and the label is
- bigger than the current accumulated size, replace
- the accumulated size with the label. */
- if (field_label)
- {
- pkl_ast_node label_magnitude, label_in_bits, cond;
-
- label_magnitude
- = pkl_ast_make_cast (ast, res_type,
- PKL_AST_OFFSET_MAGNITUDE
(field_label));
- PKL_AST_TYPE (label_magnitude) = ASTREF (res_type);
+ pkl_ast_node cond;
- label_in_bits = pkl_ast_make_binary_exp (ast,
- PKL_AST_OP_MUL,
- label_magnitude,
-
PKL_AST_OFFSET_UNIT (field_label));
- PKL_AST_TYPE (label_in_bits) = ASTREF (res_type);
+ cond = pkl_ast_make_binary_exp (ast, PKL_AST_OP_GT,
+ elem_type_size, res);
+ PKL_AST_TYPE (cond) = ASTREF (res_type);
- cond = pkl_ast_make_binary_exp (ast, PKL_AST_OP_GT,
- label_in_bits, res);
- PKL_AST_TYPE (cond) = ASTREF (res_type);
-
- res = pkl_ast_make_cond_exp (ast, cond, label_in_bits,
res);
- PKL_AST_TYPE (res) = ASTREF (res_type);
- }
-
- /* Add the size of the field to the accumulated
- size. */
- elem_type = PKL_AST_STRUCT_TYPE_FIELD_TYPE (t);
+ res = pkl_ast_make_cond_exp (ast, cond, elem_type_size, res);
+ PKL_AST_TYPE (res) = ASTREF (res_type);
+ }
+ else if (field_label)
+ {
+ pkl_ast_node label_magnitude, label_in_bits, cond;
+ pkl_ast_node off_in_bits;
+
+ label_magnitude
+ = pkl_ast_make_cast (ast, res_type,
+ PKL_AST_OFFSET_MAGNITUDE (field_label));
+ PKL_AST_TYPE (label_magnitude) = ASTREF (res_type);
+
+ label_in_bits
+ = pkl_ast_make_binary_exp (ast, PKL_AST_OP_MUL,
+ label_magnitude,
+ PKL_AST_OFFSET_UNIT
(field_label));
+ PKL_AST_TYPE (label_in_bits) = ASTREF (res_type);
+
+ off_in_bits = pkl_ast_make_binary_exp (ast, PKL_AST_OP_ADD,
+ label_in_bits,
+ elem_type_size);
+ PKL_AST_TYPE (off_in_bits) = ASTREF (res_type);
+
+ cond = pkl_ast_make_binary_exp (ast, PKL_AST_OP_GT,
+ res, off_in_bits);
+ PKL_AST_TYPE (cond) = ASTREF (res_type);
+
+ res = pkl_ast_make_cond_exp (ast, cond, res, off_in_bits);
+ PKL_AST_TYPE (res) = ASTREF (res_type);
+ }
+ else
+ {
+ /* Add the size of the field to the accumulated size. */
res = pkl_ast_make_binary_exp (ast, PKL_AST_OP_ADD,
- res,
- pkl_ast_sizeof_type (ast,
-
elem_type));
+ res, elem_type_size);
PKL_AST_TYPE (res) = ASTREF (res_type);
}
}
@@ -1210,23 +1251,54 @@ pkl_ast_type_is_complete (pkl_ast_node type)
elem;
elem = PKL_AST_CHAIN (elem))
{
- pkl_ast_node elem_label
- = PKL_AST_STRUCT_TYPE_FIELD_LABEL (elem);
-
- if (PKL_AST_CODE (elem) == PKL_AST_STRUCT_TYPE_FIELD
- && ((elem_label && PKL_AST_CODE (elem_label) != PKL_AST_OFFSET)
- || PKL_AST_STRUCT_TYPE_FIELD_OPTCOND (elem)
- || (pkl_ast_type_is_complete
(PKL_AST_STRUCT_TYPE_FIELD_TYPE (elem))
- == PKL_AST_TYPE_COMPLETE_NO)))
+ pkl_ast_node elem_label;
+ pkl_ast_node elem_type;
+
+ if (PKL_AST_CODE (elem) != PKL_AST_STRUCT_TYPE_FIELD)
+ continue;
+
+ elem_label = PKL_AST_STRUCT_TYPE_FIELD_LABEL (elem);
+ elem_type = PKL_AST_STRUCT_TYPE_FIELD_TYPE (elem);
+ if ((elem_label && PKL_AST_CODE (elem_label) != PKL_AST_OFFSET)
+ || PKL_AST_STRUCT_TYPE_FIELD_OPTCOND (elem)
+ || (pkl_ast_type_is_complete (elem_type)
+ == PKL_AST_TYPE_COMPLETE_NO))
{
complete = PKL_AST_TYPE_COMPLETE_NO;
break;
}
}
+ /* This is a union type with complete fields. This type is
+ complete if all fields have the same size. */
+ if (complete == PKL_AST_TYPE_COMPLETE_YES && PKL_AST_TYPE_S_UNION_P
(type))
+ {
+ pkl_ast_node size_node;
+ size_t size = -1;
+
+ for (elem = PKL_AST_TYPE_S_ELEMS (type);
+ elem;
+ elem = PKL_AST_CHAIN (elem))
+ {
+ if (PKL_AST_CODE (elem) != PKL_AST_STRUCT_TYPE_FIELD)
+ continue;
+
+ size_node = PKL_AST_STRUCT_TYPE_FIELD_SIZE (elem);
+ assert (size_node);
+ assert (PKL_AST_TYPE_CODE (size_node) == PKL_TYPE_INTEGRAL);
+ if (size == -1)
+ size = PKL_AST_INTEGER_VALUE (size_node);
+ else if (PKL_AST_INTEGER_VALUE (size_node) != size)
+ {
+ complete = PKL_AST_TYPE_COMPLETE_NO;
+ break;
+ }
+ }
+ }
break;
}
/* Array types are complete if the number of elements in the
- array are specified and it is a literal expression. */
+ array are specified and it is a literal expression; and type
+ of elements is also complete. */
case PKL_TYPE_ARRAY:
{
pkl_ast_node bound = PKL_AST_TYPE_A_BOUND (type);
@@ -1239,9 +1311,10 @@ pkl_ast_type_is_complete (pkl_ast_node type)
calculated at this point. */
assert (bound_type);
- if (PKL_AST_TYPE_CODE (bound_type) == PKL_TYPE_INTEGRAL
+ if ((PKL_AST_TYPE_CODE (bound_type) == PKL_TYPE_INTEGRAL
+ || PKL_AST_TYPE_CODE (bound_type) == PKL_TYPE_OFFSET)
&& PKL_AST_LITERAL_P (bound))
- complete = PKL_AST_TYPE_COMPLETE_YES;
+ complete = pkl_ast_type_is_complete (PKL_AST_TYPE_A_ETYPE
(type));
else
complete = PKL_AST_TYPE_COMPLETE_NO;
}
@@ -2144,6 +2217,7 @@ pkl_ast_node_free (pkl_ast_node ast)
pkl_ast_node_free (PKL_AST_STRUCT_TYPE_FIELD_NAME (ast));
pkl_ast_node_free (PKL_AST_STRUCT_TYPE_FIELD_TYPE (ast));
+ pkl_ast_node_free (PKL_AST_STRUCT_TYPE_FIELD_SIZE (ast));
pkl_ast_node_free (PKL_AST_STRUCT_TYPE_FIELD_CONSTRAINT (ast));
pkl_ast_node_free (PKL_AST_STRUCT_TYPE_FIELD_INITIALIZER (ast));
pkl_ast_node_free (PKL_AST_STRUCT_TYPE_FIELD_LABEL (ast));
@@ -3004,6 +3078,7 @@ pkl_ast_print_1 (FILE *fp, pkl_ast_node ast, int indent)
PRINT_COMMON_FIELDS;
PRINT_AST_SUBAST (name, STRUCT_TYPE_FIELD_NAME);
PRINT_AST_SUBAST (type, STRUCT_TYPE_FIELD_TYPE);
+ PRINT_AST_SUBAST (type, STRUCT_TYPE_FIELD_SIZE);
PRINT_AST_SUBAST (exp, STRUCT_TYPE_FIELD_CONSTRAINT);
PRINT_AST_SUBAST (exp, STRUCT_TYPE_FIELD_INITIALIZER);
PRINT_AST_SUBAST (exp, STRUCT_TYPE_FIELD_LABEL);
diff --git a/libpoke/pkl-ast.h b/libpoke/pkl-ast.h
index b1e4ecea..be28ba49 100644
--- a/libpoke/pkl-ast.h
+++ b/libpoke/pkl-ast.h
@@ -753,6 +753,8 @@ pkl_ast_node pkl_ast_make_struct_ref (pkl_ast ast,
TYPE is a PKL_AST_TYPE node.
+ SIZE is the size of TYPE if it is a complete type, or NULL.
+
CONSTRAINT is a constraint associated with the struct field. It is
an expression that should evaluate to a boolean.
@@ -773,6 +775,7 @@ pkl_ast_node pkl_ast_make_struct_ref (pkl_ast ast,
#define PKL_AST_STRUCT_TYPE_FIELD_NAME(AST) ((AST)->sct_type_elem.name)
#define PKL_AST_STRUCT_TYPE_FIELD_TYPE(AST) ((AST)->sct_type_elem.type)
+#define PKL_AST_STRUCT_TYPE_FIELD_SIZE(AST) ((AST)->sct_type_elem.size)
#define PKL_AST_STRUCT_TYPE_FIELD_CONSTRAINT(AST)
((AST)->sct_type_elem.constraint)
#define PKL_AST_STRUCT_TYPE_FIELD_LABEL(AST) ((AST)->sct_type_elem.label)
#define PKL_AST_STRUCT_TYPE_FIELD_ENDIAN(AST) ((AST)->sct_type_elem.endian)
@@ -785,6 +788,7 @@ struct pkl_ast_struct_type_field
union pkl_ast_node *name;
union pkl_ast_node *type;
+ union pkl_ast_node *size;
union pkl_ast_node *constraint;
union pkl_ast_node *initializer;
union pkl_ast_node *label;
diff --git a/libpoke/pkl-pass.c b/libpoke/pkl-pass.c
index fc24d1b5..98439bae 100644
--- a/libpoke/pkl-pass.c
+++ b/libpoke/pkl-pass.c
@@ -471,6 +471,8 @@ pkl_do_pass_1 (pkl_compiler compiler,
if (PKL_AST_STRUCT_TYPE_FIELD_NAME (node))
PKL_PASS (PKL_AST_STRUCT_TYPE_FIELD_NAME (node));
PKL_PASS (PKL_AST_STRUCT_TYPE_FIELD_TYPE (node));
+ if (PKL_AST_STRUCT_TYPE_FIELD_SIZE (node))
+ PKL_PASS (PKL_AST_STRUCT_TYPE_FIELD_SIZE (node));
if (PKL_AST_STRUCT_TYPE_FIELD_CONSTRAINT (node))
PKL_PASS (PKL_AST_STRUCT_TYPE_FIELD_CONSTRAINT (node));
if (PKL_AST_STRUCT_TYPE_FIELD_INITIALIZER (node))
diff --git a/libpoke/pkl-trans.c b/libpoke/pkl-trans.c
index edcd697e..f235a0af 100644
--- a/libpoke/pkl-trans.c
+++ b/libpoke/pkl-trans.c
@@ -1419,6 +1419,22 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans2_ps_incrdecr)
}
PKL_PHASE_END_HANDLER
+/* Calculate the size of struct type fields that are complete. */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_trans2_ps_struct_type_field)
+{
+ pkl_ast_node field = PKL_PASS_NODE;
+ pkl_ast_node field_type = PKL_AST_STRUCT_TYPE_FIELD_TYPE (field);
+
+ if (pkl_ast_type_is_complete (field_type) == PKL_AST_TYPE_COMPLETE_YES)
+ {
+ PKL_AST_STRUCT_TYPE_FIELD_SIZE (field)
+ = ASTREF (pkl_ast_sizeof_type (PKL_PASS_AST, field_type));
+ PKL_PASS_RESTART = 1;
+ }
+}
+PKL_PHASE_END_HANDLER
+
struct pkl_phase pkl_phase_trans2 =
{
PKL_PHASE_PS_HANDLER (PKL_AST_SRC, pkl_trans_ps_src),
@@ -1433,6 +1449,7 @@ struct pkl_phase pkl_phase_trans2 =
PKL_PHASE_PS_HANDLER (PKL_AST_CAST, pkl_trans2_ps_cast),
PKL_PHASE_PS_HANDLER (PKL_AST_INCRDECR, pkl_trans2_ps_incrdecr),
PKL_PHASE_PS_TYPE_HANDLER (PKL_TYPE_OFFSET, pkl_trans2_ps_type_offset),
+ PKL_PHASE_PS_HANDLER (PKL_AST_STRUCT_TYPE_FIELD,
pkl_trans2_ps_struct_type_field),
};
--
2.34.1
[PATCH 4/5] pkl: Add folding for array add operation, Mohammad-Reza Nabipoor, 2022/01/22
[PATCH 5/5] pkl: Compute attributes at compile-time whenever possible, Mohammad-Reza Nabipoor, 2022/01/22