switch.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. /* $Id$ */
  6. /* 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 */
  7. #include "lint.h"
  8. #ifndef LINT
  9. #include <em.h>
  10. #else
  11. #include "l_em.h"
  12. #endif /* LINT */
  13. #include "debug.h"
  14. #include "botch_free.h"
  15. #include <alloc.h>
  16. #include "density.h"
  17. #include "Lpars.h"
  18. #include "idf.h"
  19. #include "label.h"
  20. #include <flt_arith.h>
  21. #include "arith.h"
  22. #include "switch.h"
  23. #include "code.h"
  24. #include "assert.h"
  25. #include "expr.h"
  26. #include "type.h"
  27. #include "sizes.h"
  28. #include "code_c.h"
  29. extern char options[];
  30. int density = DENSITY;
  31. compact(nr, low, up)
  32. arith low, up;
  33. {
  34. /* Careful! up - low might not fit in an arith. And then,
  35. the test "up-low < 0" might also not work to detect this
  36. situation! Or is this just a bug in the M68020/M68000?
  37. */
  38. arith diff = up - low;
  39. return (nr == 0 || (diff >= 0 && diff / nr <= (density - 1)));
  40. }
  41. static struct switch_hdr *switch_stack = 0;
  42. /* (EB 86.05.20) The following rules hold for switch statements:
  43. - the expression E in "switch(E)" shall have integral type (3.6.4.2)
  44. - the expression E in "case E:" is converted to the promoted type
  45. of the controlling expression
  46. For simplicity, we suppose int_size == word_size.
  47. */
  48. code_startswitch(expp)
  49. struct expr **expp;
  50. {
  51. /* Check the expression, stack a new case header and
  52. fill in the necessary fields.
  53. */
  54. register label l_table = text_label();
  55. register label l_break = text_label();
  56. register struct switch_hdr *sh = new_switch_hdr();
  57. int fund = any2arith(expp, SWITCH);
  58. /* INT, LONG, FLOAT, DOUBLE or LNGDBL */
  59. switch (fund) {
  60. case FLOAT:
  61. case DOUBLE:
  62. case LNGDBL:
  63. error("floating point type in switch");
  64. erroneous2int(expp);
  65. break;
  66. }
  67. stack_stmt(l_break, NO_LABEL);
  68. sh->sh_break = l_break;
  69. /* sh->sh_default = 0; */
  70. sh->sh_table = l_table;
  71. /* sh->sh_nrofentries = 0; */
  72. sh->sh_type = (*expp)->ex_type; /* the expression switched */
  73. /* sh->sh_entries = (struct case_entry *) 0; -- case-entry list */
  74. sh->sh_expr = *expp;
  75. #ifdef LINT
  76. code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
  77. #endif
  78. sh->next = switch_stack; /* push onto switch-stack */
  79. switch_stack = sh;
  80. C_bra(l_table); /* goto start of switch_table */
  81. }
  82. extern char *long2str();
  83. code_endswitch()
  84. {
  85. register struct switch_hdr *sh = switch_stack;
  86. register label tablabel;
  87. register struct case_entry *ce;
  88. arith size = sh->sh_type->tp_size;
  89. if (sh->sh_default == 0) /* no default occurred yet */
  90. sh->sh_default = sh->sh_break;
  91. #ifndef LINT
  92. C_bra(sh->sh_break); /* skip the switch table now */
  93. C_df_ilb(sh->sh_table); /* switch table entry */
  94. /* evaluate the switch expr. */
  95. code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
  96. if (sh->sh_nrofentries <= 1) {
  97. if (sh->sh_nrofentries) {
  98. load_cst(sh->sh_lowerbd, size);
  99. C_cms(size);
  100. C_zeq(sh->sh_entries->ce_label);
  101. }
  102. else C_asp(size);
  103. C_bra(sh->sh_default);
  104. }
  105. else {
  106. tablabel = data_label(); /* the rom must have a label */
  107. C_df_dlb(tablabel);
  108. C_rom_ilb(sh->sh_default);
  109. if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
  110. /* CSA */
  111. register arith val;
  112. C_rom_icon(long2str((long)sh->sh_lowerbd,10), size);
  113. C_rom_icon(long2str((long)(sh->sh_upperbd - sh->sh_lowerbd),10),
  114. size);
  115. ce = sh->sh_entries;
  116. for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
  117. ASSERT(ce);
  118. if (val == ce->ce_value) {
  119. C_rom_ilb(ce->ce_label);
  120. ce = ce->next;
  121. }
  122. else
  123. C_rom_ilb(sh->sh_default);
  124. }
  125. C_lae_dlb(tablabel, (arith)0); /* perform the switch */
  126. C_csa(size);
  127. }
  128. else { /* CSB */
  129. C_rom_icon(long2str((long)sh->sh_nrofentries,10),size);
  130. for (ce = sh->sh_entries; ce; ce = ce->next) {
  131. /* generate the entries: value + prog.label */
  132. C_rom_icon(long2str((long)ce->ce_value,10),size);
  133. C_rom_ilb(ce->ce_label);
  134. }
  135. C_lae_dlb(tablabel, (arith)0); /* perform the switch */
  136. C_csb(size);
  137. }
  138. }
  139. C_df_ilb(sh->sh_break);
  140. #endif
  141. switch_stack = sh->next; /* unstack the switch descriptor */
  142. for (ce = sh->sh_entries; ce;) { /* free allocated switch structure */
  143. register struct case_entry *tmp = ce->next;
  144. free_case_entry(ce);
  145. ce = tmp;
  146. }
  147. free_switch_hdr(sh);
  148. unstack_stmt();
  149. }
  150. code_case(expr)
  151. struct expr *expr;
  152. {
  153. register arith val;
  154. register struct case_entry *ce;
  155. register struct switch_hdr *sh = switch_stack;
  156. ASSERT(is_cp_cst(expr));
  157. if (sh == 0) {
  158. error("case statement not in switch");
  159. return;
  160. }
  161. if (expr->ex_flags & EX_ERROR) /* is probably 0 anyway */
  162. return;
  163. ch3cast(&expr, CASE, sh->sh_type);
  164. ce = new_case_entry();
  165. C_df_ilb(ce->ce_label = text_label());
  166. ce->ce_value = val = expr->VL_VALUE;
  167. if (sh->sh_entries == 0) { /* first case entry */
  168. /* ce->next = (struct case_entry *) 0; */
  169. sh->sh_entries = ce;
  170. sh->sh_lowerbd = sh->sh_upperbd = val;
  171. sh->sh_nrofentries = 1;
  172. }
  173. else { /* second etc. case entry; put ce into proper place */
  174. register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
  175. if (val < sh->sh_lowerbd)
  176. sh->sh_lowerbd = val;
  177. else
  178. if (val > sh->sh_upperbd)
  179. sh->sh_upperbd = val;
  180. while (c1 && c1->ce_value < ce->ce_value) {
  181. c2 = c1;
  182. c1 = c1->next;
  183. }
  184. /* At this point three cases are possible:
  185. 1: c1 != 0 && c2 != 0: insert ce somewhere in the middle
  186. 2: c1 != 0 && c2 == 0: insert ce right after the head
  187. 3: c1 == 0 && c2 != 0: append ce to last element
  188. The case c1 == 0 && c2 == 0 cannot occur, since
  189. the list is guaranteed to be non-empty.
  190. */
  191. if (c1) {
  192. if (c1->ce_value == ce->ce_value) {
  193. error("multiple case entry for value %ld",
  194. ce->ce_value);
  195. free_case_entry(ce);
  196. return;
  197. }
  198. if (c2) {
  199. ce->next = c2->next;
  200. c2->next = ce;
  201. }
  202. else {
  203. ce->next = sh->sh_entries;
  204. sh->sh_entries = ce;
  205. }
  206. }
  207. else {
  208. ASSERT(c2);
  209. ce->next = (struct case_entry *) 0;
  210. c2->next = ce;
  211. }
  212. (sh->sh_nrofentries)++;
  213. }
  214. }
  215. code_default()
  216. {
  217. register struct switch_hdr *sh = switch_stack;
  218. if (sh == 0) {
  219. error("default statement not in switch");
  220. return;
  221. }
  222. if (sh->sh_default != 0) {
  223. error("multiple entry for default in switch");
  224. return;
  225. }
  226. C_df_ilb(sh->sh_default = text_label());
  227. }