home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 338_02 / genstmt.c < prev    next >
Text File  |  1989-11-29  |  12KB  |  348 lines

  1. #include        <stdio.h>
  2. #include        "c.h"
  3. #include        "expr.h"
  4. #include        "gen.h"
  5. #include        "cglbdec.h"
  6.  
  7. /*
  8.  *    68000 C compiler
  9.  *
  10.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *  all commercial rights reserved.
  12.  *
  13.  *    This compiler is intended as an instructive tool for personal use. Any
  14.  *    use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *    This compiler may be distributed freely for non-commercial use as long
  17.  *    as this notice stays intact. Please forward any enhancements or questions
  18.  *    to:
  19.  *
  20.  *        Matthew Brandt
  21.  *        Box 920337
  22.  *        Norcross, Ga 30092
  23.  */
  24.  
  25. int     breaklab;
  26. int     contlab;
  27. int     retlab;
  28.  
  29. extern TYP              stdfunc;
  30. extern struct amode     push[], pop[];
  31.  
  32. struct amode    *makedreg(r) /* make an address reference to a data register. */
  33. int     r;
  34. {       struct amode    *ap;
  35.         ap = xalloc(sizeof(struct amode));
  36.         ap->mode = am_dreg;
  37.         ap->preg = r;
  38.         return ap;
  39. }
  40.  
  41. struct amode    *makeareg(r) /* make an address reference to an address register. */
  42. int     r;
  43. {       struct amode    *ap;
  44.         ap = xalloc(sizeof(struct amode));
  45.         ap->mode = am_areg;
  46.         ap->preg = r;
  47.         return ap;
  48. }
  49.  
  50. struct amode    *make_mask(mask) /* generate the mask address structure. */
  51. int     mask;
  52. {       struct amode    *ap;
  53.         ap = xalloc(sizeof(struct amode));
  54.         ap->mode = am_mask;
  55.         ap->offset = mask;
  56.         return ap;
  57. }
  58.  
  59. struct amode    *make_direct(i) /* make a direct reference to an immediate value. */
  60. int     i;
  61. {       return make_offset(makenode(en_icon,i,0));
  62. }
  63.  
  64. struct amode    *make_strlab(s) /* generate a direct reference to a string label. */
  65. char    *s;
  66. {       struct amode    *ap;
  67.         ap = xalloc(sizeof(struct amode));
  68.         ap->mode = am_direct;
  69.         ap->offset = makenode(en_nacon,s,0);
  70.         return ap;
  71. }
  72.  
  73. genwhile(stmt) /* generate code to evaluate a while statement. */
  74. struct snode    *stmt;
  75. {       int     lab1, lab2;
  76.         initstack();            /* initialize temp registers */
  77.         lab1 = contlab;         /* save old continue label */
  78.         lab2 = breaklab;        /* save old break label */
  79.         contlab = nextlabel++;  /* new continue label */
  80.         gen_label(contlab);
  81.         if( stmt->s1 != 0 )      /* has block */
  82.                 {
  83.                 breaklab = nextlabel++;
  84.                 initstack();
  85.                 falsejp(stmt->exp,breaklab);
  86.                 genstmt(stmt->s1);
  87.                 gen_code(op_bra,0,make_label(contlab),0);
  88.                 gen_label(breaklab);
  89.                 breaklab = lab2;        /* restore old break label */
  90.                 }
  91.         else                            /* no loop code */
  92.                 {
  93.                 initstack();
  94.                 truejp(stmt->exp,contlab);
  95.                 }
  96.         contlab = lab1;         /* restore old continue label */
  97. }
  98.  
  99. gen_for(stmt) /* generate code to evaluate a for loop */
  100. struct snode    *stmt;
  101. {       int     old_break, old_cont, exit_label, loop_label;
  102.         old_break = breaklab;
  103.         old_cont = contlab;
  104.         loop_label = nextlabel++;
  105.         exit_label = nextlabel++;
  106.         contlab = loop_label;
  107.         initstack();
  108.         if( stmt->label != 0 )
  109.                 gen_expr(stmt->label,F_ALL | F_NOVALUE
  110.                         ,natural_size(stmt->label));
  111.         gen_label(loop_label);
  112.         initstack();
  113.         if( stmt->exp != 0 )
  114.                 falsejp(stmt->exp,exit_label);
  115.         if( stmt->s1 != 0 )
  116.         {
  117.                 breaklab = exit_label;
  118.                 genstmt(stmt->s1);
  119.         }
  120.         initstack();
  121.         if( stmt->s2 != 0 )
  122.                 gen_expr(stmt->s2,F_ALL | F_NOVALUE,natural_size(stmt->s2));
  123.         gen_code(op_bra,0,make_label(loop_label),0);
  124.         breaklab = old_break;
  125.         contlab = old_cont;
  126.         gen_label(exit_label);
  127. }
  128.  
  129. genif(stmt) /* generate code to evaluate an if statement. */
  130. struct snode    *stmt;
  131. {       int     lab1, lab2, oldbreak;
  132.         lab1 = nextlabel++;     /* else label */
  133.         lab2 = nextlabel++;     /* exit label */
  134.         oldbreak = breaklab;    /* save break label */
  135.         initstack();            /* clear temps */
  136.         falsejp(stmt->exp,lab1);
  137.         if( stmt->s1 != 0 && stmt->s1->next != 0 )
  138.                 if( stmt->s2 != 0 )
  139.                         breaklab = lab2;
  140.                 else
  141.                         breaklab = lab1;
  142.         genstmt(stmt->s1);
  143.         if( stmt->s2 != 0 )             /* else part exists */
  144.                 {
  145.                 gen_code(op_bra,0,make_label(lab2),0);
  146.                 gen_label(lab1);
  147.                 if( stmt->s2 == 0 || stmt->s2->next == 0 )
  148.                         breaklab = oldbreak;
  149.                 else
  150.                         breaklab = lab2;
  151.                 genstmt(stmt->s2);
  152.                 gen_label(lab2);
  153.                 }
  154.         else                            /* no else code */
  155.                 gen_label(lab1);
  156.         breaklab = oldbreak;
  157. }
  158.  
  159. gendo(stmt) /* generate code for a do - while loop. */
  160. struct snode    *stmt;
  161. {       int     oldcont, oldbreak;
  162.         oldcont = contlab;
  163.         oldbreak = breaklab;
  164.         contlab = nextlabel++;
  165.         gen_label(contlab);
  166.         if( stmt->s1 != 0 && stmt->s1->next != 0 )
  167.                 {
  168.                 breaklab = nextlabel++;
  169.                 genstmt(stmt->s1);      /* generate body */
  170.                 initstack();
  171.                 truejp(stmt->exp,contlab);
  172.                 gen_label(breaklab);
  173.                 }
  174.         else
  175.                 {
  176.                 genstmt(stmt->s1);
  177.                 initstack();
  178.                 truejp(stmt->exp,contlab);
  179.                 }
  180.         breaklab = oldbreak;
  181.         contlab = oldcont;
  182. }
  183.  
  184. call_library(lib_name) /* generate a call to a library routine. */
  185. char    *lib_name;
  186. {       SYM     *sp;
  187.         sp = gsearch(lib_name);
  188.         if( sp == 0 )
  189.                 {
  190.                 ++global_flag;
  191.                 sp = xalloc(sizeof(SYM));
  192.                 sp->tp = &stdfunc;
  193.                 sp->name = lib_name;
  194.                 sp->storage_class = sc_external;
  195.                 insert(sp,&gsyms);
  196.                 --global_flag;
  197.                 }
  198.         gen_code(op_jsr,0,make_strlab(lib_name),0);
  199. }
  200.  
  201. genswitch(stmt) /* generate a linear search switch statement. */
  202. struct snode    *stmt;
  203. {       int             curlab;
  204.         struct snode    *defcase;
  205.         struct amode    *ap;
  206.         curlab = nextlabel++;
  207.         defcase = 0;
  208.         initstack();
  209.         ap = gen_expr(stmt->exp,F_DREG | F_VOL,4);
  210.         if( ap->preg != 0 )
  211.                 gen_code(op_move,4,ap,makedreg(0));
  212.         stmt = stmt->s1;
  213.         call_library("cswitch");
  214.         while( stmt != 0 )
  215.                 {
  216.                 if( stmt->s2 )          /* default case ? */
  217.                         {
  218.                         stmt->label = curlab;
  219.                         defcase = stmt;
  220.                         }
  221.                 else
  222.                         {
  223.                         gen_code(op_dc,4,make_label(curlab),
  224.                                 make_direct(stmt->label));
  225.                         stmt->label = curlab;
  226.                         }
  227.                 if( stmt->s1 != 0 && stmt->next != 0 )
  228.                         curlab = nextlabel++;
  229.                 stmt = stmt->next;
  230.                 }
  231.         if( defcase == 0 )
  232.                 gen_code(op_dc,4,make_direct(0),make_label(breaklab));
  233.         else
  234.                 gen_code(op_dc,4,make_direct(0),make_label(defcase->label));
  235. }
  236.  
  237. gencase(stmt) /* generate all cases for a switch statement. */
  238. struct snode    *stmt;
  239. {       while( stmt != 0 )
  240.                 {
  241.                 if( stmt->s1 != 0 )
  242.                         {
  243.                         gen_label(stmt->label);
  244.                         genstmt(stmt->s1);
  245.                         }
  246.                 else if( stmt->next == 0 )
  247.                         gen_label(stmt->label);
  248.                 stmt = stmt->next;
  249.                 }
  250. }
  251.  
  252. genxswitch(stmt) /* analyze and generate best switch statement. */
  253. struct snode    *stmt;
  254. {       int     oldbreak;
  255.         oldbreak = breaklab;
  256.         breaklab = nextlabel++;
  257.         genswitch(stmt);
  258.         gencase(stmt->s1);
  259.         gen_label(breaklab);
  260.         breaklab = oldbreak;
  261. }
  262.  
  263. genreturn(stmt) /* generate a return statement. */
  264. struct snode    *stmt;
  265. {       struct amode    *ap;
  266.         if( stmt != 0 && stmt->exp != 0 )
  267.                 {
  268.                 initstack();
  269.                 ap = gen_expr(stmt->exp,F_ALL,4);
  270.                 if( ap->mode != am_dreg || ap->preg != 0 )
  271.                         gen_code(op_move,4,ap,makedreg(0));
  272.                 }
  273.         if( retlab == -1 )
  274.                 {
  275.                 retlab = nextlabel++;
  276.                 gen_label(retlab);
  277.  
  278.                 if( save_mask != 0 )
  279.                         gen_code(op_movem,4,pop,make_mask(save_mask));
  280.  
  281.                 gen_code(op_unlk,0,makeareg(6),0);
  282.                 gen_code(op_rts,0,0,0);
  283.                 }
  284.         else
  285.                 gen_code(op_bra,0,make_label(retlab),0);
  286. }
  287.  
  288. genstmt(stmt)
  289. /* genstmt will generate a statement and follow the next pointer
  290.    until the block is generated.
  291. */
  292. struct snode    *stmt;
  293. {       while( stmt != 0 )
  294.                 {
  295.                 switch( stmt->stype )
  296.                         {
  297.                         case st_label:
  298.                                 gen_label(stmt->label);
  299.                                 break;
  300.                         case st_goto:
  301.                                 gen_code(op_bra,0,make_label(stmt->label),0);
  302.                                 break;
  303.                         case st_expr:
  304.                                 initstack();
  305.                                 gen_expr(stmt->exp,F_ALL | F_NOVALUE,
  306.                                         natural_size(stmt->exp));
  307.                                 break;
  308.                         case st_return:
  309.                                 genreturn(stmt);
  310.                                 break;
  311.                         case st_if:
  312.                                 genif(stmt);
  313.                                 break;
  314.                         case st_while:
  315.                                 genwhile(stmt);
  316.                                 break;
  317.                         case st_for:
  318.                                 gen_for(stmt);
  319.                                 break;
  320.                         case st_continue:
  321.                                 gen_code(op_bra,0,make_label(contlab),0);
  322.                                 break;
  323.                         case st_break:
  324.                                 gen_code(op_bra,0,make_label(breaklab),0);
  325.                                 break;
  326.                         case st_switch:
  327.                                 genxswitch(stmt);
  328.                                 break;
  329.                         default:
  330.                                 printf("DIAG - unknown statement.\n");
  331.                                 break;
  332.                         }
  333.                 stmt = stmt->next;
  334.                 }
  335. }
  336.  
  337. genfunc(stmt) /* generate a function body. */
  338. struct snode    *stmt;
  339. {       retlab = contlab = breaklab = -1;
  340.         if( lc_auto & 1 )    /* if frame size odd */
  341.             ++lc_auto;        /* make it even */
  342.         gen_code(op_link,0,makeareg(6),make_immed(-lc_auto));
  343.         opt1(stmt);
  344.         genstmt(stmt);
  345.         genreturn(0);
  346. }
  347.  
  348.