ANALYZE.C
上传用户:hlzzc88
上传日期:2007-01-06
资源大小:220k
文件大小:20k
源码类别:

编译器/解释器

开发平台:

Others

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1997, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and either the original sources or derived sources 
  11.  * are distributed along with any executables derived from the originals.
  12.  *
  13.  * The author is not responsible for any damages that may arise from use
  14.  * of this software, either idirect or consequential.
  15.  *
  16.  * v1.35 March 1997
  17.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  18.  *
  19.  * Credits to Mathew Brandt for original K&R C compiler
  20.  *
  21.  */
  22. #include        <stdio.h>
  23. #include "list.h"
  24. #include        "expr.h"
  25. #include        "c.h"
  26. #include        "errors.h"
  27. #include  "diag.h"
  28. extern int cf_freeaddress,cf_freedata,cf_freefloat;
  29. extern long framedepth,stackdepth;
  30. extern LIST *varlisthead;
  31. extern int lc_maxauto;
  32. extern int stackadd, stackmod;
  33. int floatregs = 1,dataregs=1,addrregs = 1;
  34. CSE       *olist;         /* list of optimizable expressions */
  35. /*
  36.  *      this module will step through the parse tree and find all
  37.  *      optimizable expressions. at present these expressions are
  38.  *      limited to expressions that are valid throughout the scope
  39.  *      of the function. the list of optimizable expressions is:
  40.  *
  41.  *              constants
  42.  *              global and static addresses
  43.  *              auto addresses
  44.  *              contents of auto addresses.
  45.  *
  46.  *      contents of auto addresses are valid only if the address is
  47.  *      never referred to without dereferencing.
  48.  *
  49.  *      scan will build a list of optimizable expressions which
  50.  *      opt1 will replace during the second optimization pass.
  51.  */
  52. int equalnode(ENODE *node1, ENODE *node2)
  53. /*
  54.  *      equalnode will return 1 if the expressions pointed to by
  55.  *      node1 and node2 are equivalent.
  56.  */
  57. {       if( node1 == 0 || node2 == 0 )
  58.                 return 0;
  59.         if( node1->nodetype != node2->nodetype )
  60.                 return 0;
  61. if (natural_size(node1) != natural_size(node2))
  62. return 0;
  63.         if( (isintconst(node1->nodetype) || node1->nodetype == en_labcon ||
  64. node1->nodetype == en_autoreg || node1->nodetype == en_nalabcon ||
  65.             node1->nodetype == en_nacon || node1->nodetype == en_napccon
  66. || node1->nodetype == en_autocon || node1->nodetype == en_absacon) &&
  67.             node1->v.i == node2->v.i )
  68.                 return 1;
  69. if ((node1->nodetype==en_rcon ||node1->nodetype==en_lrcon ||node1->nodetype==en_fcon) && node1->v.f == node2->v.f)
  70. return 1;
  71.         if( lvalue(node1) && equalnode(node1->v.p[0], node2->v.p[0]) )
  72.                 return 1;
  73.         return 0;
  74. }
  75. CSE *searchnode(ENODE *node)
  76. /*
  77.  *      searchnode will search the common expression table for an entry
  78.  *      that matches the node passed and return a pointer to it.
  79.  */
  80. {       CSE     *csp;
  81.         csp = olist;
  82.         while( csp != 0 ) {
  83.                 if( equalnode(node,csp->exp) )
  84.                         return csp;
  85.                 csp = csp->next;
  86.                 }
  87.         return 0;
  88. }
  89. ENODE *copynode(ENODE *node)
  90. /*
  91.  *      copy the node passed into a new enode so it wont get
  92.  *      corrupted during substitution.
  93.  */
  94. {       ENODE    *temp;
  95.         if( node == 0 )
  96.                 return 0;
  97.         temp = xalloc(sizeof(ENODE));
  98. temp->cflags = node->cflags;
  99.         temp->nodetype = node->nodetype;
  100.         temp->v.p[0] = node->v.p[0];
  101.         temp->v.p[1] = node->v.p[1];
  102.         return temp;
  103. }
  104. CSE *enternode(ENODE *node,int duse,int size)
  105. /*
  106.  *      enternode will enter a reference to an expression node into the
  107.  *      common expression table. duse is a flag indicating whether or not
  108.  *      this reference will be dereferenced.
  109.  */
  110. {       CSE      *csp;
  111. if (size == 0)
  112. size = natural_size(node);
  113.         if( (csp = searchnode(node)) == 0 ) {   /* add to tree */
  114.                 csp = xalloc(sizeof(CSE));
  115.                 csp->next = olist;
  116.                 csp->uses = 1;
  117. csp->reg = -1;
  118.                 csp->duses = (duse != 0);
  119.                 csp->exp = copynode(node);
  120.                 csp->voidf = 0;
  121. csp->size = size;
  122.                 olist = csp;
  123.                 return csp;
  124.                 }
  125. else
  126. if (chksize(csp->size,size))
  127. csp->size = size;
  128.         ++(csp->uses);
  129.         if( duse )
  130.                 ++(csp->duses);
  131.         return csp;
  132. }
  133. CSE *voidauto(ENODE *node)
  134. /*
  135.  *      voidauto will void an auto dereference node which points to
  136.  *      the same auto constant as node.
  137.  */
  138. {       CSE      *csp;
  139.         csp = olist;
  140.         while( csp != 0 ) {
  141.                 if( lvalue(csp->exp) && equalnode(node,csp->exp->v.p[0]) ) {
  142.                         if( csp->voidf )
  143.                                 return 0;
  144.                         csp->voidf = 1;
  145.                         return csp;
  146.                         }
  147.                 csp = csp->next;
  148.                 }
  149.         return 0;
  150. }
  151. void voidall(void)
  152. /*
  153.  * Go through the CSP list voiding any use of a variable that
  154.  * has its address taken.
  155.  */
  156. {
  157. CSE *csp;
  158. csp = olist;
  159. while (csp) {
  160. if (csp->exp->nodetype == en_autocon || csp->exp->nodetype == en_autoreg) {
  161. CSE *two = voidauto(csp->exp);
  162. if (two) {
  163. csp->uses += two->duses;
  164. }
  165. }
  166. csp = csp->next;
  167. }
  168. }
  169. void scanexpr(ENODE *node, int duse,int size)
  170. /*
  171.  *      scanexpr will scan the expression pointed to by node for optimizable
  172.  *      subexpressions. when an optimizable expression is found it is entered
  173.  *      into the tree. if a reference to an autocon node is scanned the
  174.  *      corresponding auto dereferenced node will be voided. duse should be
  175.  *      set if the expression will be dereferenced.
  176.  */
  177. {       CSE      *csp, *csp1;
  178. int sz;
  179.         if( node == 0 )
  180.                 return;
  181.         switch( node->nodetype ) {
  182.                 case en_rcon: case en_lrcon: case en_fcon:
  183.                 case en_icon:
  184. case en_lcon:
  185. case en_iucon:
  186. case en_lucon:
  187. case en_ccon:
  188.                         enternode(node,duse,size);
  189.                         break;
  190.                 case en_napccon:
  191.                 case en_nacon:
  192. case en_absacon:
  193.                 case en_autocon:
  194.                 case en_autoreg:
  195.                         enternode(node,duse,4);
  196.                         break;
  197. case en_bits:
  198. scanexpr(node->v.p[0],duse,0);
  199. break;
  200. case en_floatref:
  201. case en_doubleref:
  202. case en_longdoubleref:
  203.                 case en_b_ref:
  204.                 case en_w_ref:
  205.                 case en_ul_ref:
  206.                 case en_l_ref:
  207.                 case en_ub_ref:
  208.                 case en_uw_ref:
  209. if (node->v.p[0]->nodetype == en_autocon ||
  210. node->v.p[0]->nodetype == en_autoreg)
  211. enternode(node,duse,size);
  212. else
  213.                           scanexpr(node->v.p[0],1,natural_size(node));
  214.                         break;
  215.                 case en_uminus:
  216.                 case en_compl:  case en_ainc:
  217.                 case en_adec:   case en_not:
  218.                         scanexpr(node->v.p[0],duse,0);
  219.                         break;
  220. case en_cb: case en_cub:
  221. case en_cw: case en_cuw:
  222. case en_cl: case en_cul:
  223. case en_cf: case en_cd: case en_cp: case en_cld:
  224.                         scanexpr(node->v.p[0],duse,natural_size(node));
  225.                         break;
  226.                 case en_asadd:  case en_assub:
  227. size = natural_size(node->v.p[0]);
  228.                         scanexpr(node->v.p[0],duse,0);
  229.                         scanexpr(node->v.p[1],duse,size);
  230.                         break;
  231.                 case en_add:    case en_sub:
  232.                         scanexpr(node->v.p[0],duse,0);
  233.                         scanexpr(node->v.p[1],duse,0);
  234.                         break;
  235. case en_asalsh: case en_asarsh: case en_alsh: case en_arsh:
  236.                 case en_asmul:  case en_asdiv:
  237.                 case en_asmod:  case en_aslsh:
  238. case en_asumod: case en_asudiv: case en_asumul:
  239.                 case en_asrsh:  case en_asand:
  240.                 case en_assign: case en_refassign:
  241. case en_asor:  case en_asxor:
  242. size = natural_size(node->v.p[0]);
  243.                         scanexpr(node->v.p[0],0,0);
  244.                         scanexpr(node->v.p[1],0,size);
  245.                         break;
  246. case en_void:
  247. case en_pmul: case en_pdiv:
  248.                 case en_mul:    case en_div:
  249.                 case en_umul:    case en_udiv: case en_umod:
  250.                 case en_lsh:    case en_rsh:
  251.                 case en_mod:    case en_and:
  252.                 case en_or:     case en_xor:
  253.                 case en_lor:    case en_land:
  254.                 case en_eq:     case en_ne:
  255.                 case en_gt:     case en_ge:
  256.                 case en_lt:     case en_le:
  257. case en_ugt: case en_uge: case en_ult: case en_ule:
  258.                 case en_cond:
  259. case en_moveblock: case en_stackblock: case en_callblock:
  260. case en_pcallblock:
  261.                         scanexpr(node->v.p[0],0,0);
  262.                         scanexpr(node->v.p[1],0,0);
  263.                         break;
  264.                 case en_fcall: case en_intcall: case en_fcallb:
  265. case en_pfcall: case en_pfcallb:
  266.                 case en_trapcall:
  267. /*                        scanexpr(node->v.p[0],1,0);
  268. */                        scanexpr(node->v.p[1],0,0);
  269.                         break;
  270.                 }
  271. }
  272. void scan(SNODE *block)
  273. /*
  274.  *      scan will gather all optimizable expressions into the expression
  275.  *      list for a block of statements.
  276.  */
  277. {       while( block != 0 ) {
  278.                 switch( block->stype ) {
  279.                         case st_return:
  280.                         case st_expr:
  281.                                 opt4(&block->exp);
  282.                                 scanexpr(block->exp,0,0);
  283.                                 break;
  284.                         case st_while:
  285.                         case st_do:
  286.                                 opt4(&block->exp);
  287.                                 scanexpr(block->exp,0,0);
  288.                                 scan(block->s1);
  289.                                 break;
  290.                         case st_for:
  291.                                 opt4(&block->label);
  292.                                 scanexpr(block->label,0,0);
  293.                                 opt4(&block->exp);
  294.                                 scanexpr(block->exp,0,0);
  295.                                 scan(block->s1);
  296.                                 opt4(&block->s2);
  297.                                 scanexpr(block->s2,0,0);
  298.                                 break;
  299.                         case st_if:
  300.                                 opt4(&block->exp);
  301.                                 scanexpr(block->exp,0,0);
  302.                                 scan(block->s1);
  303.                                 scan(block->s2);
  304.                                 break;
  305.                         case st_switch:
  306.                                 opt4(&block->exp);
  307.                                 scanexpr(block->exp,0,0);
  308.                                 scan(block->s1);
  309.                                 break;
  310.                         case st_case:
  311.                                 scan(block->s1);
  312.                                 break;
  313. case st_block:
  314. scan(block->exp);
  315. break;
  316. case st_asm:
  317. if (block->exp)
  318. asm_scan(block->exp);
  319. break;
  320.                         }
  321.                 block = block->next;
  322.                 }
  323. }
  324. void exchange(CSE **c1)
  325. /*
  326.  *      exchange will exchange the order of two expression entries
  327.  *      following c1 in the linked list.
  328.  */
  329. {       CSE      *csp1, *csp2;
  330.         csp1 = *c1;
  331.         csp2 = csp1->next;
  332.         csp1->next = csp2->next;
  333.         csp2->next = csp1;
  334.         *c1 = csp2;
  335. }
  336. int     desire(CSE *csp)
  337. /*
  338.  *      returns the desirability of optimization for a subexpression.
  339.  */
  340. {       if( csp->voidf || (isintconst(csp->exp->nodetype) &&
  341.                         csp->exp->v.i < 16 && csp->exp->v.i >= 0))
  342.                 return 0;
  343.         if( lvalue(csp->exp) )
  344.                 return 2 * csp->uses;
  345.         return csp->uses;
  346. }
  347. int     bsort(CSE **list)
  348. /*
  349.  *      bsort implements a bubble sort on the expression list.
  350.  */
  351. {       CSE      *csp1, *csp2;
  352.         csp1 = *list;
  353.         if( csp1 == 0 || csp1->next == 0 )
  354.                 return 0;
  355.         bsort( &(csp1->next));
  356.         csp2 = csp1->next;
  357.         if( desire(csp1) < desire(csp2) ) {
  358.                 exchange(list);
  359.                 return 1;
  360.                 }
  361.         return 0;
  362. }
  363. void repexpr(ENODE *node, int size)
  364. /*
  365.  *      repexpr will replace all allocated references within an expression
  366.  *      with tempref nodes.
  367.  */
  368. {       CSE      *csp;
  369.         if( node == 0 )
  370.                 return;
  371. if (size == 0)
  372. size = natural_size(node);
  373.         switch( node->nodetype ) {
  374.                 case en_rcon: case en_lrcon: case en_fcon:
  375.                 case en_icon:
  376. case en_lcon:
  377. case en_iucon:
  378. case en_lucon:
  379. case en_ccon:
  380.                 case en_nacon:
  381.                 case en_napccon:
  382. case en_absacon:
  383.                 case en_autocon:
  384. case en_autoreg:
  385.                         if( (csp = searchnode(node)) != 0 )
  386.                                 if( csp->reg > 0 ) {
  387.                                         node->nodetype = en_tempref;
  388.                                         node->v.i = csp->reg | (size << 8);
  389.                                         }
  390.                         break;
  391. case en_floatref:
  392. case en_doubleref:
  393. case en_longdoubleref:
  394.                 case en_ub_ref:
  395.                 case en_uw_ref:
  396.                 case en_b_ref:
  397.                 case en_w_ref:
  398.                 case en_l_ref:
  399.                 case en_ul_ref:
  400.                         if( (csp = searchnode(node)) != 0 ) {
  401.                                 if( csp->reg > 0 ) {
  402.                                         node->nodetype = en_tempref;
  403.                                         node->v.i = csp->reg | (size << 8);
  404.                                         }
  405.                                 else
  406.                                         repexpr(node->v.p[0],0);
  407.                                 }
  408.                         else
  409.                                 repexpr(node->v.p[0],0);
  410.                         break;
  411.                 case en_uminus: case en_bits:
  412.                 case en_not:    case en_compl:
  413.                 case en_ainc:   case en_adec:
  414.                         repexpr(node->v.p[0],0);
  415.                         break;
  416. case en_cb: case en_cub:
  417. case en_cw: case en_cuw:
  418. case en_cl: case en_cul:
  419. case en_cf: case en_cd: case en_cp: case en_cld:
  420.                         repexpr(node->v.p[0],natural_size(node));
  421.                         break;
  422.                 case en_add:    case en_sub:
  423.                 case en_umul:    case en_udiv: case en_umod:
  424.                 case en_mul:    case en_div:
  425.                 case en_mod:    case en_lsh:
  426. case en_asalsh: case en_asarsh: case en_alsh: case en_arsh:
  427.                 case en_rsh:    case en_and:
  428.                 case en_or:     case en_xor:
  429.                 case en_land:   case en_lor:
  430.                 case en_eq:     case en_ne:
  431.                 case en_lt:     case en_le:
  432. case en_ugt: case en_uge: case en_ult: case en_ule:
  433.                 case en_gt:     case en_ge:
  434.                 case en_cond:   case en_void:
  435.                 case en_asadd:  case en_assub:
  436.                 case en_asmul:  case en_asdiv:
  437.                 case en_asor:   case en_asand:   case en_asxor:
  438.                 case en_asmod:  case en_aslsh:
  439. case en_asumod: case en_asudiv: case en_asumul: case en_pmul:
  440.                 case en_asrsh:  case en_fcall: case en_trapcall: case en_pdiv:
  441. case en_pfcall: case en_pfcallb:
  442.                 case en_assign: case en_intcall: case en_fcallb: case en_refassign:
  443.                 case en_moveblock: case en_stackblock: case en_callblock:
  444. case en_pcallblock:
  445.                         repexpr(node->v.p[0],0);
  446.                         repexpr(node->v.p[1],0);
  447.                         break;
  448.                 }
  449. }
  450. void repcse(SNODE *block)
  451. /*
  452.  *      repcse will scan through a block of statements replacing the
  453.  *      optimized expressions with their temporary references.
  454.  */
  455. {       while( block != 0 ) {
  456.                 switch( block->stype ) {
  457.                         case st_return:
  458.                         case st_expr:
  459.                                 repexpr(block->exp,0);
  460.                                 break;
  461.                         case st_while:
  462.                         case st_do:
  463.                                 repexpr(block->exp,0);
  464.                                 repcse(block->s1);
  465.                                 break;
  466.                         case st_for:
  467.                                 repexpr(block->label,0);
  468.                                 repexpr(block->exp,0);
  469.                                 repcse(block->s1);
  470.                                 repexpr(block->s2,0);
  471.                                 break;
  472.                         case st_if:
  473.                                 repexpr(block->exp,0);
  474.                                 repcse(block->s1);
  475.                                 repcse(block->s2);
  476.                                 break;
  477.                         case st_switch:
  478.                                 repexpr(block->exp,0);
  479.                                 repcse(block->s1);
  480.                                 break;
  481.                         case st_case:
  482.                                 repcse(block->s1);
  483.                                 break;
  484. case st_block:
  485. repcse(block->exp);
  486. break;
  487. case st_asm:
  488. if (block->exp)
  489. asm_repcse(block->exp);
  490. break;
  491.                         }
  492.                 block = block->next;
  493.                 }
  494. }
  495. void allocstack(void)
  496. /*
  497.  * This allocates space for local variables
  498.  * we do this AFTER the register optimization so that we can
  499.  * avoid allocating space on the stack twice
  500.  */
  501. {
  502. int lvl = 0;
  503. int again = TRUE;
  504. int oldauto, max;
  505. lc_maxauto = max = 0;
  506. while (again) {
  507. LIST *t = varlisthead;
  508. int align;
  509. lvl ++;
  510. oldauto = max;
  511. again = FALSE;
  512. while (t) {
  513. SYM *sp = t->data;
  514. while (sp && (sp->inreg || sp->funcparm || sp->storage_class == sc_static || sp->storage_class == sc_label || sp->storage_class == sc_ulabel))
  515. sp = sp->next;
  516. if (!sp) {
  517. t = t->link;
  518. continue;
  519. }
  520. if (sp->value.i >= lvl)
  521. again = TRUE;
  522. if (sp->value.i == lvl) {
  523. lc_maxauto = oldauto;
  524. while (sp) {
  525. if (!sp->inreg && !sp->funcparm && sp->storage_class != sc_static) {
  526. int val;
  527. align = getalign(sc_auto,sp->tp);
  528. val = lc_maxauto % align;
  529. if (val != 0)
  530. lc_maxauto += align - val;
  531. lc_maxauto += sp->tp->size;
  532. sp->value.i = -lc_maxauto;
  533. }
  534. sp = sp->next;
  535. }
  536. }
  537. if (lc_maxauto > max)
  538. max = lc_maxauto;
  539. t = t->link;
  540. }
  541. }
  542. lc_maxauto = max;
  543. lc_maxauto += stackadd;
  544. lc_maxauto &= stackmod;
  545. }
  546. void opt1(SNODE *block)
  547. /*
  548.  *      opt1 is the externally callable optimization routine. it will
  549.  *      collect and allocate common subexpressions and substitute the
  550.  *      tempref for all occurrances of the expression within the block.
  551.  *
  552.  * optimizer is currently turned off...
  553.  */
  554. {
  555. int datareg = cf_freedata;
  556. int addreg = 16 + cf_freeaddress;
  557. int floatreg = 32 + cf_freefloat;
  558. olist = 0;
  559.         scan(block);            /* collect expressions */
  560. voidall(); /* Disallow regs whose address is taken  */
  561. voidfloat(block); /* disallow optimizing things which are assigned values derived from floats */
  562. reserveregs(&datareg, &addreg, &floatreg); /* Allocate register vars */
  563.         allocate(datareg, addreg,floatreg,block);             /* allocate registers  for opt*/
  564.         repcse(block);          /* replace allocated expressions */
  565. loadregs(); /* Initialize allocated regs */
  566. }