shc.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * This file contains the main part of the stackheight computation phase.
  3. *
  4. * Author: Hans van Eck.
  5. */
  6. #include <stdio.h>
  7. #include <em_spec.h>
  8. #include <em_mnem.h>
  9. #include <em_pseu.h>
  10. #include "param.h"
  11. #include "assert.h"
  12. #include "types.h"
  13. #include "shc.h"
  14. #include "alloc.h"
  15. #include "proinf.h"
  16. #include "line.h"
  17. #include "ext.h"
  18. #include "pop_push.h"
  19. extern char *pop_push[];
  20. extern char flow_tab[];
  21. #define NON_CONTINUABLE(i) (flow_tab[i]&JUMP)
  22. #define ISABRANCH(i) (flow_tab[i]&HASLABEL)
  23. #define ISCONDBRANCH(i) (flow_tab[i]&CONDBRA)
  24. lblst_p est_list = NULL;
  25. #define INSTR(lnp) (lnp->l_instr & BMASK)
  26. #define TYPE(lnp) lnp->l_optyp
  27. #define PREV(lnp) lnp->l_prev
  28. #define SHORT(lnp) lnp->l_a.la_short
  29. #define MINI(lnp) ((lnp->l_optyp & BMASK) - Z_OPMINI)
  30. #define IS_MINI(lnp) (lnp->l_optyp >= OPMINI)
  31. #define IS_LOC(l) (l!=(line_p) 0 && INSTR(l)==op_loc && IS_MINI(l))
  32. int state;
  33. static int stack_height = 0;
  34. init_state()
  35. {
  36. stack_height = 0;
  37. change_state(KNOWN);
  38. est_list = NULL;
  39. }
  40. shc_pseudos()
  41. {
  42. register line_p lp;
  43. for (lp = pseudos; lp != (line_p)0; lp = lp->l_next) {
  44. switch(INSTR(lp)) {
  45. case ps_con:
  46. case ps_rom:
  47. if (lp->l_optyp == OPLIST) {
  48. register arg_p ap = lp->l_a.la_arg;
  49. while (ap != (arg_p) 0) {
  50. if (ap->a_typ == ARGNUM) {
  51. assign_label(ap->a_a.a_np->n_repl);
  52. }
  53. ap = ap->a_next;
  54. }
  55. } else if (lp->l_optyp == OPNUMLAB)
  56. assign_label(lp->l_a.la_np->n_repl);
  57. }
  58. }
  59. }
  60. shc_instr(lnp)
  61. line_p lnp;
  62. {
  63. char *s;
  64. register instr = INSTR(lnp);
  65. register int mult, arg, argdef;
  66. line_p x = PREV(lnp);
  67. line_p y = (x == (line_p) 0 ? (line_p) 0 : PREV(x));
  68. if (state == NO_STACK_MES) return;
  69. if ( instr == op_lab) {
  70. do_inst_label(lnp);
  71. return;
  72. }
  73. if (instr < sp_fmnem || instr > sp_lmnem) {
  74. return;
  75. }
  76. if(state == NOTREACHED) return; /* What else ? */
  77. s = pop_push[instr];
  78. if (*s != '0')
  79. while (*s != '\0') {
  80. if (*s++ == '-') mult = -1;
  81. else mult = 1;
  82. if (TYPE(lnp) == OPSHORT) {
  83. arg = SHORT(lnp);
  84. if (arg < wordsize) arg = wordsize;
  85. argdef = TRUE;
  86. } else if (IS_MINI(lnp)) {
  87. arg = MINI(lnp);
  88. if (arg > 0 && arg < wordsize) arg = wordsize;
  89. if (arg < 0 && -arg < wordsize) arg = -wordsize;
  90. argdef = TRUE;
  91. } else argdef = FALSE;
  92. switch (*s++) {
  93. case 'w': stack_height += mult * wordsize; break;
  94. case 'd': stack_height += mult * wordsize * 2; break;
  95. case 'p': stack_height += mult * pointersize; break;
  96. case 'a':
  97. if (argdef == FALSE || instr == op_ass) {
  98. change_state(NO_STACK_MES);
  99. return;
  100. }
  101. stack_height += mult * arg;
  102. break;
  103. case 'x':
  104. if (IS_LOC(x)) {
  105. arg = MINI(x);
  106. if (arg < wordsize) arg = wordsize;
  107. stack_height += mult * arg;
  108. break;
  109. }
  110. change_state(NO_STACK_MES);
  111. return;
  112. case 'y':
  113. if (IS_LOC(y)) {
  114. arg = MINI(y);
  115. if (arg < wordsize) arg = wordsize;
  116. stack_height += mult * arg;
  117. break;
  118. }
  119. change_state(NO_STACK_MES);
  120. return;
  121. case '?':
  122. /* Actually, the effect of a ret on the stack is
  123. * known, but it has a '?' anyway. I think this
  124. * should be changed in ~etc/em_table
  125. */
  126. if (instr == op_ret)
  127. break;
  128. change_state(NO_STACK_MES);
  129. return;
  130. default:
  131. assert(FALSE);
  132. }
  133. }
  134. if (ISABRANCH(instr)) do_inst_label(lnp);
  135. if (NON_CONTINUABLE(instr)) change_state(NOTREACHED);
  136. }
  137. change_state(mode)
  138. int mode;
  139. {
  140. state = mode;
  141. if (mode != KNOWN) stack_height = 0;
  142. }
  143. delete_labels()
  144. {
  145. register lblst_p tmp;
  146. while ((tmp = est_list) != NULL) {
  147. est_list = est_list->ll_next;
  148. oldlblst(tmp);
  149. }
  150. }
  151. inst_old_label(lst_elt)
  152. register lblst_p lst_elt;
  153. {
  154. if (state != NOTREACHED) {
  155. if (stack_height < 0 || lst_elt->ll_height != stack_height) {
  156. change_state(NO_STACK_MES);
  157. }
  158. } else { /* after a label */
  159. stack_height = lst_elt->ll_height;
  160. }
  161. }
  162. inst_new_label(label)
  163. register num_p label;
  164. {
  165. register lblst_p lst_elt;
  166. lst_elt = newlblst();
  167. lst_elt->ll_next = est_list;
  168. lst_elt->ll_num = label;
  169. lst_elt->ll_height = stack_height;
  170. est_list = lst_elt;
  171. label->n_lst_elt = lst_elt;
  172. label->n_flags |= NUMSET;
  173. }
  174. assign_label(label)
  175. num_p label;
  176. {
  177. if (label->n_flags & NUMSET)
  178. inst_old_label(label->n_lst_elt);
  179. else inst_new_label(label);
  180. }
  181. do_inst_label(lnp) /* (re-)install a label */
  182. line_p lnp;
  183. {
  184. num_p label = lnp->l_a.la_np->n_repl;
  185. int instr = INSTR(lnp);
  186. assign_label(label);
  187. if (instr == op_lab) {
  188. if (state == NOTREACHED) {
  189. label->n_lst_elt->ll_fallthrough = FALSE;
  190. } else {
  191. label->n_lst_elt->ll_fallthrough = TRUE;
  192. }
  193. } else if (ISCONDBRANCH(instr)) { /* conditional branch */
  194. label->n_flags |= NUMCOND;
  195. }
  196. if (state != NO_STACK_MES) change_state(KNOWN);
  197. }