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 3.26 1994/06/24 12:06:27 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 */
16 #include "botch_free.h"
28 #include "noRoption.h"
30 extern char options[];
31 int density = DENSITY;
36 /* Careful! up - low might not fit in an arith. And then,
37 the test "up-low < 0" might also not work to detect this
38 situation! Or is this just a bug in the M68020/M68000?
40 arith diff = up - low;
42 return (nr == 0 || (diff >= 0 && diff / nr <= (density - 1)));
45 static struct switch_hdr *switch_stack = 0;
47 /* (EB 86.05.20) The following rules hold for switch statements:
48 - the expression E in "switch(E)" is cast to 'int' (RM 9.7)
49 - the expression E in "case E:" must be 'int' (RM 9.7)
50 - the values in the CSA/CSB tables are words (EM 7.4)
51 For simplicity, we suppose int_size == word_size.
54 code_startswitch(expp)
57 /* Check the expression, stack a new case header and
58 fill in the necessary fields.
60 register label l_table = text_label();
61 register label l_break = text_label();
62 register struct switch_hdr *sh = new_switch_hdr();
63 int fund = any2arith(expp, SWITCH); /* INT, LONG or DOUBLE */
69 warning("long in switch (cast to int)");
71 int2int(expp, int_type);
75 error("float/double in switch");
80 stack_stmt(l_break, NO_LABEL);
81 sh->sh_break = l_break;
83 sh->sh_table = l_table;
84 sh->sh_nrofentries = 0;
85 sh->sh_type = (*expp)->ex_type; /* the expression switched */
86 sh->sh_lowerbd = sh->sh_upperbd = (arith)0; /* immaterial ??? */
87 sh->sh_entries = (struct case_entry *) 0; /* case-entry list */
90 code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
92 sh->next = switch_stack; /* push onto switch-stack */
94 C_bra(l_table); /* goto start of switch_table */
99 register struct switch_hdr *sh = switch_stack;
100 register label tablabel;
101 register struct case_entry *ce;
103 if (sh->sh_default == 0) /* no default occurred yet */
104 sh->sh_default = sh->sh_break;
105 C_bra(sh->sh_break); /* skip the switch table now */
106 C_df_ilb(sh->sh_table); /* switch table entry */
107 /* evaluate the switch expr. */
109 code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
111 tablabel = data_label(); /* the rom must have a label */
113 C_rom_ilb(sh->sh_default);
114 if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
118 C_rom_cst(sh->sh_lowerbd);
119 C_rom_cst(sh->sh_upperbd - sh->sh_lowerbd);
121 if (sh->sh_nrofentries)
122 for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
124 if (val == ce->ce_value) {
125 C_rom_ilb(ce->ce_label);
129 C_rom_ilb(sh->sh_default);
131 C_lae_dlb(tablabel, (arith)0); /* perform the switch */
132 C_csa(sh->sh_type->tp_size);
135 C_rom_cst((arith)sh->sh_nrofentries);
136 for (ce = sh->sh_entries; ce; ce = ce->next) {
137 /* generate the entries: value + prog.label */
138 C_rom_cst(ce->ce_value);
139 C_rom_ilb(ce->ce_label);
141 C_lae_dlb(tablabel, (arith)0); /* perform the switch */
142 C_csb(sh->sh_type->tp_size);
144 C_df_ilb(sh->sh_break);
145 switch_stack = sh->next; /* unstack the switch descriptor */
146 for (ce = sh->sh_entries; ce;) { /* free allocated switch structure */
147 register struct case_entry *tmp = ce->next;
160 register struct case_entry *ce;
161 register struct switch_hdr *sh = switch_stack;
163 ASSERT(is_cp_cst(expr));
165 error("case statement not in switch");
168 if (expr->ex_flags & EX_ERROR) /* is probably 0 anyway */
170 ch7cast(&expr, CASE, sh->sh_type);
171 ce = new_case_entry();
172 C_df_ilb(ce->ce_label = text_label());
173 ce->ce_value = val = expr->VL_VALUE;
174 if (sh->sh_entries == 0) { /* first case entry */
175 ce->next = (struct case_entry *) 0;
177 sh->sh_lowerbd = sh->sh_upperbd = val;
178 sh->sh_nrofentries = 1;
180 else { /* second etc. case entry; put ce into proper place */
181 register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
183 if (val < sh->sh_lowerbd)
184 sh->sh_lowerbd = val;
186 if (val > sh->sh_upperbd)
187 sh->sh_upperbd = val;
188 while (c1 && c1->ce_value < ce->ce_value) {
192 /* At this point three cases are possible:
193 1: c1 != 0 && c2 != 0: insert ce somewhere in the middle
194 2: c1 != 0 && c2 == 0: insert ce right after the head
195 3: c1 == 0 && c2 != 0: append ce to last element
196 The case c1 == 0 && c2 == 0 cannot occur, since
197 the list is guaranteed to be non-empty.
200 if (c1->ce_value == ce->ce_value) {
201 error("multiple case entry for value %ld",
211 ce->next = sh->sh_entries;
217 ce->next = (struct case_entry *) 0;
220 (sh->sh_nrofentries)++;
226 register struct switch_hdr *sh = switch_stack;
229 error("default statement not in switch");
232 if (sh->sh_default != 0) {
233 error("multiple entry for default in switch");
237 C_df_ilb(sh->sh_default = text_label());