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
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/>.
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
68 static inline bool type_is_equal(const struct type
*t1
, const struct type
*t2
)
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
{
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
)
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
));
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
;
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);