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