1 // 2 // Copyright (C) 2013-2019 Nick Gasson 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 // 17 18 #ifndef _OBJECT_H 19 #define _OBJECT_H 20 21 #include "util.h" 22 #include "array.h" 23 #include "tree.h" 24 #include "type.h" 25 26 #include <stdint.h> 27 28 // 29 // Structures shared between tree and type objects 30 // 31 32 #define ONE_HOT(x) (UINT64_C(1) << (x)) 33 34 typedef uint64_t imask_t; 35 36 #define I_IDENT ONE_HOT(0) 37 #define I_VALUE ONE_HOT(1) 38 #define I_SEVERITY ONE_HOT(2) 39 #define I_MESSAGE ONE_HOT(3) 40 #define I_TARGET ONE_HOT(4) 41 #define I_IVAL ONE_HOT(5) 42 #define I_IDENT2 ONE_HOT(6) 43 #define I_DECLS ONE_HOT(7) 44 #define I_STMTS ONE_HOT(8) 45 #define I_PORTS ONE_HOT(9) 46 #define I_GENERICS ONE_HOT(10) 47 #define I_PARAMS ONE_HOT(11) 48 #define I_GENMAPS ONE_HOT(12) 49 #define I_WAVES ONE_HOT(13) 50 #define I_CONDS ONE_HOT(14) 51 #define I_TYPE ONE_HOT(15) 52 #define I_SUBKIND ONE_HOT(16) 53 #define I_DELAY ONE_HOT(17) 54 #define I_REJECT ONE_HOT(18) 55 #define I_POS ONE_HOT(19) 56 #define I_REF ONE_HOT(20) 57 #define I_FILE_MODE ONE_HOT(21) 58 #define I_ASSOCS ONE_HOT(22) 59 #define I_CONTEXT ONE_HOT(23) 60 #define I_TRIGGERS ONE_HOT(24) 61 #define I_ELSES ONE_HOT(25) 62 #define I_CLASS ONE_HOT(26) 63 #define I_RANGES ONE_HOT(27) 64 #define I_NAME ONE_HOT(28) 65 #define I_NETS ONE_HOT(29) 66 #define I_DVAL ONE_HOT(30) 67 #define I_SPEC ONE_HOT(31) 68 #define I_OPS ONE_HOT(32) 69 #define I_INDEXCON ONE_HOT(33) 70 #define I_BASE ONE_HOT(34) 71 #define I_ELEM ONE_HOT(35) 72 #define I_FILE ONE_HOT(36) 73 #define I_ACCESS ONE_HOT(37) 74 #define I_RESOLUTION ONE_HOT(38) 75 #define I_RESULT ONE_HOT(39) 76 #define I_UNITS ONE_HOT(40) 77 #define I_LITERALS ONE_HOT(41) 78 #define I_DIMS ONE_HOT(42) 79 #define I_FIELDS ONE_HOT(43) 80 #define I_TEXT_BUF ONE_HOT(44) 81 #define I_ATTRS ONE_HOT(45) 82 #define I_PTYPES ONE_HOT(46) 83 #define I_CHARS ONE_HOT(47) 84 #define I_CONSTR ONE_HOT(48) 85 #define I_FLAGS ONE_HOT(49) 86 #define I_TEXT ONE_HOT(50) 87 88 #define ITEM_IDENT (I_IDENT | I_IDENT2) 89 #define ITEM_TREE (I_VALUE | I_SEVERITY | I_MESSAGE | I_TARGET \ 90 | I_DELAY | I_REJECT | I_REF | I_FILE_MODE \ 91 | I_NAME | I_SPEC | I_RESOLUTION | I_CONSTR) 92 #define ITEM_TREE_ARRAY (I_DECLS | I_STMTS | I_PORTS | I_GENERICS | I_WAVES \ 93 | I_CONDS | I_TRIGGERS | I_ELSES | I_PARAMS \ 94 | I_GENMAPS | I_ASSOCS | I_CONTEXT | I_OPS \ 95 | I_LITERALS | I_FIELDS | I_UNITS | I_CHARS) 96 #define ITEM_TYPE (I_TYPE | I_BASE | I_ELEM | I_ACCESS | I_RESULT \ 97 | I_FILE) 98 #define ITEM_INT64 (I_POS | I_IVAL) 99 #define ITEM_INT32 (I_SUBKIND | I_CLASS | I_FLAGS) 100 #define ITEM_NETID_ARRAY (I_NETS) 101 #define ITEM_DOUBLE (I_DVAL) 102 #define ITEM_TYPE_ARRAY (I_PTYPES | I_INDEXCON) 103 #define ITEM_RANGE_ARRAY (I_RANGES | I_DIMS) 104 #define ITEM_TEXT_BUF (I_TEXT_BUF) 105 #define ITEM_ATTRS (I_ATTRS) 106 #define ITEM_TEXT (I_TEXT) 107 108 #define OBJECT_TAG_TREE 0 109 #define OBJECT_TAG_TYPE 1 110 111 DECLARE_ARRAY(netid); 112 DECLARE_ARRAY(range); 113 DECLARE_ARRAY(tree); 114 DECLARE_ARRAY(type); 115 DECLARE_ARRAY(ident); 116 117 #define lookup_item(class, t, mask) ({ \ 118 assert((t) != NULL); \ 119 assert((mask & (mask - 1)) == 0); \ 120 \ 121 const imask_t has = has_map[(t)->object.kind]; \ 122 \ 123 if (unlikely((has & mask) == 0)) \ 124 object_lookup_failed((class)->name, kind_text_map, \ 125 (t)->object.kind, mask); \ 126 \ 127 const int tzc = __builtin_ctzll(mask); \ 128 const int off = ((t)->object.kind * 64) + tzc; \ 129 const int n = (class)->item_lookup[off]; \ 130 \ 131 &((t)->object.items[n]); \ 132 }) 133 134 typedef enum { 135 A_STRING, A_INT, A_PTR, A_TREE 136 } attr_kind_t; 137 138 typedef uint16_t generation_t; 139 typedef uint32_t index_t; 140 141 typedef struct { 142 attr_kind_t kind; 143 ident_t name; 144 union { 145 ident_t sval; 146 int ival; 147 void *pval; 148 tree_t tval; 149 }; 150 } attr_t; 151 152 typedef struct { 153 uint16_t alloc; 154 uint16_t num; 155 attr_t *table; 156 } attr_tab_t; 157 158 typedef union { 159 ident_t ident; 160 tree_t tree; 161 tree_array_t tree_array; 162 type_t type; 163 unsigned subkind; 164 int64_t ival; 165 double dval; 166 range_t *range; 167 netid_array_t netid_array; 168 range_array_t range_array; 169 text_buf_t *text_buf; 170 type_array_t type_array; 171 attr_tab_t attrs; 172 ident_array_t ident_array; 173 char *text; 174 } item_t; 175 176 typedef struct { 177 uint8_t kind; 178 uint8_t tag; 179 generation_t generation; 180 index_t index; 181 loc_t loc; 182 item_t items[0]; 183 } object_t; 184 185 typedef struct { 186 generation_t generation; 187 index_t index; 188 tree_copy_fn_t callback; 189 void *context; 190 object_t **copied; 191 } object_copy_ctx_t; 192 193 typedef struct { 194 object_t **cache; 195 index_t index; 196 generation_t generation; 197 tree_rewrite_fn_t fn; 198 void *context; 199 size_t cache_size; 200 } object_rewrite_ctx_t; 201 202 typedef struct { 203 unsigned count; 204 tree_visit_fn_t preorder; 205 tree_visit_fn_t postorder; 206 void *context; 207 tree_kind_t kind; 208 unsigned generation; 209 bool deep; 210 } object_visit_ctx_t; 211 212 typedef int change_allowed_t[2]; 213 214 typedef struct { 215 const char *name; 216 const change_allowed_t *change_allowed; 217 const imask_t *has_map; 218 const char **kind_text_map; 219 const int tag; 220 const int last_kind; 221 const int gc_roots[6]; 222 const int gc_num_roots; 223 int *object_nitems; 224 size_t *object_size; 225 int *item_lookup; 226 } object_class_t; 227 228 typedef struct { 229 fbuf_t *file; 230 ident_wr_ctx_t ident_ctx; 231 unsigned generation; 232 unsigned n_objects; 233 } object_wr_ctx_t; 234 235 typedef struct { 236 fbuf_t *file; 237 ident_rd_ctx_t ident_ctx; 238 unsigned n_objects; 239 object_t **store; 240 unsigned store_sz; 241 char *db_fname; 242 } object_rd_ctx_t; 243 244 __attribute__((noreturn)) 245 void object_lookup_failed(const char *name, const char **kind_text_map, 246 int kind, imask_t mask); 247 248 void item_without_type(imask_t mask); 249 250 void object_change_kind(const object_class_t *class, 251 object_t *object, int kind); 252 object_t *object_new(const object_class_t *class, int kind); 253 void object_one_time_init(void); 254 void object_gc(void); 255 void object_visit(object_t *object, object_visit_ctx_t *ctx); 256 object_t *object_rewrite(object_t *object, object_rewrite_ctx_t *ctx); 257 unsigned object_next_generation(void); 258 object_t *object_copy_sweep(object_t *object, object_copy_ctx_t *ctx); 259 bool object_copy_mark(object_t *object, object_copy_ctx_t *ctx); 260 void object_replace(object_t *t, object_t *a); 261 262 void object_write(object_t *object, object_wr_ctx_t *ctx); 263 object_wr_ctx_t *object_write_begin(fbuf_t *f); 264 void object_write_end(object_wr_ctx_t *ctx); 265 266 object_rd_ctx_t *object_read_begin(fbuf_t *f, const char *fname); 267 void object_read_end(object_rd_ctx_t *ctx); 268 object_t *object_read(object_rd_ctx_t *ctx, int tag); 269 270 #endif // _OBJECT_H 271