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".
5 /* $Id: switch.c,v 1.10 1994/06/27 08:02:54 ceriel Exp $ */
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 */
15 #include "botch_free.h"
21 #include <flt_arith.h>
30 extern char options[];
32 int density = DENSITY;
37 /* Careful! up - low might not fit in an arith. And then,
38 the test "up-low < 0" might also not work to detect this
39 situation! Or is this just a bug in the M68020/M68000?
41 arith diff = up - low;
43 return (nr == 0 || (diff >= 0 && diff / nr <= (density - 1)));
46 static struct switch_hdr *switch_stack = 0;
48 /* (EB 86.05.20) The following rules hold for switch statements:
49 - the expression E in "switch(E)" shall have integral type (3.6.4.2)
50 - the expression E in "case E:" is converted to the promoted type
51 of the controlling expression
52 For simplicity, we suppose int_size == word_size.
55 code_startswitch(expp)
58 /* Check the expression, stack a new case header and
59 fill in the necessary fields.
61 register label l_table = text_label();
62 register label l_break = text_label();
63 register struct switch_hdr *sh = new_switch_hdr();
64 int fund = any2arith(expp, SWITCH);
65 /* INT, LONG, FLOAT, DOUBLE or LNGDBL */
71 error("floating point type in switch");
75 stack_stmt(l_break, NO_LABEL);
76 sh->sh_break = l_break;
77 /* sh->sh_default = 0; */
78 sh->sh_table = l_table;
79 /* sh->sh_nrofentries = 0; */
80 sh->sh_type = (*expp)->ex_type; /* the expression switched */
81 /* sh->sh_entries = (struct case_entry *) 0; /* case-entry list */
84 code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
86 sh->next = switch_stack; /* push onto switch-stack */
88 C_bra(l_table); /* goto start of switch_table */
91 extern char *long2str();
95 register struct switch_hdr *sh = switch_stack;
96 register label tablabel;
97 register struct case_entry *ce;
98 arith size = sh->sh_type->tp_size;
100 if (sh->sh_default == 0) /* no default occurred yet */
101 sh->sh_default = sh->sh_break;
104 C_bra(sh->sh_break); /* skip the switch table now */
105 C_df_ilb(sh->sh_table); /* switch table entry */
106 /* evaluate the switch expr. */
107 code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
108 if (sh->sh_nrofentries <= 1) {
109 if (sh->sh_nrofentries) {
110 load_cst(sh->sh_lowerbd, size);
112 C_zeq(sh->sh_entries->ce_label);
115 C_bra(sh->sh_default);
118 tablabel = data_label(); /* the rom must have a label */
120 C_rom_ilb(sh->sh_default);
121 if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
125 C_rom_icon(long2str((long)sh->sh_lowerbd,10), size);
126 C_rom_icon(long2str((long)(sh->sh_upperbd - sh->sh_lowerbd),10),
129 for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
131 if (val == ce->ce_value) {
132 C_rom_ilb(ce->ce_label);
136 C_rom_ilb(sh->sh_default);
138 C_lae_dlb(tablabel, (arith)0); /* perform the switch */
142 C_rom_icon(long2str((long)sh->sh_nrofentries,10),size);
143 for (ce = sh->sh_entries; ce; ce = ce->next) {
144 /* generate the entries: value + prog.label */
145 C_rom_icon(long2str((long)ce->ce_value,10),size);
146 C_rom_ilb(ce->ce_label);
148 C_lae_dlb(tablabel, (arith)0); /* perform the switch */
152 C_df_ilb(sh->sh_break);
155 switch_stack = sh->next; /* unstack the switch descriptor */
156 for (ce = sh->sh_entries; ce;) { /* free allocated switch structure */
157 register struct case_entry *tmp = ce->next;
170 register struct case_entry *ce;
171 register struct switch_hdr *sh = switch_stack;
173 ASSERT(is_cp_cst(expr));
175 error("case statement not in switch");
178 if (expr->ex_flags & EX_ERROR) /* is probably 0 anyway */
180 ch3cast(&expr, CASE, sh->sh_type);
181 ce = new_case_entry();
182 C_df_ilb(ce->ce_label = text_label());
183 ce->ce_value = val = expr->VL_VALUE;
184 if (sh->sh_entries == 0) { /* first case entry */
185 /* ce->next = (struct case_entry *) 0; */
187 sh->sh_lowerbd = sh->sh_upperbd = val;
188 sh->sh_nrofentries = 1;
190 else { /* second etc. case entry; put ce into proper place */
191 register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
193 if (val < sh->sh_lowerbd)
194 sh->sh_lowerbd = val;
196 if (val > sh->sh_upperbd)
197 sh->sh_upperbd = val;
198 while (c1 && c1->ce_value < ce->ce_value) {
202 /* At this point three cases are possible:
203 1: c1 != 0 && c2 != 0: insert ce somewhere in the middle
204 2: c1 != 0 && c2 == 0: insert ce right after the head
205 3: c1 == 0 && c2 != 0: append ce to last element
206 The case c1 == 0 && c2 == 0 cannot occur, since
207 the list is guaranteed to be non-empty.
210 if (c1->ce_value == ce->ce_value) {
211 error("multiple case entry for value %ld",
221 ce->next = sh->sh_entries;
227 ce->next = (struct case_entry *) 0;
230 (sh->sh_nrofentries)++;
236 register struct switch_hdr *sh = switch_stack;
239 error("default statement not in switch");
242 if (sh->sh_default != 0) {
243 error("multiple entry for default in switch");
247 C_df_ilb(sh->sh_default = text_label());