|
|
1 # include "comp.h"
2 # include "str.h"
3 # include "array.h"
4 # include "object.h"
5 # include "xfloat.h"
6 # include "interpret.h"
7 # include "data.h"
8 # include "table.h"
9 # include "node.h"
10 # include "control.h"
11 # include "codegen.h"
12 # include "compile.h"
13
14 # define LINE_CHUNK 128
15
16 typedef struct _linechunk_ {
17 struct _linechunk_ *next; /* next in list */
18 char info[LINE_CHUNK]; /* chunk of line number info */
19 } linechunk;
20
21 static linechunk *lline, *tline; /* line chunk list */
22 static linechunk *fline; /* free line chunk list */
23 static unsigned int lchunksz = LINE_CHUNK; /* line chunk size */
24 static unsigned short line; /* current line number */
25 static unsigned int line_info_size; /* size of all line info */
26
27 /*
28 * NAME: line->byte()
29 * DESCRIPTION: output a line description byte
30 */
31 static void line_byte(byte)
32 int byte;
33 {
34 if (lchunksz == LINE_CHUNK) {
35 register linechunk *l;
36
37 /* new chunk */
38 if (fline != (linechunk *) NULL) {
39 /* from free list */
40 l = fline;
41 fline = l->next;
42 } else {
43 l = ALLOC(linechunk, 1);
44 }
45 l->next = (linechunk *) NULL;
46 if (tline != (linechunk *) NULL) {
47 tline->next = l;
48 } else {
49 lline = l;
50 }
51 tline = l;
52 lchunksz = 0;
53 }
54
55 tline->info[lchunksz++] = byte;
56 line_info_size++;
57 }
58
59 /*
60 * NAME: line->fix()
61 * DESCRIPTION: Fix the new line number. Return 0 .. 2 for simple offsets,
62 * 3 for special ones.
63 */
64 static int line_fix(newline)
65 register unsigned short newline;
66 {
67 register short offset;
68
69 if (newline == 0) {
70 /* nothing changes */
71 return 0;
72 }
73 offset = newline - line;
74 if (line != 0 && offset >= 0 && offset <= 2) {
75 /* simple offset */
76 line = newline;
77 return offset;
78 }
79
80 if (offset >= -64 && offset <= 63) {
81 /* one byte offset */
82 line_byte(offset + 128 + 64);
83 } else {
84 /* two byte offset */
85 offset += 16384;
86 line_byte((offset >> 8) & 127);
87 line_byte(offset);
88 }
89 line = newline;
90 return 3;
91 }
92
93 /*
94 * NAME: line->make()
95 * DESCRIPTION: put line number info after the function
96 */
97 static void line_make(buf)
98 register char *buf;
99 {
100 register linechunk *l;
101
102 /* collect all line blocks in one large block */
103 for (l = lline; l != tline; l = l->next) {
104 memcpy(buf, l->info, LINE_CHUNK);
105 buf += LINE_CHUNK;
106 }
107 memcpy(buf, l->info, lchunksz);
108
109 /* add blocks to free list */
110 tline->next = fline;
111 fline = lline;
112 /* clear blocks */
113 lline = (linechunk *) NULL;
114 tline = (linechunk *) NULL;
115 lchunksz = LINE_CHUNK;
116 line = 0;
117 line_info_size = 0;
118 }
119
120 /*
121 * NAME: line->clear()
122 * DESCRIPTION: clean up line number info chunks
123 */
124 static void line_clear()
125 {
126 register linechunk *l, *f;
127
128 for (l = fline; l != (linechunk *) NULL; ) {
129 f = l;
130 l = l->next;
131 FREE(f);
132 }
133 fline = (linechunk *) NULL;
134 }
135
136
137 # define CODE_CHUNK 128
138
139 typedef struct _codechunk_ {
140 struct _codechunk_ *next; /* next in list */
141 char code[CODE_CHUNK]; /* chunk of code */
142 } codechunk;
143
144 static codechunk *lcode, *tcode; /* code chunk list */
145 static codechunk *fcode; /* free code chunk list */
146 static unsigned int cchunksz = CODE_CHUNK; /* code chunk size */
147 static Uint here; /* current offset */
148 static char *last_instruction; /* last instruction's address */
149
150 /*
151 * NAME: code->byte()
152 * DESCRIPTION: output a byte of code
153 */
154 static void code_byte(byte)
155 char byte;
156 {
157 if (cchunksz == CODE_CHUNK) {
158 register codechunk *l;
159
160 /* new chunk */
161 if (fcode != (codechunk *) NULL) {
162 /* from free list */
163 l = fcode;
164 fcode = l->next;
165 } else {
166 l = ALLOC(codechunk, 1);
167 }
168 l->next = (codechunk *) NULL;
169 if (tcode != (codechunk *) NULL) {
170 tcode->next = l;
171 } else {
172 lcode = l;
173 }
174 tcode = l;
175 cchunksz = 0;
176 }
177 tcode->code[cchunksz++] = byte;
178 here++;
179 }
180
181 /*
182 * NAME: code->word()
183 * DESCRIPTION: output a word of code
184 */
185 static void code_word(word)
186 unsigned short word;
187 {
188 code_byte(word >> 8);
189 code_byte(word);
190 }
191
192 /*
193 * NAME: code->instr()
194 * DESCRIPTION: generate an instruction code
195 */
196 static void code_instr(i, line)
197 register int i;
198 register unsigned short line;
199 {
200 code_byte(i | (line_fix(line) << I_LINE_SHIFT));
201 last_instruction = &tcode->code[cchunksz - 1];
202 }
203
204 /*
205 * NAME: code->kfun()
206 * DESCRIPTION: generate code for a builtin kfun
207 */
208 static void code_kfun(kf, line)
209 int kf;
210 unsigned short line;
211 {
212 code_instr(I_CALL_KFUNC, line);
213 code_byte(kf);
214 }
215
216 /*
217 * NAME: code->make()
218 * DESCRIPTION: create function code block
219 */
220 static char *code_make(depth, nlocals, size)
221 unsigned short depth, *size;
222 int nlocals;
223 {
224 register codechunk *l;
225 register char *code;
226 Uint sz;
227
228 *size = sz = 5 + here + line_info_size;
229 if (sz > USHRT_MAX) {
230 c_error("function too large");
231 }
232 code = ALLOC(char, sz);
233 *code++ = depth >> 8;
234 *code++ = depth;
235 *code++ = nlocals;
236 *code++ = here >> 8;
237 *code++ = here;
238
239 /* collect all code blocks in one large block */
240 for (l = lcode; l != tcode; l = l->next) {
241 memcpy(code, l->code, CODE_CHUNK);
242 code += CODE_CHUNK;
243 }
244 memcpy(code, l->code, cchunksz);
245 code += cchunksz;
246 line_make(code);
247 code -= 5 + here;
248
249 /* add blocks to free list */
250 tcode->next = fcode;
251 fcode = lcode;
252 /* clear blocks */
253 lcode = (codechunk *) NULL;
254 tcode = (codechunk *) NULL;
255 cchunksz = CODE_CHUNK;
256
257 here = 0;
258 return code;
259 }
260
261 /*
262 * NAME: code->clear()
263 * DESCRIPTION: clean up the code chunks
264 */
265 static void code_clear()
266 {
267 register codechunk *l, *f;
268
269 for (l = fcode; l != (codechunk *) NULL; ) {
270 f = l;
271 l = l->next;
272 FREE(f);
273 }
274 fcode = (codechunk *) NULL;
275
276 line_clear();
277 }
278
279
280 # define JUMP_CHUNK 128
281
282 typedef struct _jmplist_ {
283 Uint where; /* where to jump from */
284 Uint to; /* where to jump to */
285 struct _jmplist_ *next; /* next in list */
286 } jmplist;
287
288 typedef struct _jmpchunk_ {
289 struct _jmpchunk_ *next; /* next in list */
290 jmplist jump[JUMP_CHUNK]; /* chunk of jumps */
291 } jmpchunk;
292
293 static jmpchunk *ljump; /* list of jump chunks */
294 static jmpchunk *fjump; /* list of free jump chunks */
295 static int jchunksz = JUMP_CHUNK; /* size of jump chunk */
296 static jmplist *true_list; /* list of true jumps */
297 static jmplist *false_list; /* list of false jumps */
298 static jmplist *break_list; /* list of break jumps */
299 static jmplist *continue_list; /* list of continue jumps */
300
301 /*
302 * NAME: jump->addr()
303 * DESCRIPTION: generate a jump
304 */
305 static jmplist *jump_addr(list)
306 jmplist *list;
307 {
308 register jmplist *j;
309
310 if (jchunksz == JUMP_CHUNK) {
311 register jmpchunk *l;
312
313 /* new chunk */
314 if (fjump != (jmpchunk *) NULL) {
315 /* from free list */
316 l = fjump;
317 fjump = l->next;
318 } else {
319 l = ALLOC(jmpchunk, 1);
320 }
321 l->next = ljump;
322 ljump = l;
323 jchunksz = 0;
324 }
325 j = &ljump->jump[jchunksz++];
326 j->where = here;
327 j->next = list;
328 code_word(0); /* empty space in code block filled in later */
329
330 return j;
331 }
332
333 /*
334 * NAME: jump()
335 * DESCRIPTION: create a jump
336 */
337 static jmplist *jump(i, list)
338 int i;
339 jmplist *list;
340 {
341 code_instr(i, 0);
342 return jump_addr(list);
343 }
344
345 /*
346 * NAME: jump->resolve()
347 * DESCRIPTION: resolve all jumps in a jump list
348 */
349 static void jump_resolve(list, to)
350 register jmplist *list;
351 register Uint to;
352 {
353 while (list != (jmplist *) NULL) {
354 list->to = to;
355 list = list->next;
356 }
357 }
358
359 /*
360 * NAME: jump->make()
361 * DESCRIPTION: fill in all jumps in a code block
362 */
363 static void jump_make(code)
364 register char *code;
365 {
366 register jmpchunk *l;
367 register jmplist *j;
368 register int i;
369 jmplist *jmpjmp;
370
371 i = jchunksz;
372 jmpjmp = (jmplist *) NULL;
373 for (l = ljump; l != (jmpchunk *) NULL; ) {
374 jmpchunk *f;
375
376 /*
377 * fill in jump addresses in code block
378 */
379 j = &l->jump[i];
380 do {
381 --j;
382 code[j->where ] = j->to >> 8;
383 code[j->where + 1] = j->to;
384 if ((code[j->to] & I_INSTR_MASK) == I_JUMP) {
385 /*
386 * add to jump-to-jump list
387 */
388 j->next = jmpjmp;
389 jmpjmp = j;
390 }
391 } while (--i > 0);
392 i = JUMP_CHUNK;
393 f = l;
394 l = l->next;
395 f->next = fjump;
396 fjump = f;
397 }
398
399 for (j = jmpjmp; j != (jmplist *) NULL; j = j->next) {
400 register Uint where, to;
401
402 /*
403 * replace jump-to-jump by a direct jump to destination
404 */
405 where = j->where;
406 to = j->to;
407 while ((code[to] & I_INSTR_MASK) == I_JUMP && to != where - 1) {
408 /*
409 * Change to jump across the next jump. If there is a loop, it
410 * will eventually result in a jump to itself.
411 */
412 code[where ] = code[to + 1];
413 code[where + 1] = code[to + 2];
414 where = to + 1;
415 to = (UCHAR(code[to + 1]) << 8) | UCHAR(code[to + 2]);
416 }
417 /*
418 * jump to final destination
419 */
420 code[j->where ] = to >> 8;
421 code[j->where + 1] = to;
422 }
423
424 ljump = (jmpchunk *) NULL;
425 jchunksz = JUMP_CHUNK;
426 }
427
428 /*
429 * NAME: jump->clear()
430 * DESCRIPTION: clean up the jump chunks
431 */
432 static void jump_clear()
433 {
434 register jmpchunk *l, *f;
435
436 for (l = fjump; l != (jmpchunk *) NULL; ) {
437 f = l;
438 l = l->next;
439 FREE(f);
440 }
441 fjump = (jmpchunk *) NULL;
442 }
443
444
445 static void cg_expr P((node*, int));
446 static void cg_cond P((node*, int));
447 static void cg_stmt P((node*));
448
449 static int nparams; /* number of parameters */
450
451 /*
452 * NAME: codegen->cast()
453 * DESCRIPTION: generate code for a cast
454 */
455 static void cg_cast(type)
456 unsigned short type;
457 {
458 code_instr(I_CAST, 0);
459 if ((type & T_REF) != 0) {
460 type = T_ARRAY;
461 }
462 code_byte(type);
463 }
464
465 /*
466 * NAME: codegen->lvalue()
467 * DESCRIPTION: generate code for an lvalue
468 */
469 static void cg_lvalue(n, type)
470 register node *n;
471 int type;
472 {
473 register node *m;
474 register int typeflag;
475
476 typeflag = (type != 0) ? I_TYPE_BIT : 0;
477
478 if (n->type == N_CAST) {
479 n = n->l.left;
480 }
481 switch (n->type) {
482 case N_LOCAL:
483 code_instr(I_PUSH_LOCAL_LVAL | typeflag, n->line);
484 code_byte(nparams - (int) n->r.number - 1);
485 break;
486
487 case N_GLOBAL:
488 if ((n->r.number >> 8) == 1) {
489 code_instr(I_PUSH_GLOBAL_LVAL | typeflag, n->line);
490 code_byte((int) n->r.number);
491 } else {
492 code_instr(I_PUSH_FAR_GLOBAL_LVAL | typeflag, n->line);
493 code_word((int) n->r.number);
494 }
495 break;
496
497 case N_INDEX:
498 m = n->l.left;
499 if (m->type == N_CAST) {
500 m = m->l.left;
501 }
502 switch (m->type) {
503 case N_LOCAL:
504 code_instr(I_PUSH_LOCAL_LVAL, m->line);
505 code_byte(nparams - (int) m->r.number - 1);
506 break;
507
508 case N_GLOBAL:
509 if ((m->r.number >> 8) == 1) {
510 code_instr(I_PUSH_GLOBAL_LVAL, m->line);
511 code_byte((int) m->r.number);
512 } else {
513 code_instr(I_PUSH_FAR_GLOBAL_LVAL, m->line);
514 code_word((int) m->r.number);
515 }
516 break;
517
518 case N_INDEX:
519 cg_expr(m->l.left, FALSE);
520 cg_expr(m->r.right, FALSE);
521 code_instr(I_INDEX_LVAL, m->line);
522 break;
523
524 default:
525 cg_expr(m, FALSE);
526 break;
527 }
528 cg_expr(n->r.right, FALSE);
529 code_instr(I_INDEX_LVAL | typeflag, n->line);
530 break;
531 }
532
533 if (typeflag != 0) {
534 code_byte((type & T_REF) ? T_ARRAY : type);
535 }
536 }
537
538 /*
539 * NAME: codegen->fetch()
540 * DESCRIPTION: generate code for a fetched lvalue
541 */
542 static void cg_fetch(n)
543 node *n;
544 {
545 cg_lvalue(n, 0);
546 code_instr(I_FETCH, 0);
547 if (n->type == N_CAST) {
548 cg_cast(n->mod);
549 }
550 }
551
552 /*
553 * NAME: codegen->asgnop()
554 * DESCRIPTION: generate code for an assignment operator
555 */
556 static void cg_asgnop(n, op)
557 register node *n;
558 int op;
559 {
560 cg_fetch(n->l.left);
561 cg_expr(n->r.right, FALSE);
562 code_kfun(op, n->line);
563 code_instr(I_STORE, 0);
564 }
565
566 /*
567 * NAME: codegen->aggr()
568 * DESCRIPTION: generate code for an aggregate
569 */
570 static int cg_aggr(n)
571 register node *n;
572 {
573 register int i;
574
575 if (n == (node *) NULL) {
576 return 0;
577 }
578 for (i = 1; n->type == N_PAIR; i++) {
579 cg_expr(n->l.left, FALSE);
580 n = n->r.right;
581 }
582 cg_expr(n, FALSE);
583 return i;
584 }
585
586 /*
587 * NAME: codegen->map_aggr()
588 * DESCRIPTION: generate code for a mapping aggregate
589 */
590 static int cg_map_aggr(n)
591 register node *n;
592 {
593 register int i;
594
595 if (n == (node *) NULL) {
596 return 0;
597 }
598 for (i = 2; n->type == N_PAIR; i += 2) {
599 cg_expr(n->l.left->l.left, FALSE);
600 cg_expr(n->l.left->r.right, FALSE);
601 n = n->r.right;
602 }
603 cg_expr(n->l.left, FALSE);
604 cg_expr(n->r.right, FALSE);
605 return i;
606 }
607
608 /*
609 * NAME: codegen->sumargs()
610 * DESCRIPTION: generate code for summand arguments
611 */
612 static int cg_sumargs(n)
613 register node *n;
614 {
615 int i;
616
617 if (n->type == N_SUM) {
618 i = cg_sumargs(n->l.left);
619 n = n->r.right;
620 } else {
621 i = 0;
622 }
623
624 if (n->type == N_AGGR) {
625 n->type = N_INT;
626 n->l.number = -3 - cg_aggr(n->l.left);
627 cg_expr(n, FALSE);
628 } else if (n->type == N_RANGE) {
629 cg_expr(n->l.left, FALSE);
630 n = n->r.right;
631 if (n->l.left != (node *) NULL) {
632 cg_expr(n->l.left, FALSE);
633 if (n->r.right != (node *) NULL) {
634 cg_expr(n->r.right, FALSE);
635 code_kfun(KF_CKRANGEFT, n->line);
636 } else {
637 code_kfun(KF_CKRANGEF, n->line);
638 }
639 } else if (n->r.right != (node *) NULL) {
640 cg_expr(n->r.right, FALSE);
641 code_kfun(KF_CKRANGET, n->line);
642 } else {
643 code_kfun(KF_RANGE, n->line);
644 code_instr(I_PUSH_INT1, 0);
645 code_byte(-2);
646 }
647 } else {
648 cg_expr(n, FALSE);
649 code_instr(I_PUSH_INT1, 0);
650 code_byte(-2); /* no range */
651 }
652
653 return i + 1;
654 }
655
656 /*
657 * NAME: codegen->funargs()
658 * DESCRIPTION: generate code for function arguments
659 */
660 static int cg_funargs(n, lv)
661 register node *n;
662 bool lv;
663 {
664 register int i;
665
666 if (n == (node *) NULL) {
667 return 0;
668 }
669 for (i = 1; n->type == N_PAIR; i++) {
670 cg_expr(n->l.left, FALSE);
671 n = n->r.right;
672 }
673 if (n->type == N_SPREAD) {
674 register int type;
675
676 cg_expr(n->l.left, FALSE);
677 type = n->l.left->mod & ~(1 << REFSHIFT);
678 if (lv && type != T_MIXED) {
679 /* typechecked lvalues */
680 code_instr(I_SPREAD | I_TYPE_BIT, n->line);
681 code_byte(n->mod);
682 code_byte((type & T_REF) ? T_ARRAY : type);
683 } else {
684 code_instr(I_SPREAD, n->line);
685 code_byte(n->mod);
686 }
687 } else {
688 cg_expr(n, FALSE);
689 }
690 return i;
691 }
692
693 /*
694 * NAME: codegen->expr()
695 * DESCRIPTION: generate code for an expression
696 */
697 static void cg_expr(n, pop)
698 register node *n;
699 register int pop;
700 {
701 register jmplist *jlist, *j2list;
702 register unsigned short i;
703 long l;
704
705 switch (n->type) {
706 case N_ADD:
707 cg_expr(n->l.left, FALSE);
708 if (n->r.right->type == N_FLOAT) {
709 if (NFLT_ISONE(n->r.right)) {
710 code_kfun(KF_ADD1, n->line);
711 break;
712 }
713 if (NFLT_ISMONE(n->r.right)) {
714 code_kfun(KF_SUB1, n->line);
715 break;
716 }
717 }
718 cg_expr(n->r.right, FALSE);
719 code_kfun(KF_ADD, n->line);
720 break;
721
722 case N_ADD_INT:
723 cg_expr(n->l.left, FALSE);
724 if (n->r.right->type == N_INT) {
725 if (n->r.right->l.number == 1) {
726 code_kfun(KF_ADD1_INT, n->line);
727 break;
728 }
729 if (n->r.right->l.number == -1) {
730 code_kfun(KF_SUB1_INT, n->line);
731 break;
732 }
733 }
734 cg_expr(n->r.right, FALSE);
735 code_kfun(KF_ADD_INT, n->line);
736 break;
737
738 case N_ADD_EQ:
739 cg_asgnop(n, KF_ADD);
740 break;
741
742 case N_ADD_EQ_INT:
743 cg_asgnop(n, KF_ADD_INT);
744 break;
745
746 case N_ADD_EQ_1:
747 cg_fetch(n->l.left);
748 code_kfun(KF_ADD1, 0);
749 code_instr(I_STORE, 0);
750 break;
751
752 case N_ADD_EQ_1_INT:
753 cg_fetch(n->l.left);
754 code_kfun(KF_ADD1_INT, 0);
755 code_instr(I_STORE, 0);
756 break;
757
758 case N_AGGR:
759 if (n->mod == T_MAPPING) {
760 i = cg_map_aggr(n->l.left);
761 code_instr(I_AGGREGATE, n->line);
762 code_byte(1);
763 } else {
764 i = cg_aggr(n->l.left);
765 code_instr(I_AGGREGATE, n->line);
766 code_byte(0);
767 }
768 code_word(i);
769 break;
770
771 case N_AND:
772 cg_expr(n->l.left, FALSE);
773 cg_expr(n->r.right, FALSE);
774 code_kfun(KF_AND, n->line);
775 break;
776
777 case N_AND_INT:
778 cg_expr(n->l.left, FALSE);
779 cg_expr(n->r.right, FALSE);
780 code_kfun(KF_AND_INT, n->line);
781 break;
782
783 case N_AND_EQ:
784 cg_asgnop(n, KF_AND);
785 break;
786
787 case N_AND_EQ_INT:
788 cg_asgnop(n, KF_AND_INT);
789 break;
790
791 case N_ASSIGN:
792 if (n->r.right->type == N_CAST) {
793 cg_lvalue(n->l.left, n->r.right->mod);
794 cg_expr(n->r.right->l.left, FALSE);
795 } else {
796 cg_lvalue(n->l.left, 0);
797 cg_expr(n->r.right, FALSE);
798 }
799 code_instr(I_STORE, n->line);
800 break;
801
802 case N_CAST:
803 cg_expr(n->l.left, FALSE);
804 cg_cast(n->mod);
805 break;
806
807 case N_CATCH:
808 jlist = jump((pop) ? I_CATCH | I_POP_BIT : I_CATCH, (jmplist *) NULL);
809 cg_expr(n->l.left, TRUE);
810 code_instr(I_RETURN, 0);
811 jump_resolve(jlist, here);
812 return;
813
814 case N_COMMA:
815 cg_expr(n->l.left, TRUE);
816 cg_expr(n->r.right, pop);
817 return;
818
819 case N_DIV:
820 cg_expr(n->l.left, FALSE);
821 cg_expr(n->r.right, FALSE);
822 code_kfun(KF_DIV, n->line);
823 break;
824
825 case N_DIV_INT:
826 cg_expr(n->l.left, FALSE);
827 cg_expr(n->r.right, FALSE);
828 code_kfun(KF_DIV_INT, n->line);
829 break;
830
831 case N_DIV_EQ:
832 cg_asgnop(n, KF_DIV);
833 break;
834
835 case N_DIV_EQ_INT:
836 cg_asgnop(n, KF_DIV_INT);
837 break;
838
839 case N_EQ:
840 cg_expr(n->l.left, FALSE);
841 cg_expr(n->r.right, FALSE);
842 code_kfun(KF_EQ, n->line);
843 break;
844
845 case N_EQ_INT:
846 cg_expr(n->l.left, FALSE);
847 cg_expr(n->r.right, FALSE);
848 code_kfun(KF_EQ_INT, n->line);
849 break;
850
851 case N_FLOAT:
852 code_instr(I_PUSH_FLOAT, n->line);
853 code_word(n->l.fhigh);
854 code_word((int) (n->r.flow >> 16));
855 code_word((int) n->r.flow);
856 break;
857
858 case N_FUNC:
859 i = cg_funargs(n->l.left->r.right, (n->r.number >> 24) & KFCALL_LVAL);
860 switch (n->r.number >> 24) {
861 case KFCALL:
862 case KFCALL_LVAL:
863 code_kfun((int) n->r.number, n->line);
864 if (PROTO_CLASS(KFUN((short) n->r.number).proto) & C_KFUN_VARARGS) {
865 code_byte(i);
866 }
867 break;
868
869 case DFCALL:
870 if ((n->r.number & 0xff00) == 0) {
871 /* auto object */
872 code_instr(I_CALL_AFUNC, n->line);
873 code_byte((int) n->r.number);
874 } else {
875 code_instr(I_CALL_DFUNC, n->line);
876 code_word((int) n->r.number);
877 }
878 code_byte(i);
879 break;
880
881 case FCALL:
882 code_instr(I_CALL_FUNC, n->line);
883 code_word(ctrl_gencall((long) n->r.number));
884 code_byte(i);
885 break;
886 }
887 break;
888
889 case N_GE:
890 cg_expr(n->l.left, FALSE);
891 cg_expr(n->r.right, FALSE);
892 code_kfun(KF_GE, n->line);
893 break;
894
895 case N_GE_INT:
896 cg_expr(n->l.left, FALSE);
897 cg_expr(n->r.right, FALSE);
898 code_kfun(KF_GE_INT, n->line);
899 break;
900
901 case N_GLOBAL:
902 if ((n->r.number >> 8) == 1) {
903 code_instr(I_PUSH_GLOBAL, n->line);
904 code_byte((int) n->r.number);
905 } else {
906 code_instr(I_PUSH_FAR_GLOBAL, n->line);
907 code_word((int) n->r.number);
908 }
909 break;
910
911 case N_GT:
912 cg_expr(n->l.left, FALSE);
913 cg_expr(n->r.right, FALSE);
914 code_kfun(KF_GT, n->line);
915 break;
916
917 case N_GT_INT:
918 cg_expr(n->l.left, FALSE);
919 cg_expr(n->r.right, FALSE);
920 code_kfun(KF_GT_INT, n->line);
921 break;
922
923 case N_INDEX:
924 cg_expr(n->l.left, FALSE);
925 cg_expr(n->r.right, FALSE);
926 code_instr(I_INDEX, n->line);
927 break;
928
929 case N_INT:
930 if (n->l.number == 0) {
931 code_instr(I_PUSH_ZERO, n->line);
932 } else if (n->l.number == 1) {
933 code_instr(I_PUSH_ONE, n->line);
934 } else if (n->l.number >= -128 && n->l.number <= 127) {
935 code_instr(I_PUSH_INT1, n->line);
936 code_byte((int) n->l.number);
937 } else {
938 code_instr(I_PUSH_INT4, n->line);
939 code_word((int) (n->l.number >> 16));
940 code_word((int) n->l.number);
941 }
942 break;
943
944 case N_LAND:
945 if (!pop) {
946 jlist = true_list;
947 true_list = (jmplist *) NULL;
948 cg_cond(n, TRUE);
949 code_instr(I_PUSH_ZERO, 0);
950 j2list = jump(I_JUMP, (jmplist *) NULL);
951 jump_resolve(true_list, here);
952 true_list = jlist;
953 code_instr(I_PUSH_ONE, 0);
954 jump_resolve(j2list, here);
955 } else {
956 jlist = false_list;
957 false_list = (jmplist *) NULL;
958 cg_cond(n->l.left, FALSE);
959 cg_expr(n->r.right, TRUE);
960 jump_resolve(false_list, here);
961 false_list = jlist;
962 }
963 return;
964
965 case N_LE:
966 cg_expr(n->l.left, FALSE);
967 cg_expr(n->r.right, FALSE);
968 code_kfun(KF_LE, n->line);
969 break;
970
971 case N_LE_INT:
972 cg_expr(n->l.left, FALSE);
973 cg_expr(n->r.right, FALSE);
974 code_kfun(KF_LE_INT, n->line);
975 break;
976
977 case N_LOCAL:
978 code_instr(I_PUSH_LOCAL, n->line);
979 code_byte(nparams - (int) n->r.number - 1);
980 break;
981
982 case N_LOR:
983 if (!pop) {
984 jlist = false_list;
985 false_list = (jmplist *) NULL;
986 cg_cond(n, FALSE);
987 code_instr(I_PUSH_ONE, 0);
988 j2list = jump(I_JUMP, (jmplist *) NULL);
989 jump_resolve(false_list, here);
990 false_list = jlist;
991 code_instr(I_PUSH_ZERO, 0);
992 jump_resolve(j2list, here);
993 } else {
994 jlist = true_list;
995 true_list = (jmplist *) NULL;
996 cg_cond(n->l.left, TRUE);
997 cg_expr(n->r.right, TRUE);
998 jump_resolve(true_list, here);
999 true_list = jlist;
1000 }
1001 return;
1002
1003 case N_LSHIFT:
1004 cg_expr(n->l.left, FALSE);
1005 cg_expr(n->r.right, FALSE);
1006 code_kfun(KF_LSHIFT, n->line);
1007 break;
1008
1009 case N_LSHIFT_INT:
1010 cg_expr(n->l.left, FALSE);
1011 cg_expr(n->r.right, FALSE);
1012 code_kfun(KF_LSHIFT_INT, n->line);
1013 break;
1014
1015 case N_LSHIFT_EQ:
1016 cg_asgnop(n, KF_LSHIFT);
1017 break;
1018
1019 case N_LSHIFT_EQ_INT:
1020 cg_asgnop(n, KF_LSHIFT_INT);
1021 break;
1022
1023 case N_LT:
1024 cg_expr(n->l.left, FALSE);
1025 cg_expr(n->r.right, FALSE);
1026 code_kfun(KF_LT, n->line);
1027 break;
1028
1029 case N_LT_INT:
1030 cg_expr(n->l.left, FALSE);
1031 cg_expr(n->r.right, FALSE);
1032 code_kfun(KF_LT_INT, n->line);
1033 break;
1034
1035 case N_LVALUE:
1036 cg_lvalue(n->l.left, (n->l.left->mod != T_MIXED) ? n->l.left->mod : 0);
1037 break;
1038
1039 case N_MOD:
1040 cg_expr(n->l.left, FALSE);
1041 cg_expr(n->r.right, FALSE);
1042 code_kfun(KF_MOD, n->line);
1043 break;
1044
1045 case N_MOD_INT:
1046 cg_expr(n->l.left, FALSE);
1047 cg_expr(n->r.right, FALSE);
1048 code_kfun(KF_MOD_INT, n->line);
1049 break;
1050
1051 case N_MOD_EQ:
1052 cg_asgnop(n, KF_MOD);
1053 break;
1054
1055 case N_MOD_EQ_INT:
1056 cg_asgnop(n, KF_MOD_INT);
1057 break;
1058
1059 case N_MULT:
1060 cg_expr(n->l.left, FALSE);
1061 cg_expr(n->r.right, FALSE);
1062 code_kfun(KF_MULT, n->line);
1063 break;
1064
1065 case N_MULT_INT:
1066 cg_expr(n->l.left, FALSE);
1067 cg_expr(n->r.right, FALSE);
1068 code_kfun(KF_MULT_INT, n->line);
1069 break;
1070
1071 case N_MULT_EQ:
1072 cg_asgnop(n, KF_MULT);
1073 break;
1074
1075 case N_MULT_EQ_INT:
1076 cg_asgnop(n, KF_MULT_INT);
1077 break;
1078
1079 case N_NE:
1080 cg_expr(n->l.left, FALSE);
1081 cg_expr(n->r.right, FALSE);
1082 code_kfun(KF_NE, n->line);
1083 break;
1084
1085 case N_NE_INT:
1086 cg_expr(n->l.left, FALSE);
1087 cg_expr(n->r.right, FALSE);
1088 code_kfun(KF_NE_INT, n->line);
1089 break;
1090
1091 case N_NIL:
1092 code_kfun(KF_NIL, n->line);
1093 break;
1094
1095 case N_NOT:
1096 cg_expr(n->l.left, FALSE);
1097 code_kfun((n->l.left->mod == T_INT) ? KF_NOT_INT : KF_NOT, n->line);
1098 break;
1099
1100 case N_OR:
1101 cg_expr(n->l.left, FALSE);
1102 cg_expr(n->r.right, FALSE);
1103 code_kfun(KF_OR, n->line);
1104 break;
1105
1106 case N_OR_INT:
1107 cg_expr(n->l.left, FALSE);
1108 cg_expr(n->r.right, FALSE);
1109 code_kfun(KF_OR_INT, n->line);
1110 break;
1111
1112 case N_OR_EQ:
1113 cg_asgnop(n, KF_OR);
1114 break;
1115
1116 case N_OR_EQ_INT:
1117 cg_asgnop(n, KF_OR_INT);
1118 break;
1119
1120 case N_QUEST:
1121 if (n->r.right->l.left != (node *) NULL) {
1122 jlist = false_list;
1123 false_list = (jmplist *) NULL;
1124 cg_cond(n->l.left, FALSE);
1125 cg_expr(n->r.right->l.left, pop);
1126 if (n->r.right->r.right != (node *) NULL) {
1127 j2list = jump(I_JUMP, (jmplist *) NULL);
1128 jump_resolve(false_list, here);
1129 false_list = jlist;
1130 cg_expr(n->r.right->r.right, pop);
1131 jump_resolve(j2list, here);
1132 } else {
1133 jump_resolve(false_list, here);
1134 false_list = jlist;
1135 }
1136 } else {
1137 jlist = true_list;
1138 true_list = (jmplist *) NULL;
1139 cg_cond(n->l.left, TRUE);
1140 if (n->r.right->r.right != (node *) NULL) {
1141 cg_expr(n->r.right->r.right, pop);
1142 }
1143 jump_resolve(true_list, here);
1144 true_list = jlist;
1145 }
1146 return;
1147
1148 case N_RANGE:
1149 cg_expr(n->l.left, FALSE);
1150 n = n->r.right;
1151 if (n->l.left != (node *) NULL) {
1152 cg_expr(n->l.left, FALSE);
1153 if (n->r.right != (node *) NULL) {
1154 cg_expr(n->r.right, FALSE);
1155 code_kfun(KF_RANGEFT, n->line);
1156 } else {
1157 code_kfun(KF_RANGEF, n->line);
1158 }
1159 } else if (n->r.right != (node *) NULL) {
1160 cg_expr(n->r.right, FALSE);
1161 code_kfun(KF_RANGET, n->line);
1162 } else {
1163 code_kfun(KF_RANGE, n->line);
1164 }
1165 break;
1166
1167 case N_RSHIFT:
1168 cg_expr(n->l.left, FALSE);
1169 cg_expr(n->r.right, FALSE);
1170 code_kfun(KF_RSHIFT, n->line);
1171 break;
1172
1173 case N_RSHIFT_INT:
1174 cg_expr(n->l.left, FALSE);
1175 cg_expr(n->r.right, FALSE);
1176 code_kfun(KF_RSHIFT_INT, n->line);
1177 break;
1178
1179 case N_RSHIFT_EQ:
1180 cg_asgnop(n, KF_RSHIFT);
1181 break;
1182
1183 case N_RSHIFT_EQ_INT:
1184 cg_asgnop(n, KF_RSHIFT_INT);
1185 break;
1186
1187 case N_STR:
1188 l = ctrl_dstring(n->l.string);
1189 if ((l & 0x01000000L) && (unsigned short) l < 256) {
1190 code_instr(I_PUSH_STRING, n->line);
1191 code_byte((int) l);
1192 } else if ((unsigned short) l < 256) {
1193 code_instr(I_PUSH_NEAR_STRING, n->line);
1194 code_byte((int) (l >> 16));
1195 code_byte((int) l);
1196 } else {
1197 code_instr(I_PUSH_FAR_STRING, n->line);
1198 code_byte((int) (l >> 16));
1199 code_word((int) l);
1200 }
1201 break;
1202
1203 case N_SUB:
1204 if ((n->l.left->type == N_INT && n->l.left->l.number == 0) ||
1205 (n->l.left->type == N_FLOAT && NFLT_ISZERO(n->l.left))) {
1206 cg_expr(n->r.right, FALSE);
1207 code_kfun(KF_UMIN, n->line);
1208 } else {
1209 cg_expr(n->l.left, FALSE);
1210 if (n->r.right->type == N_FLOAT) {
1211 if (NFLT_ISONE(n->r.right)) {
1212 code_kfun(KF_SUB1, n->line);
1213 break;
1214 }
1215 if (NFLT_ISMONE(n->r.right)) {
1216 code_kfun(KF_ADD1, n->line);
1217 break;
1218 }
1219 }
1220 cg_expr(n->r.right, FALSE);
1221 code_kfun(KF_SUB, n->line);
1222 }
1223 break;
1224
1225 case N_SUB_INT:
1226 if (n->l.left->type == N_INT && n->l.left->l.number == 0) {
1227 cg_expr(n->r.right, FALSE);
1228 code_kfun(KF_UMIN_INT, n->line);
1229 } else {
1230 cg_expr(n->l.left, FALSE);
1231 if (n->r.right->type == N_INT) {
1232 if (n->r.right->l.number == 1) {
1233 code_kfun(KF_SUB1_INT, n->line);
1234 break;
1235 }
1236 if (n->r.right->l.number == -1) {
1237 code_kfun(KF_ADD1_INT, n->line);
1238 break;
1239 }
1240 }
1241 cg_expr(n->r.right, FALSE);
1242 code_kfun(KF_SUB_INT, n->line);
1243 }
1244 break;
1245
1246 case N_SUB_EQ:
1247 cg_asgnop(n, KF_SUB);
1248 break;
1249
1250 case N_SUB_EQ_INT:
1251 cg_asgnop(n, KF_SUB_INT);
1252 break;
1253
1254 case N_SUB_EQ_1:
1255 cg_fetch(n->l.left);
1256 code_kfun(KF_SUB1, 0);
1257 code_instr(I_STORE, 0);
1258 break;
1259
1260 case N_SUB_EQ_1_INT:
1261 cg_fetch(n->l.left);
1262 code_kfun(KF_SUB1_INT, 0);
1263 code_instr(I_STORE, 0);
1264 break;
1265
1266 case N_SUM:
1267 i = cg_sumargs(n);
1268 code_kfun(KF_SUM, 0);
1269 code_byte(i);
1270 break;
1271
1272 case N_SUM_EQ:
1273 cg_fetch(n->l.left);
1274 code_instr(I_PUSH_INT1, 0);
1275 code_byte(-2);
1276 i = cg_sumargs(n->r.right) + 1;
1277 code_kfun(KF_SUM, 0);
1278 code_byte(i);
1279 code_instr(I_STORE, 0);
1280 break;
1281
1282 case N_TOFLOAT:
1283 cg_expr(n->l.left, FALSE);
1284 code_kfun(KF_TOFLOAT, n->line);
1285 break;
1286
1287 case N_TOINT:
1288 cg_expr(n->l.left, FALSE);
1289 code_kfun(KF_TOINT, n->line);
1290 break;
1291
1292 case N_TOSTRING:
1293 cg_expr(n->l.left, FALSE);
1294 code_kfun(KF_TOSTRING, n->line);
1295 break;
1296
1297 case N_TST:
1298 cg_expr(n->l.left, FALSE);
1299 code_kfun((n->l.left->mod == T_INT) ? KF_TST_INT : KF_TST, n->line);
1300 break;
1301
1302 case N_UPLUS:
1303 cg_expr(n->l.left, pop);
1304 return;
1305
1306 case N_XOR:
1307 if (n->r.right->type == N_INT && n->r.right->l.number == -1) {
1308 cg_expr(n->l.left, FALSE);
1309 code_kfun(KF_NEG, n->line);
1310 } else {
1311 cg_expr(n->l.left, FALSE);
1312 cg_expr(n->r.right, FALSE);
1313 code_kfun(KF_XOR, n->line);
1314 }
1315 break;
1316
1317 case N_XOR_INT:
1318 if (n->r.right->type == N_INT && n->r.right->l.number == -1) {
1319 cg_expr(n->l.left, FALSE);
1320 code_kfun(KF_NEG_INT, n->line);
1321 } else {
1322 cg_expr(n->l.left, FALSE);
1323 cg_expr(n->r.right, FALSE);
1324 code_kfun(KF_XOR_INT, n->line);
1325 }
1326 break;
1327
1328 case N_XOR_EQ:
1329 if (n->r.right->type == N_INT && n->r.right->l.number == -1) {
1330 cg_fetch(n->l.left);
1331 code_kfun(KF_NEG, 0);
1332 code_instr(I_STORE, 0);
1333 } else {
1334 cg_asgnop(n, KF_XOR);
1335 }
1336 break;
1337
1338 case N_XOR_EQ_INT:
1339 if (n->r.right->type == N_INT && n->r.right->l.number == -1) {
1340 cg_fetch(n->l.left);
1341 code_kfun(KF_NEG_INT, 0);
1342 code_instr(I_STORE, 0);
1343 } else {
1344 cg_asgnop(n, KF_XOR_INT);
1345 }
1346 break;
1347
1348 case N_MIN_MIN:
1349 cg_fetch(n->l.left);
1350 code_kfun(KF_SUB1, 0);
1351 code_instr(I_STORE, 0);
1352 code_kfun((n->mod == T_INT) ? KF_ADD1_INT : KF_ADD1, 0);
1353 break;
1354
1355 case N_MIN_MIN_INT:
1356 cg_fetch(n->l.left);
1357 code_kfun(KF_SUB1_INT, 0);
1358 code_instr(I_STORE, 0);
1359 code_kfun(KF_ADD1_INT, 0);
1360 break;
1361
1362 case N_PLUS_PLUS:
1363 cg_fetch(n->l.left);
1364 code_kfun(KF_ADD1, 0);
1365 code_instr(I_STORE, 0);
1366 code_kfun((n->mod == T_INT) ? KF_SUB1_INT : KF_SUB1, 0);
1367 break;
1368
1369 case N_PLUS_PLUS_INT:
1370 cg_fetch(n->l.left);
1371 code_kfun(KF_ADD1_INT, 0);
1372 code_instr(I_STORE, 0);
1373 code_kfun(KF_SUB1_INT, 0);
1374 break;
1375
1376 # ifdef DEBUG
1377 default:
1378 fatal("unknown expression type %d", n->type);
1379 # endif
1380 }
1381
1382 if (pop) {
1383 *last_instruction |= I_POP_BIT;
1384 }
1385 }
1386
1387 /*
1388 * NAME: codegen->cond()
1389 * DESCRIPTION: generate code for a condition
1390 */
1391 static void cg_cond(n, jmptrue)
1392 register node *n;
1393 register int jmptrue;
1394 {
1395 register jmplist *jlist;
1396
1397 for (;;) {
1398 switch (n->type) {
1399 case N_INT:
1400 if (jmptrue) {
1401 if (n->l.number != 0) {
1402 true_list = jump(I_JUMP, true_list);
1403 }
1404 } else if (n->l.number == 0) {
1405 false_list = jump(I_JUMP, false_list);
1406 }
1407 break;
1408
1409 case N_LAND:
1410 if (jmptrue) {
1411 jlist = false_list;
1412 false_list = (jmplist *) NULL;
1413 cg_cond(n->l.left, FALSE);
1414 cg_cond(n->r.right, TRUE);
1415 jump_resolve(false_list, here);
1416 false_list = jlist;
1417 } else {
1418 cg_cond(n->l.left, FALSE);
1419 cg_cond(n->r.right, FALSE);
1420 }
1421 break;
1422
1423 case N_LOR:
1424 if (!jmptrue) {
1425 jlist = true_list;
1426 true_list = (jmplist *) NULL;
1427 cg_cond(n->l.left, TRUE);
1428 cg_cond(n->r.right, FALSE);
1429 jump_resolve(true_list, here);
1430 true_list = jlist;
1431 } else {
1432 cg_cond(n->l.left, TRUE);
1433 cg_cond(n->r.right, TRUE);
1434 }
1435 break;
1436
1437 case N_NOT:
1438 jlist = true_list;
1439 true_list = false_list;
1440 false_list = jlist;
1441 cg_cond(n->l.left, !jmptrue);
1442 jlist = true_list;
1443 true_list = false_list;
1444 false_list = jlist;
1445 break;
1446
1447 case N_COMMA:
1448 cg_expr(n->l.left, TRUE);
1449 n = n->r.right;
1450 continue;
1451
1452 default:
1453 cg_expr(n, FALSE);
1454 if (jmptrue) {
1455 true_list = jump(I_JUMP_NONZERO | I_POP_BIT, true_list);
1456 } else {
1457 false_list = jump(I_JUMP_ZERO | I_POP_BIT, false_list);
1458 }
1459 break;
1460 }
1461 break;
1462 }
1463 }
1464
1465 typedef struct {
1466 Uint where; /* where to jump to */
1467 jmplist *jump; /* list of unresolved jumps */
1468 } case_label;
1469
1470 static case_label *switch_table; /* label table for current switch */
1471
1472 /*
1473 * NAME: codegen->switch_int()
1474 * DESCRIPTION: generate single label code for a switch statement
1475 */
1476 static void cg_switch_int(n)
1477 register node *n;
1478 {
1479 register node *m;
1480 register int i, size, sz;
1481 case_label *table;
1482
1483 /*
1484 * switch expression
1485 */
1486 cg_expr(n->r.right->l.left, FALSE);
1487
1488 /*
1489 * switch table
1490 */
1491 code_instr(I_SWITCH | I_POP_BIT, 0);
1492 code_byte(SWITCH_INT);
1493 m = n->l.left;
1494 size = n->mod;
1495 sz = n->r.right->mod;
1496 if (m->l.left == (node *) NULL) {
1497 /* explicit default */
1498 m = m->r.right;
1499 } else {
1500 /* implicit default */
1501 size++;
1502 }
1503 code_word(size);
1504 code_byte(sz);
1505
1506 table = switch_table;
1507 switch_table = ALLOCA(case_label, size);
1508 switch_table[0].jump = jump_addr((jmplist *) NULL);
1509 i = 1;
1510 do {
1511 register Int l;
1512
1513 l = m->l.left->l.number;
1514 switch (sz) {
1515 case 4:
1516 code_word((int) (l >> 16));
1517 case 2:
1518 code_word((int) l);
1519 break;
1520
1521 case 3:
1522 code_byte((int) (l >> 16));
1523 code_word((int) l);
1524 break;
1525
1526 case 1:
1527 code_byte((int) l);
1528 break;
1529 }
1530 switch_table[i++].jump = jump_addr((jmplist *) NULL);
1531 m = m->r.right;
1532 } while (i < size);
1533
1534 /*
1535 * generate code for body
1536 */
1537 cg_stmt(n->r.right->r.right);
1538
1539 /*
1540 * resolve jumps
1541 */
1542 if (size > n->mod) {
1543 /* default: across switch */
1544 switch_table[0].where = here;
1545 }
1546 for (i = 0; i < size; i++) {
1547 jump_resolve(switch_table[i].jump, switch_table[i].where);
1548 }
1549 AFREE(switch_table);
1550 switch_table = table;
1551 }
1552
1553 /*
1554 * NAME: codegen->switch_range()
1555 * DESCRIPTION: generate range label code for a switch statement
1556 */
1557 static void cg_switch_range(n)
1558 register node *n;
1559 {
1560 register node *m;
1561 register int i, size, sz;
1562 case_label *table;
1563
1564 /*
1565 * switch expression
1566 */
1567 cg_expr(n->r.right->l.left, FALSE);
1568
1569 /*
1570 * switch table
1571 */
1572 code_instr(I_SWITCH | I_POP_BIT, 0);
1573 code_byte(SWITCH_RANGE);
1574 m = n->l.left;
1575 size = n->mod;
1576 sz = n->r.right->mod;
1577 if (m->l.left == (node *) NULL) {
1578 /* explicit default */
1579 m = m->r.right;
1580 } else {
1581 /* implicit default */
1582 size++;
1583 }
1584 code_word(size);
1585 code_byte(sz);
1586
1587 table = switch_table;
1588 switch_table = ALLOCA(case_label, size);
1589 switch_table[0].jump = jump_addr((jmplist *) NULL);
1590 i = 1;
1591 do {
1592 register Int l;
1593
1594 l = m->l.left->l.number;
1595 switch (sz) {
1596 case 4:
1597 code_word((int) (l >> 16));
1598 case 2:
1599 code_word((int) l);
1600 break;
1601
1602 case 3:
1603 code_byte((int) (l >> 16));
1604 code_word((int) l);
1605 break;
1606
1607 case 1:
1608 code_byte((int) l);
1609 break;
1610 }
1611 l = m->l.left->r.number;
1612 switch (sz) {
1613 case 4:
1614 code_word((int) (l >> 16));
1615 case 2:
1616 code_word((int) l);
1617 break;
1618
1619 case 3:
1620 code_byte((int) (l >> 16));
1621 code_word((int) l);
1622 break;
1623
1624 case 1:
1625 code_byte((int) l);
1626 break;
1627 }
1628 switch_table[i++].jump = jump_addr((jmplist *) NULL);
1629 m = m->r.right;
1630 } while (i < size);
1631
1632 /*
1633 * generate code for body
1634 */
1635 cg_stmt(n->r.right->r.right);
1636
1637 /*
1638 * resolve jumps
1639 */
1640 if (size > n->mod) {
1641 /* default: across switch */
1642 switch_table[0].where = here;
1643 }
1644 for (i = 0; i < size; i++) {
1645 jump_resolve(switch_table[i].jump, switch_table[i].where);
1646 }
1647 AFREE(switch_table);
1648 switch_table = table;
1649 }
1650
1651 /*
1652 * NAME: codegen->switch_str()
1653 * DESCRIPTION: generate code for a string switch statement
1654 */
1655 static void cg_switch_str(n)
1656 register node *n;
1657 {
1658 register node *m;
1659 register int i, size;
1660 case_label *table;
1661
1662 /*
1663 * switch expression
1664 */
1665 cg_expr(n->r.right->l.left, FALSE);
1666
1667 /*
1668 * switch table
1669 */
1670 code_instr(I_SWITCH | I_POP_BIT, 0);
1671 code_byte(SWITCH_STRING);
1672 m = n->l.left;
1673 size = n->mod;
1674 if (m->l.left == (node *) NULL) {
1675 /* explicit default */
1676 m = m->r.right;
1677 } else {
1678 /* implicit default */
1679 size++;
1680 }
1681 code_word(size);
1682
1683 table = switch_table;
1684 switch_table = ALLOCA(case_label, size);
1685 switch_table[0].jump = jump_addr((jmplist *) NULL);
1686 i = 1;
1687 if (m->l.left->type == nil_node) {
1688 /*
1689 * nil
1690 */
1691 code_byte(0);
1692 switch_table[i++].jump = jump_addr((jmplist *) NULL);
1693 m = m->r.right;
1694 } else {
1695 /* no 0 case */
1696 code_byte(1);
1697 }
1698 while (i < size) {
1699 register Int l;
1700
1701 l = ctrl_dstring(m->l.left->l.string);
1702 code_byte((int) (l >> 16));
1703 code_word((int) l);
1704 switch_table[i++].jump = jump_addr((jmplist *) NULL);
1705 m = m->r.right;
1706 }
1707
1708 /*
1709 * generate code for body
1710 */
1711 cg_stmt(n->r.right->r.right);
1712
1713 /*
1714 * resolve jumps
1715 */
1716 if (size > n->mod) {
1717 /* default: across switch */
1718 switch_table[0].where = here;
1719 }
1720 for (i = 0; i < size; i++) {
1721 jump_resolve(switch_table[i].jump, switch_table[i].where);
1722 }
1723 AFREE(switch_table);
1724 switch_table = table;
1725 }
1726
1727 /*
1728 * NAME: codegen->stmt()
1729 * DESCRIPTION: generate code for a statement
1730 */
1731 static void cg_stmt(n)
1732 register node *n;
1733 {
1734 register node *m;
1735 register jmplist *jlist, *j2list;
1736 register Uint where;
1737
1738 while (n != (node *) NULL) {
1739 if (n->type == N_PAIR) {
1740 m = n->l.left;
1741 n = n->r.right;
1742 } else {
1743 m = n;
1744 n = (node *) NULL;
1745 }
1746 switch (m->type) {
1747 case N_BLOCK:
1748 if (m->mod == N_BREAK) {
1749 jlist = break_list;
1750 break_list = (jmplist *) NULL;
1751 cg_stmt(m->l.left);
1752 if (break_list != (jmplist *) NULL) {
1753 jump_resolve(break_list, here);
1754 }
1755 break_list = jlist;
1756 } else {
1757 jlist = continue_list;
1758 continue_list = (jmplist *) NULL;
1759 cg_stmt(m->l.left);
1760 if (continue_list != (jmplist *) NULL) {
1761 jump_resolve(continue_list, here);
1762 }
1763 continue_list = jlist;
1764 }
1765 break;
1766
1767 case N_BREAK:
1768 while (m->mod > 0) {
1769 code_instr(I_RETURN, 0);
1770 m->mod--;
1771 }
1772 break_list = jump(I_JUMP, break_list);
1773 break;
1774
1775 case N_CASE:
1776 switch_table[m->mod].where = here;
1777 cg_stmt(m->l.left);
1778 break;
1779
1780 case N_CONTINUE:
1781 while (m->mod > 0) {
1782 code_instr(I_RETURN, 0);
1783 m->mod--;
1784 }
1785 continue_list = jump(I_JUMP, continue_list);
1786 break;
1787
1788 case N_DO:
1789 where = here;
1790 cg_stmt(m->r.right);
1791 jlist = true_list;
1792 true_list = (jmplist *) NULL;
1793 cg_cond(m->l.left, TRUE);
1794 jump_resolve(true_list, where);
1795 true_list = jlist;
1796 break;
1797
1798 case N_FOR:
1799 if (m->r.right != (node *) NULL) {
1800 jlist = jump(I_JUMP, (jmplist *) NULL);
1801 where = here;
1802 cg_stmt(m->r.right);
1803 jump_resolve(jlist, here);
1804 } else {
1805 /* empty loop body */
1806 where = here;
1807 }
1808 jlist = true_list;
1809 true_list = (jmplist *) NULL;
1810 cg_cond(m->l.left, TRUE);
1811 jump_resolve(true_list, where);
1812 true_list = jlist;
1813 break;
1814
1815 case N_FOREVER:
1816 where = here;
1817 if (m->l.left != (node *) NULL) {
1818 cg_expr(m->l.left, TRUE);
1819 }
1820 cg_stmt(m->r.right);
1821 jump_resolve(jump(I_JUMP, (jmplist *) NULL), where);
1822 break;
1823
1824 case N_RLIMITS:
1825 cg_expr(m->l.left->l.left, FALSE);
1826 cg_expr(m->l.left->r.right, FALSE);
1827 code_instr(I_RLIMITS, 0);
1828 code_byte(m->mod);
1829 cg_stmt(m->r.right);
1830 if (!(m->flags & F_END)) {
1831 code_instr(I_RETURN, 0);
1832 }
1833 break;
1834
1835 case N_CATCH:
1836 jlist = jump(I_CATCH | I_POP_BIT, (jmplist *) NULL);
1837 cg_stmt(m->l.left);
1838 if (m->l.left->flags & F_END) {
1839 jump_resolve(jlist, here);
1840 if (m->r.right != (node *) NULL) {
1841 cg_stmt(m->r.right);
1842 }
1843 } else {
1844 code_instr(I_RETURN, 0);
1845 if (m->r.right != (node *) NULL) {
1846 j2list = jump(I_JUMP, (jmplist *) NULL);
1847 jump_resolve(jlist, here);
1848 cg_stmt(m->r.right);
1849 jump_resolve(j2list, here);
1850 } else {
1851 jump_resolve(jlist, here);
1852 }
1853 }
1854 break;
1855
1856 case N_IF:
1857 if (m->r.right->l.left != (node *) NULL &&
1858 m->r.right->l.left->mod == 0) {
1859 if (m->r.right->l.left->type == N_BREAK) {
1860 jlist = true_list;
1861 true_list = break_list;
1862 cg_cond(m->l.left, TRUE);
1863 break_list = true_list;
1864 true_list = jlist;
1865 if (m->r.right->r.right != (node *) NULL) {
1866 /* else */
1867 cg_stmt(m->r.right->r.right);
1868 }
1869 break;
1870 } else if (m->r.right->l.left->type == N_CONTINUE) {
1871 jlist = true_list;
1872 true_list = continue_list;
1873 cg_cond(m->l.left, TRUE);
1874 continue_list = true_list;
1875 true_list = jlist;
1876 if (m->r.right->r.right != (node *) NULL) {
1877 /* else */
1878 cg_stmt(m->r.right->r.right);
1879 }
1880 break;
1881 }
1882 }
1883 jlist = false_list;
1884 false_list = (jmplist *) NULL;
1885 cg_cond(m->l.left, FALSE);
1886 cg_stmt(m->r.right->l.left);
1887 if (m->r.right->r.right != (node *) NULL) {
1888 /* else */
1889 if (m->r.right->l.left != (node *) NULL &&
1890 (m->r.right->l.left->flags & F_END)) {
1891 jump_resolve(false_list, here);
1892 false_list = jlist;
1893 cg_stmt(m->r.right->r.right);
1894 } else {
1895 j2list = jump(I_JUMP, (jmplist *) NULL);
1896 jump_resolve(false_list, here);
1897 false_list = jlist;
1898 cg_stmt(m->r.right->r.right);
1899 jump_resolve(j2list, here);
1900 }
1901 } else {
1902 /* no else */
1903 jump_resolve(false_list, here);
1904 false_list = jlist;
1905 }
1906 break;
1907
1908 case N_PAIR:
1909 cg_stmt(m);
1910 break;
1911
1912 case N_POP:
1913 cg_expr(m->l.left, TRUE);
1914 break;
1915
1916 case N_RETURN:
1917 cg_expr(m->l.left, FALSE);
1918 while (m->mod > 0) {
1919 code_instr(I_RETURN, 0);
1920 m->mod--;
1921 }
1922 code_instr(I_RETURN, m->line);
1923 break;
1924
1925 case N_SWITCH_INT:
1926 cg_switch_int(m);
1927 break;
1928
1929 case N_SWITCH_RANGE:
1930 cg_switch_range(m);
1931 break;
1932
1933 case N_SWITCH_STR:
1934 cg_switch_str(m);
1935 break;
1936 }
1937 }
1938 }
1939
1940
1941 static int nfuncs; /* # functions generated */
1942
1943 /*
1944 * NAME: codegen->init()
1945 * DESCRIPTION: initialize the code generator
1946 */
1947 void cg_init(inherited)
1948 int inherited;
1949 {
1950 nfuncs = 0;
1951 }
1952
1953 /*
1954 * NAME: codegen->compiled()
1955 * DESCRIPTION: return FALSE to signal that the code is interpreted, and not
1956 * compiled
1957 */
1958 bool cg_compiled()
1959 {
1960 return FALSE;
1961 }
1962
1963 /*
1964 * NAME: codegen->function()
1965 * DESCRIPTION: generate code for a function
1966 */
1967 char *cg_function(fname, n, nvar, npar, depth, size)
1968 string *fname;
1969 node *n;
1970 int nvar, npar;
1971 unsigned int depth;
1972 unsigned short *size;
1973 {
1974 char *prog;
1975
1976 nparams = npar;
1977 cg_stmt(n);
1978 prog = code_make(depth + nvar - npar, nvar - npar, size);
1979 jump_make(prog + 5);
1980 nfuncs++;
1981
1982 return prog;
1983 }
1984
1985 /*
1986 * NAME: codegen->nfuncs()
1987 * DESCRIPTION: return the number of functions generated
1988 */
1989 int cg_nfuncs()
1990 {
1991 return nfuncs;
1992 }
1993
1994 /*
1995 * NAME: codegen->clear()
1996 * DESCRIPTION: clean up code generator
1997 */
1998 void cg_clear()
1999 {
2000 jump_clear();
2001 code_clear();
2002 }
2003
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.