ArchWizard

DGD/

source navigation ]
diff markup ]
identifier search ]
file search ]
Version: [ 1.0.a0 ] [ 1.1 ] [ 1.2 ] [ 1.2p1 ] [ 1.2p2 ] [ 1.2p3 ] [ 1.2p4 ] [ 1.2.151 ]

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.