Added package with the documentation and the examples
[lwc.git] / icode.c
blobbebb4f2384ad2ef793e42aa8bd976e434cf3ab6e
1 #include "global.h"
3 /******************************************************************************
5 For some things we need some internal static inline functions,
6 where otherwise we would have to use statements in
7 expressions and hacks.
9 However, these are created only if/when needed.
11 ******************************************************************************/
13 static intnode *dinits;
15 Token i_call_initialization (recID r)
17 intnode *n = intfind (dinits, r);
18 if (n) return n->v.i;
20 Token n1 = name_of_struct (r);
21 Token fn = name_intern_ctor (r);
22 Token xx = RESERVED_x;
23 Token yy = RESERVED_y;
24 Token ii = RESERVED_i;
25 Token XX = RESERVED_X;
27 /** ** cheat:
28 - static inline void A__ICoNsTrUcTioN (struct A *x, const int u)
29 - {
30 - int i;
31 - for (i = 0; i < y; i++) {
32 - struct A *X = &xx [i];
33 - .. here we gen_construction_code from hier.c ...
34 - }
35 - }
36 ** **/
38 OUTSTREAM IC = new_stream ();
40 outprintf (IC, RESERVED_static, RESERVED_inline, RESERVED_void,
41 fn, '(', iRESERVED_struct (r), n1, '*', xx, ',', RESERVED_const,
42 RESERVED_int, yy, ')', '{', RESERVED_int, ii, ';', RESERVED_for, '(',
43 ii, '=', RESERVED_0, ';', ii, '<', yy, ';', ii, PLUSPLUS, ')', '{',
44 iRESERVED_struct (r), n1, '*', XX, '=', '&', xx, '[', ii, ']', ';', -1);
46 gen_construction_code (IC, r, XX);
48 outprintf (IC, '}', '}', -1);
50 concate_streams (INTERNAL_CODE, IC);
52 union ival i = { .i = fn };
53 intadd (&dinits, r, i);
55 return fn;
58 static intnode *dcasts;
60 Token i_downcast_function (recID rb, recID rd)
62 int bdi = rb + rd * 3000;
63 intnode *n = intfind (dcasts, bdi);
64 if (n) return n->v.i;
66 rd = aliasclass (rd);
67 rb = aliasclass (rb);
68 bdi = rb + rd * 3000;
69 if (n = intfind (dcasts, bdi)) return n->v.i;
71 Token base = name_of_struct (rb), der = name_of_struct (rd);
72 Token fname = name_downcast (base, der);
73 Token x = RESERVED_x;
74 Token *path;
75 bool va = is_ancestor_runtime (rd, rb, &path);
77 /** ** cheat:
78 - static inline struct der *downcast (struct base *x)
79 - {
80 - return (struct der*)((void*)x - (int) &(((struct der*)0)->path));
81 - }
82 - or:
83 - static inline struct der *downcast (struct base *x)
84 - {
85 - return (struct der*)((void*)x + x->_v_p_t_r_->base_der_DoWnCaSt);
86 - }
87 - or broken into the above two:
88 - static inline struct der *downcast (struct base *x)
89 - {
90 - return downcast (downcast (x));
91 - }
92 ** **/
94 #define VOIDCAST '(', RESERVED_void, '*', ')'
96 OUTSTREAM IC = new_stream ();
97 outprintf (IC, RESERVED_static, RESERVED_inline,
98 iRESERVED_struct (rd), der, '*', fname, '(', RESERVED_const,
99 iRESERVED_struct (rb), base, '*', x, ')', '{', RESERVED_return, -1);
101 if (!va) {
102 outprintf (IC,
103 '(', iRESERVED_struct (rd), der, '*', ')',
104 '(', VOIDCAST, x, '-', '(', RESERVED_int, ')', '&',
105 '(', '(', '(', iRESERVED_struct (rd), der, '*', ')',
106 RESERVED_0, ')', POINTSAT, ISTR (path), ')', ')', -1);
107 } else if (path [1] == -1) {
108 Token path [128];
110 downcast_rtti (rd, rb, rb, path);
111 outprintf (IC,
112 '(', iRESERVED_struct (rd), der, '*', ')', '(',
113 VOIDCAST, x, '+', x, POINTSAT, ISTR (path), ')', -1);
114 } else {
116 /* In this case, we can implement the first half of the downcast
117 -which is plain- with one of the above and call
118 only one DoWnCaSt function. Typically it makes no difference
119 because gcc can do great work recursively inlining all these.
120 So AFA assembly is concerned we don't have to do this optimization.
121 Having fewer DoWnCaSt functions in the output, would be
122 a better thing tho.
124 int i;
125 recID mid;
127 if (path [1] == POINTSAT)
128 mid = ancest_named (rd, path [0]);
129 else for (mid = rd, i = 0; path [i + 1] != POINTSAT && path [i + 1] != -1; i+= 2)
130 mid = ancest_named (mid, path [i]);
132 outprintf (IC,
133 '(', iRESERVED_struct (rd), name_of_struct (rd), '*', ')',
134 i_downcast_function (mid, rd), '(',
135 i_downcast_function (rb, mid), '(', x, ')',
136 ')', -1);
139 outprintf (IC, ';', '}', -1);
140 concate_streams (INTERNAL_CODE, IC);
142 union ival i = { .i = fname };
143 intadd (&dcasts, bdi, i);
144 return fname;
147 static intnode *dcasts_safe;
149 Token i_downcast_null_safe (recID rb, recID rd)
151 int bdi = rb + rd * 3000;
152 intnode *n = intfind (dcasts_safe, bdi);
153 if (n) return n->v.i;
155 /* ** cheat
156 - static inline struct der* downcast_safe (struct base *x)
158 - return x ? Downcast (x) : 0;
160 ** **/
162 OUTSTREAM IC = new_stream ();
163 Token base = name_of_struct (rb), der = name_of_struct (rd);
164 Token fname = name_downcast_safe (base, der);
165 Token x = RESERVED_x;
167 outprintf (IC, RESERVED_static, RESERVED_inline, iRESERVED_struct (rd),
168 der, '*', fname, '(', iRESERVED_struct (rb),
169 base, '*', x, ')', '{', RESERVED_return,
170 x, '?', i_downcast_function (rb, rd), '(', x, ')', ':',
171 RESERVED_0, ';', '}', -1);
173 concate_streams (INTERNAL_CODE, IC);
175 union ival i = { .i = fname };
176 intadd (&dcasts_safe, bdi, i);
177 return fname;
180 static intnode *upcasts;
182 Token i_upcast_null_safe (recID rb, recID rd, Token *path, bool ptrpath)
184 int bdi = rb + rd * 3000;
185 intnode *n = intfind (upcasts, bdi);
186 if (n) return n->v.i;
188 /* ** cheat
189 - static inline struct base* upcast_safe (struct der *x)
191 - return x ? &x->path : 0;
193 ** **/
195 Token base = name_of_struct (rb), der = name_of_struct (rd);
196 Token fname = name_upcast_safe (base, der);
197 Token x = RESERVED_x;
199 outprintf (INTERNAL_CODE, RESERVED_static, RESERVED_inline,
200 iRESERVED_struct (rb), base, '*', fname,
201 '(', iRESERVED_struct (rd), der, '*', x, ')', '{',
202 RESERVED_return, x, '?', ptrpath ? BLANKT : '&', x,
203 POINTSAT, ISTR (path), ':', RESERVED_0, ';', '}', -1);
205 union ival i = { .i = fname };
206 intadd (&upcasts, bdi, i);
207 return fname;
210 static intnode *vcalls;
212 Token i_member_virtual (recID r, Token n, typeID *argt, flookup *rF)
214 Token vpath [128], *proto;
215 flookup F;
216 int i;
217 bool modular = rF->flagz & FUNCP_MODULAR;
219 rF->flagz &= ~FUNCP_MODULAR;
220 if (!lookup_virtual_function_member (r, n, argt, vpath, &F))
221 parse_error_ll ("error && bug");
223 rF->oname = F.oname = vpath [intlen (vpath) - 1];
224 if (intfind (vcalls, F.oname))
225 return F.oname;
227 // create the new prototype
228 proto = allocaint (intlen (F.prototype) + 10);
229 intcpy (proto, F.prototype);
230 if (modular) {
231 // add 'this'
232 for (i = 0; proto [i] != MARKER; i++);
233 while (proto [i] != '(') i++;
234 Token *rest = allocaint (intlen (proto + i) + 1);
235 intcpy (rest, proto + ++i);
236 sintprintf (proto + i, RESERVED_const, iRESERVED_struct (r),
237 name_of_struct (r), '*', RESERVED_this, -1);
238 i += 5;
239 if (rest [0] != ')')
240 proto [i++] = ',';
241 sintprintf (proto + i, ISTR (rest), -1);
243 intsubst1 (proto, MARKER, F.oname);
244 rF->prototype = intdup (proto);
246 i = modular && F.xargs [0] == -1 ? 0 : 1;
247 outprintf (INTERNAL_CODE, intchr (proto, RESERVED_static) ? BLANKT : RESERVED_static,
248 intchr (proto, RESERVED_inline) ? BLANKT : RESERVED_inline,
249 ISTR (proto), '{', RESERVED_return, RESERVED_this, POINTSAT,
250 ISTR (vpath), '(',
251 modular ? (F.xargs [0] != -1 ? F.xargs [0] : BLANKT) : RESERVED_this, -1);
252 for (; F.xargs [i] != -1; i++)
253 outprintf (INTERNAL_CODE, ',', F.xargs [i], -1);
254 outprintf (INTERNAL_CODE, ')', ';', '}', -1);
256 union ival I;
257 intadd (&vcalls, F.oname, I);
258 return F.oname;
261 static intnode *trftree;
263 Token i_trampoline_func (flookup *F, bool argb[])
265 int i, j;
266 char snm [32];
267 Token tfn;
269 if (!F->oname)
270 parse_error_ll ("Can't do it");
272 for (i = 0; argb [i] != -1; i++)
273 snm [i] = argb [i] ? '1' : '0';
274 snm [i] = 0; strcat (snm, "trampoline");
276 tfn = tokstrcat (F->oname, snm);
277 if (intfind (trftree, tfn))
278 return tfn;
280 Token *proto = mallocint (intlen (F->prototype) + 1);
281 intcpy (proto, F->prototype);
282 if (intchr (proto, F->oname))
283 intsubst (proto, F->oname, tfn);
284 else if (intchr (proto, MARKER))
285 intsubst (proto, MARKER, tfn);
286 else parse_error_ll ("Nasty alien outlaw bug");
288 if (intchr (proto, RESERVED__CLASS_))
289 repl__CLASS_ (&proto, base_of (open_typeID (F->t)[2]));
291 for (i = 0; argb [i] != -1; i++)
292 if (argb [i]) {
293 for (j = 2; proto [j] != F->xargs [i]; j++);
294 if (proto [j - 1] == RESERVED_const)
295 proto [j - 2] = BLANKT;
296 proto [j - 1] = BLANKT;
299 outprintf (INTERNAL_CODE, intchr (proto, RESERVED_static) ? BLANKT : RESERVED_static,
300 intchr (proto, RESERVED_inline) ? BLANKT : RESERVED_inline,
301 ISTR (proto), '{', -1);
303 outprintf (INTERNAL_CODE, RESERVED_return, F->oname, '(', -1);
304 for (i = 0; argb [i] != -1; i++) {
305 outprintf (INTERNAL_CODE, argb [i] ? '&' : BLANKT, F->xargs [i],
306 argb [i + 1] == -1 ? BLANKT : ',', -1);
308 outprintf (INTERNAL_CODE, ')', ';', '}', -1);
309 free (proto);
311 union ival I;
312 intadd (&trftree, tfn, I);
313 return tfn;
316 static intnode *ebntree;
318 Token i_enum_by_name (Token e)
320 int i;
321 intnode *n = intfind (ebntree, e);
322 if (n)
323 return n->v.i;
325 if (!is_enum (e)) parse_error_tok (e, "__enumstr__: enumerator not defined");
327 Token fname = name_ebn_func (e), *consts = enum_syms (lookup_enum (e));
329 outprintf (INTERNAL_CODE, RESERVED_const, RESERVED_char, '*', fname, '(',
330 RESERVED_int, ')', linkonce_text (fname), ';',
331 RESERVED_const, RESERVED_char, '*', fname, '(', RESERVED_int, RESERVED_X, ')',
332 '{', RESERVED_switch, '(', RESERVED_X, ')', '{', -1);
333 for (i = 0; consts [i] != -1; i++)
334 outprintf (INTERNAL_CODE, RESERVED_case, consts [i], ':',
335 RESERVED_return, new_value_string (expand (consts [i])), ';', -1);
336 outprintf (INTERNAL_CODE, RESERVED_default, ':', RESERVED_return,
337 RESERVED_0, ';', '}', '}', -1);
339 union ival I = { .i = fname };
340 intadd (&ebntree, e, I);
341 return fname;
344 static intnode *typeidt;
346 Token i_typeid_var (Token c)
348 intnode *n = intfind (typeidt, c);
349 if (n)
350 return n->v.i;
352 Token fname = name_typeid_var (c);
354 outprintf (GVARS, RESERVED_const, RESERVED_char, fname, '[', ']',
355 linkonce_rodata (fname), '=', stringify (c), ';', -1);
357 union ival I = { .i = fname };
358 intadd (&typeidt, c, I);
359 return fname;
362 Token arrdtor;
363 static intnode *arrdtortree;
365 Token i_arrdtor_func (recID r)
367 Token i = RESERVED_i, p = RESERVED_p;
368 intnode *n = intfind (arrdtortree, r);
369 if (n)
370 return n->v.i;
372 if (!arrdtor) {
373 arrdtor = new_symbol ("ArRdToR");
374 outprintf (INTERNAL_CODE, RESERVED_struct, arrdtor, '{', RESERVED_void, '*',
375 p, ';', RESERVED_int, i, ';', '}', ';', -1);
378 Token fname = name_arrdtor (r);
380 outprintf (INTERNAL_CODE, RESERVED_static, RESERVED_inline, RESERVED_void, fname, '(',
381 RESERVED_struct, arrdtor, '*', RESERVED_this, ')', '{',
382 iRESERVED_struct (r), name_of_struct (r), '*', p, '=',
383 RESERVED_this, POINTSAT, p, ';', RESERVED_int, i, '=',
384 RESERVED_this, POINTSAT, i, ';', RESERVED_while, '(', i, ')',
385 dtor_name (r), '(', '&', p, '[', MINUSMINUS, i, ']', ')', ';', '}', -1);
387 union ival I = { .i = fname };
388 intadd (&arrdtortree, r, I);
389 return fname;
392 /***********************************************
393 These are called by expressions
394 ***********************************************/
396 void alloc_and_init (OUTSTREAM o, recID r, Token tid, Token alloc, Token vec)
398 Token sn = name_of_struct (r);
399 Token ic;
401 /** Cheat:
402 - = (struct sn*) malloc_alloca (sizeof (struct sn));
403 - sn___CoNsTruCTion (x, 1);
404 - or vector
405 - = (struct sn*) malloc_alloca (sizeof (struct sn) * n);
406 - sn___CoNsTruCTion (x, n);
407 - or with custom allocator
408 - = (struct sn*) allocator_fn ();
409 - sn___CoNsTruCTion (x, 1);
411 outprintf (o, '=', '(', iRESERVED_struct (r), sn, '*', ')', alloc, '(', -1);
412 if (in2 (alloc, new_wrap, INTERN_alloca))
413 outprintf (o, RESERVED_sizeof, '(', iRESERVED_struct (r), sn, ')', -1);
414 if (vec) outprintf (o, '*', vec, -1);
415 outprintf (o, ')', ';', -1);
417 if (need_construction (r)) {
418 ic = i_call_initialization (r);
419 outprintf (o, ic, '(', tid, ',', vec ?: RESERVED_1, ')', ';', -1);
423 void alloc_and_init_dcl (OUTSTREAM o, recID r, Token tid, bool array)
425 Token ic;
427 if (o == GLOBAL_INIT_FUNC) GlobInitUsed = true;
428 /** The classic:
429 - A__CoNsTruCTioN (&a, 1);
430 - or array
431 - A__CoNsTruCTioN (a, sizeof a / sizeof a [0]);
433 ic = i_call_initialization (r);
434 if (array) outprintf (o, ic, '(', tid, ',', RESERVED_sizeof, tid,
435 '/', RESERVED_sizeof, tid, '[', RESERVED_0, ']', ')', ';', -1);
436 else outprintf (o, ic, '(', '&', tid, ',', RESERVED_1, ')', ';', -1);