switch.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* $Header$ */
  2. /* S W I T C H - S T A T E M E N T A D M I N I S T R A T I O N */
  3. #include "debug.h"
  4. #include "botch_free.h"
  5. #include "density.h"
  6. #include "idf.h"
  7. #include "label.h"
  8. #include "arith.h"
  9. #include "switch.h"
  10. #include "code.h"
  11. #include "storage.h"
  12. #include "assert.h"
  13. #include "expr.h"
  14. #include "type.h"
  15. #include "em.h"
  16. #define compact(nr, low, up) (nr != 0 && (up - low) / nr <= (DENSITY - 1))
  17. static struct switch_hdr *switch_stack = 0;
  18. code_startswitch(expr)
  19. struct expr *expr;
  20. {
  21. /* stack a new case header and fill in the necessary fields.
  22. */
  23. register label l_table = text_label();
  24. register label l_break = text_label();
  25. register struct switch_hdr *sh = new_switch_hdr();
  26. stat_stack(l_break, NO_LABEL);
  27. sh->sh_break = l_break;
  28. sh->sh_default = 0;
  29. sh->sh_table = l_table;
  30. sh->sh_nrofentries = 0;
  31. sh->sh_type = expr->ex_type; /* the expression switched */
  32. sh->sh_lowerbd = sh->sh_upperbd = (arith)0; /* ??? */
  33. sh->sh_entries = (struct case_entry *) 0; /* case-entry list */
  34. sh->next = switch_stack; /* push onto switch-stack */
  35. switch_stack = sh;
  36. code_expr(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
  37. /* evaluate the switch expr. */
  38. C_bra(l_table); /* goto start of switch_table */
  39. }
  40. code_endswitch()
  41. {
  42. register struct switch_hdr *sh = switch_stack;
  43. register label tablabel;
  44. register struct case_entry *ce, *tmp;
  45. if (sh->sh_default == 0) /* no default occurred yet */
  46. sh->sh_default = sh->sh_break;
  47. C_bra(sh->sh_break); /* skip the switch table now */
  48. C_ilb(sh->sh_table); /* switch table entry */
  49. tablabel = data_label(); /* the rom must have a label */
  50. C_ndlb(tablabel);
  51. C_rom_begin();
  52. C_co_ilb(sh->sh_default);
  53. if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
  54. /* CSA */
  55. register arith val;
  56. C_co_cst(sh->sh_lowerbd);
  57. C_co_cst(sh->sh_upperbd - sh->sh_lowerbd);
  58. ce = sh->sh_entries;
  59. for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
  60. ASSERT(ce);
  61. if (val == ce->ce_value) {
  62. C_co_ilb(ce->ce_label);
  63. ce = ce->next;
  64. }
  65. else
  66. C_co_ilb(sh->sh_default);
  67. }
  68. C_rom_end();
  69. C_lae_ndlb(tablabel, (arith)0); /* perform the switch */
  70. C_csa(sh->sh_type->tp_size);
  71. }
  72. else { /* CSB */
  73. C_co_cst((arith)sh->sh_nrofentries);
  74. for (ce = sh->sh_entries; ce; ce = ce->next) {
  75. /* generate the entries: value + prog.label */
  76. C_co_cst(ce->ce_value);
  77. C_co_ilb(ce->ce_label);
  78. }
  79. C_rom_end();
  80. C_lae_ndlb(tablabel, (arith)0); /* perform the switch */
  81. C_csb(sh->sh_type->tp_size);
  82. }
  83. C_ilb(sh->sh_break);
  84. switch_stack = sh->next; /* unstack the switch descriptor */
  85. /* free the allocated switch structure */
  86. for (ce = sh->sh_entries; ce; ce = tmp) {
  87. tmp = ce->next;
  88. free_case_entry(ce);
  89. }
  90. free_switch_hdr(sh);
  91. stat_unstack();
  92. }
  93. code_case(val)
  94. arith val;
  95. {
  96. register struct case_entry *ce;
  97. register struct switch_hdr *sh = switch_stack;
  98. if (sh == 0) {
  99. error("case statement not in switch");
  100. return;
  101. }
  102. ce = new_case_entry();
  103. C_ilb(ce->ce_label = text_label());
  104. ce->ce_value = val;
  105. if (sh->sh_entries == 0) {
  106. /* first case entry */
  107. ce->next = (struct case_entry *) 0;
  108. sh->sh_entries = ce;
  109. sh->sh_lowerbd = sh->sh_upperbd = ce->ce_value;
  110. sh->sh_nrofentries = 1;
  111. }
  112. else {
  113. /* second etc. case entry */
  114. /* find the proper place to put ce into the list */
  115. register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
  116. if (val < sh->sh_lowerbd)
  117. sh->sh_lowerbd = val;
  118. else
  119. if (val > sh->sh_upperbd)
  120. sh->sh_upperbd = val;
  121. while (c1 && c1->ce_value < ce->ce_value) {
  122. c2 = c1;
  123. c1 = c1->next;
  124. }
  125. /* At this point three cases are possible:
  126. 1: c1 != 0 && c2 != 0:
  127. insert ce somewhere in the middle
  128. 2: c1 != 0 && c2 == 0:
  129. insert ce right after the head
  130. 3: c1 == 0 && c2 != 0:
  131. append ce to last element
  132. The case c1 == 0 && c2 == 0 cannot occur!
  133. */
  134. if (c1) {
  135. if (c1->ce_value == ce->ce_value) {
  136. error("multiple case entry for value %ld",
  137. ce->ce_value);
  138. free_case_entry(ce);
  139. return;
  140. }
  141. if (c2) {
  142. ce->next = c2->next;
  143. c2->next = ce;
  144. }
  145. else {
  146. ce->next = sh->sh_entries;
  147. sh->sh_entries = ce;
  148. }
  149. }
  150. else {
  151. ASSERT(c2);
  152. ce->next = (struct case_entry *) 0;
  153. c2->next = ce;
  154. }
  155. (sh->sh_nrofentries)++;
  156. }
  157. }
  158. code_default()
  159. {
  160. register struct switch_hdr *sh = switch_stack;
  161. if (sh == 0) {
  162. error("default not in switch");
  163. return;
  164. }
  165. if (sh->sh_default != 0) {
  166. error("multiple entry for default in switch");
  167. return;
  168. }
  169. C_ilb(sh->sh_default = text_label());
  170. }