casestat.C 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /* C A S E S T A T E M E N T C O D E G E N E R A T I O N */
  2. #include "debug.h"
  3. #include <alloc.h>
  4. #include <assert.h>
  5. #include <em.h>
  6. #include "LLlex.h"
  7. #include "Lpars.h"
  8. #include "chk_expr.h"
  9. #include "density.h"
  10. #include "main.h"
  11. #include "node.h"
  12. #include "type.h"
  13. struct case_hdr {
  14. struct case_hdr *ch_next; /* in the free list */
  15. int ch_nrofentries; /* number of cases */
  16. struct type *ch_type; /* type of case expression */
  17. arith ch_lowerbd; /* lowest case label */
  18. arith ch_upperbd; /* highest case label */
  19. struct case_entry *ch_entries; /* the cases */
  20. };
  21. /* ALLOCDEF "case_hdr" 5 */
  22. struct case_entry {
  23. struct case_entry *ce_next; /* next in list */
  24. arith ce_value; /* value of case label */
  25. label ce_label; /* generated label */
  26. };
  27. /* ALLOCDEF "case_entry" 10 */
  28. /* The constant DENSITY determines when CSA and when CSB instructions
  29. are generated. Reasonable values are: 2, 3, 4.
  30. On machines that have lots of address space and memory, higher values
  31. might also be reasonable. On these machines the density of jump tables
  32. may be lower.
  33. */
  34. #define compact(nr, low, up) (nr != 0 && (up - low) / nr <= DENSITY)
  35. CaseExpr(nd)
  36. struct node *nd;
  37. {
  38. /* Check the expression and generate code for it
  39. */
  40. register struct node *expp = nd->nd_left;
  41. if( !ChkExpression(expp) ) return;
  42. MarkUsed(expp);
  43. if( !(expp->nd_type->tp_fund & T_ORDINAL) ) {
  44. node_error(expp, "case-expression must be ordinal");
  45. return;
  46. }
  47. if( !err_occurred ) {
  48. CodePExpr(expp);
  49. C_bra(nd->nd_lab);
  50. }
  51. }
  52. CaseEnd(nd, exit_label)
  53. struct node *nd;
  54. label exit_label;
  55. {
  56. /* Stack a new case header and fill in the necessary fields.
  57. */
  58. register struct case_hdr *ch = new_case_hdr();
  59. register struct node *right;
  60. assert(nd->nd_class == Link && nd->nd_symb == CASE);
  61. ch->ch_type = nd->nd_left->nd_type;
  62. right = nd->nd_right;
  63. /* Now, create case label list
  64. */
  65. while( right ) {
  66. assert(right->nd_class == Link && right->nd_symb == ':');
  67. if( !AddCases(ch, right->nd_left, right->nd_lab) ) {
  68. FreeCh(ch);
  69. return;
  70. }
  71. right = right->nd_right;
  72. }
  73. if( !err_occurred )
  74. CaseCode(nd->nd_lab, ch, exit_label);
  75. FreeCh(ch);
  76. FreeNode(nd);
  77. }
  78. FreeCh(ch)
  79. register struct case_hdr *ch;
  80. {
  81. /* free the allocated case structure
  82. */
  83. register struct case_entry *ce;
  84. ce = ch->ch_entries;
  85. while( ce ) {
  86. struct case_entry *tmp = ce->ce_next;
  87. free_case_entry(ce);
  88. ce = tmp;
  89. }
  90. free_case_hdr(ch);
  91. }
  92. AddCases(ch, nd, CaseLabel)
  93. register struct case_hdr *ch;
  94. register struct node *nd;
  95. label CaseLabel;
  96. {
  97. while( nd ) {
  98. if( !AddOneCase(ch, nd, CaseLabel) )
  99. return 0;
  100. nd = nd->nd_next;
  101. }
  102. return 1;
  103. }
  104. AddOneCase(ch, nd, lbl)
  105. register struct case_hdr *ch;
  106. register struct node *nd;
  107. label lbl;
  108. {
  109. register struct case_entry *ce = new_case_entry();
  110. register struct case_entry *c1 = ch->ch_entries, *c2 = 0;
  111. ce->ce_value = nd->nd_INT;
  112. ce->ce_label = lbl;
  113. if( !TstCompat(ch->ch_type, nd->nd_type) ) {
  114. node_error(nd, "case-statement: type incompatibility in case");
  115. free_case_entry(ce);
  116. return 0;
  117. }
  118. if( bounded(ch->ch_type) ) {
  119. arith lo, hi;
  120. getbounds(ch->ch_type, &lo, &hi);
  121. if( ce->ce_value < lo || ce->ce_value > hi )
  122. warning("case-statement: constant out of bounds");
  123. }
  124. if( !ch->ch_entries ) {
  125. /* first case entry
  126. */
  127. ce->ce_next = (struct case_entry *) 0;
  128. ch->ch_entries = ce;
  129. ch->ch_lowerbd = ch->ch_upperbd = ce->ce_value;
  130. ch->ch_nrofentries = 1;
  131. }
  132. else {
  133. /* second etc. case entry
  134. find the proper place to put ce into the list
  135. */
  136. if( ce->ce_value < ch->ch_lowerbd )
  137. ch->ch_lowerbd = ce->ce_value;
  138. else if( ce->ce_value > ch->ch_upperbd )
  139. ch->ch_upperbd = ce->ce_value;
  140. while( c1 && c1->ce_value < ce->ce_value ) {
  141. c2 = c1;
  142. c1 = c1->ce_next;
  143. }
  144. /* At this point three cases are possible:
  145. 1: c1 != 0 && c2 != 0:
  146. insert ce somewhere in the middle
  147. 2: c1 != 0 && c2 == 0:
  148. insert ce right after the head
  149. 3: c1 == 0 && c2 != 0:
  150. append ce to last element
  151. The case c1 == 0 && c2 == 0 cannot occur, since
  152. the list is guaranteed not to be empty.
  153. */
  154. if( c1 ) {
  155. if( c1->ce_value == ce->ce_value ) {
  156. node_error(nd,
  157. "case-statement: multiple case entry");
  158. free_case_entry(ce);
  159. return 0;
  160. }
  161. if( c2 ) {
  162. ce->ce_next = c2->ce_next;
  163. c2->ce_next = ce;
  164. }
  165. else {
  166. ce->ce_next = ch->ch_entries;
  167. ch->ch_entries = ce;
  168. }
  169. }
  170. else {
  171. assert(c2);
  172. ce->ce_next = (struct case_entry *) 0;
  173. c2->ce_next = ce;
  174. }
  175. (ch->ch_nrofentries)++;
  176. }
  177. return 1;
  178. }
  179. CaseCode(lbl, ch, exit_label)
  180. label lbl;
  181. struct case_hdr *ch;
  182. label exit_label;
  183. {
  184. label CaseDescrLab = ++data_label; /* rom must have a label */
  185. register struct case_entry *ce;
  186. register arith val;
  187. C_df_dlb(CaseDescrLab);
  188. C_rom_icon("0", pointer_size);
  189. if( compact(ch->ch_nrofentries, ch->ch_lowerbd, ch->ch_upperbd) ) {
  190. /* CSA */
  191. C_rom_cst(ch->ch_lowerbd);
  192. C_rom_cst(ch->ch_upperbd - ch->ch_lowerbd);
  193. ce = ch->ch_entries;
  194. for( val = ch->ch_lowerbd; val <= ch->ch_upperbd; val++ ) {
  195. assert(ce);
  196. if( val == ce->ce_value ) {
  197. C_rom_ilb(ce->ce_label);
  198. ce = ce->ce_next;
  199. }
  200. else
  201. C_rom_icon("0", pointer_size);
  202. }
  203. C_df_ilb(lbl);
  204. C_lae_dlb(CaseDescrLab, (arith) 0);
  205. C_csa(word_size);
  206. }
  207. else {
  208. /* CSB */
  209. C_rom_cst((arith) ch->ch_nrofentries);
  210. for( ce = ch->ch_entries; ce; ce = ce->ce_next ) {
  211. C_rom_cst(ce->ce_value);
  212. C_rom_ilb(ce->ce_label);
  213. }
  214. C_df_ilb(lbl);
  215. C_lae_dlb(CaseDescrLab, (arith) 0);
  216. C_csb(word_size);
  217. }
  218. C_df_ilb(exit_label);
  219. }