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