codegen: gen_io: fix double-free of ctx->var_aux if
[ajla.git] / type.h
blobc99aa688002bcf89b519b371bbea272b9f5e5700
1 /*
2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
9 * version.
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #ifndef AJLA_TYPE_H
20 #define AJLA_TYPE_H
22 #include "list.h"
24 typedef unsigned char flat_size_t;
25 typedef uchar_efficient_t type_tag_t;
28 #define TYPE_TAG_fixed 0
29 #define TYPE_TAG_integer (TYPE_TAG_fixed + 2 * TYPE_FIXED_N)
30 #define TYPE_TAG_real (TYPE_TAG_integer + TYPE_INT_N)
31 #define TYPE_TAG_val (TYPE_TAG_real + TYPE_REAL_N)
33 #define TYPE_TAG_flat_option (TYPE_TAG_val + 0)
34 #define TYPE_TAG_builtin_N (TYPE_TAG_val + 1)
35 #define TYPE_TAG_unknown (TYPE_TAG_val + 1)
36 #define TYPE_TAG_record (TYPE_TAG_val + 2)
37 #define TYPE_TAG_flat_record (TYPE_TAG_val + 3)
38 #define TYPE_TAG_flat_array (TYPE_TAG_val + 4)
39 #define TYPE_TAG_N (TYPE_TAG_val + 5)
41 #define TYPE_TAG_VALIDATE(x) ajla_assert((unsigned)(x) < TYPE_TAG_N, (file_line, "invalid type"))
43 #define TYPE_TAG_fixed_signed 0
44 #define TYPE_TAG_fixed_unsigned 1
46 #define TYPE_TAG_IS_FIXED(x) (TYPE_TAG_VALIDATE(x), /*(x) >= TYPE_TAG_fixed &&*/ (x) < TYPE_TAG_fixed + 2 * TYPE_FIXED_N)
47 #define TYPE_TAG_IS_INT(x) (TYPE_TAG_VALIDATE(x), (x) >= TYPE_TAG_integer && (x) < TYPE_TAG_integer + TYPE_INT_N)
48 #define TYPE_TAG_IS_REAL(x) (TYPE_TAG_VALIDATE(x), (x) >= TYPE_TAG_real && (x) < TYPE_TAG_real + TYPE_REAL_N)
49 #define TYPE_TAG_FIXED_IS_UNSIGNED(x) ((((x) - TYPE_TAG_fixed) & 1) == TYPE_TAG_fixed_unsigned)
50 #define TYPE_TAG_IDX_FIXED(x) ((x) - TYPE_TAG_fixed)
51 #define TYPE_TAG_IDX_INT(x) ((x) - TYPE_TAG_integer)
52 #define TYPE_TAG_IDX_REAL(x) ((x) - TYPE_TAG_real)
53 #define TYPE_TAG_IS_BUILTIN(x) (TYPE_TAG_IS_FIXED(x) || TYPE_TAG_IS_REAL(x) || TYPE_TAG_IS_INT(x) || (x) == TYPE_TAG_flat_option)
54 #define TYPE_TAG_IS_FLAT(x) (TYPE_TAG_IS_BUILTIN(x) || (x) == TYPE_TAG_flat_record || (x) == TYPE_TAG_flat_array)
55 #define TYPE_IS_FLAT(t) (TYPE_TAG_IS_FLAT((t)->tag))
57 /* this limits recursion depth in flat_to_data */
58 #define TYPE_MAX_DEPTH 7
60 struct type {
61 type_tag_t tag;
62 unsigned char depth;
63 bool extra_compare;
64 flat_size_t size;
65 flat_size_t align;
68 static inline bool type_is_equal(const struct type *t1, const struct type *t2)
70 return t1 == t2 || (
71 t1->tag == t2->tag &&
72 t1->size == t2->size &&
73 t1->align == t2->align);
76 #define type_def(t, def) (ajla_assert_lo((t)->tag == cat(TYPE_TAG_,def), (file_line, "type_def: invalid type tag %u, expected %u", (t)->tag, cat(TYPE_TAG_,def))), get_struct(t, struct cat(def,_definition), type))
78 const struct type *type_get_fixed(unsigned bits, bool uns);
79 const struct type *type_get_int(unsigned idx);
80 const struct type *type_get_real(unsigned idx);
81 const struct type *type_get_flat_option(void);
82 const struct type *type_get_unknown(void);
83 const struct type *type_get_from_tag(type_tag_t tag);
86 struct record_definition {
87 struct type type;
88 frame_t n_slots;
89 frame_t alignment;
90 arg_t n_entries;
91 struct list entry;
92 const frame_t *idx_to_frame; /* indexed by idx */
93 const struct type *types[FLEXIBLE_ARRAY]; /* indexed by slot */
96 struct record_definition *type_alloc_record_definition(frame_t size, ajla_error_t *mayfail);
98 static inline bool record_definition_is_elided(const struct record_definition *def, arg_t idx)
100 ajla_assert(idx < def->n_entries, (file_line, "record_definition_is_elided: too high index: %"PRIuMAX" >= %"PRIuMAX"", (uintmax_t)idx, (uintmax_t)def->n_entries));
101 return def->idx_to_frame[idx] == NO_FRAME_T;
104 static inline frame_t record_definition_slot(const struct record_definition *def, arg_t idx)
106 frame_t slot;
107 ajla_assert(idx < def->n_entries, (file_line, "record_definition_slot: too high index: %"PRIuMAX" >= %"PRIuMAX"", (uintmax_t)idx, (uintmax_t)def->n_entries));
108 slot = def->idx_to_frame[idx];
109 ajla_assert(slot < def->n_slots, (file_line, "record_definition_slot: too high slot: %"PRIuMAX" >= %"PRIuMAX"", (uintmax_t)slot, (uintmax_t)def->n_slots));
110 return slot;
114 struct flat_record_definition_entry {
115 flat_size_t flat_offset;
116 const struct type *subtype;
119 struct flat_type_head {
120 struct type type; /* must be first */
123 struct flat_record_definition {
124 struct type type; /* must be first */
125 const struct type *base;
126 struct flat_record_definition_entry entries[FLEXIBLE_ARRAY]; /* indexed by slot of the original record */
129 #define flat_record_n_entries(def) (type_def((def)->base,record)->n_entries)
130 #define flat_record_n_slots(def) (type_def((def)->base,record)->n_slots)
133 struct flat_array_definition {
134 struct type type; /* must be first */
135 const struct type *base;
136 flat_size_t n_elements;
140 struct type_entry;
141 struct type_entry *type_prepare_flat_record(const struct type *base, ajla_error_t *mayfail);
142 void type_set_flat_record_entry(struct type_entry *def, arg_t idx, const struct type *subtype);
143 const struct type *type_get_flat_record(struct type_entry *def, ajla_error_t *mayfail);
144 void type_free_flat_record(struct type_entry *def);
146 const struct type *type_get_flat_array(const struct type *base, pcode_t n_elements, ajla_error_t *mayfail);
149 int type_memcmp(const unsigned char *flat1, const unsigned char *flat2, const struct type *type, size_t n);
152 void type_init(void);
153 void type_done(void);
155 #endif