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