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 */
17 struct case_hdr *ch_next; /* in the free list */
18 int ch_nrofentries; /* number of cases */
19 struct type *ch_type; /* type of case expression */
20 arith ch_lowerbd; /* lowest case label */
21 arith ch_upperbd; /* highest case label */
22 struct case_entry *ch_entries; /* the cases */
25 /* ALLOCDEF "case_hdr" 5 */
28 struct case_entry *ce_next; /* next in list */
29 arith ce_value; /* value of case label */
30 label ce_label; /* generated label */
33 /* ALLOCDEF "case_entry" 10 */
35 /* The constant DENSITY determines when CSA and when CSB instructions
36 are generated. Reasonable values are: 2, 3, 4.
37 On machines that have lots of address space and memory, higher values
38 might also be reasonable. On these machines the density of jump tables
41 #define compact(nr, low, up) (nr != 0 && (up - low) / nr <= DENSITY)
46 /* Check the expression and generate code for it
49 register struct node *expp = nd->nd_left;
51 if( !ChkExpression(expp) ) return;
54 if( !(expp->nd_type->tp_fund & T_ORDINAL) ) {
55 node_error(expp, "case-expression must be ordinal");
65 CaseEnd(nd, exit_label)
69 /* Stack a new case header and fill in the necessary fields.
71 register struct case_hdr *ch = new_case_hdr();
72 register struct node *right;
74 assert(nd->nd_class == Link && nd->nd_symb == CASE);
76 ch->ch_type = nd->nd_left->nd_type;
80 /* Now, create case label list
83 assert(right->nd_class == Link && right->nd_symb == ':');
85 if( !AddCases(ch, right->nd_left, right->nd_lab) ) {
89 right = right->nd_right;
93 CaseCode(nd->nd_lab, ch, exit_label);
100 register struct case_hdr *ch;
102 /* free the allocated case structure
104 register struct case_entry *ce;
108 struct case_entry *tmp = ce->ce_next;
117 AddCases(ch, nd, CaseLabel)
118 register struct case_hdr *ch;
119 register struct node *nd;
123 if( !AddOneCase(ch, nd, CaseLabel) )
130 AddOneCase(ch, nd, lbl)
131 register struct case_hdr *ch;
132 register struct node *nd;
135 register struct case_entry *ce = new_case_entry();
136 register struct case_entry *c1 = ch->ch_entries, *c2 = 0;
138 ce->ce_value = nd->nd_INT;
140 if( !TstCompat(ch->ch_type, nd->nd_type) ) {
141 node_error(nd, "case-statement: type incompatibility in case");
145 if( bounded(ch->ch_type) ) {
148 getbounds(ch->ch_type, &lo, &hi);
149 if( ce->ce_value < lo || ce->ce_value > hi )
150 warning("case-statement: constant out of bounds");
153 if( !ch->ch_entries ) {
156 ce->ce_next = (struct case_entry *) 0;
158 ch->ch_lowerbd = ch->ch_upperbd = ce->ce_value;
159 ch->ch_nrofentries = 1;
162 /* second etc. case entry
163 find the proper place to put ce into the list
166 if( ce->ce_value < ch->ch_lowerbd )
167 ch->ch_lowerbd = ce->ce_value;
168 else if( ce->ce_value > ch->ch_upperbd )
169 ch->ch_upperbd = ce->ce_value;
171 while( c1 && c1->ce_value < ce->ce_value ) {
175 /* At this point three cases are possible:
176 1: c1 != 0 && c2 != 0:
177 insert ce somewhere in the middle
178 2: c1 != 0 && c2 == 0:
179 insert ce right after the head
180 3: c1 == 0 && c2 != 0:
181 append ce to last element
182 The case c1 == 0 && c2 == 0 cannot occur, since
183 the list is guaranteed not to be empty.
186 if( c1->ce_value == ce->ce_value ) {
188 "case-statement: multiple case entry");
193 ce->ce_next = c2->ce_next;
197 ce->ce_next = ch->ch_entries;
204 ce->ce_next = (struct case_entry *) 0;
207 (ch->ch_nrofentries)++;
212 CaseCode(lbl, ch, exit_label)
217 label CaseDescrLab = ++data_label; /* rom must have a label */
219 register struct case_entry *ce;
222 C_df_dlb(CaseDescrLab);
223 C_rom_icon("0", pointer_size);
225 if( compact(ch->ch_nrofentries, ch->ch_lowerbd, ch->ch_upperbd) ) {
227 C_rom_cst(ch->ch_lowerbd);
228 C_rom_cst(ch->ch_upperbd - ch->ch_lowerbd);
230 for( val = ch->ch_lowerbd; val <= ch->ch_upperbd; val++ ) {
232 if( val == ce->ce_value ) {
233 C_rom_ilb(ce->ce_label);
237 C_rom_icon("0", pointer_size);
240 C_lae_dlb(CaseDescrLab, (arith) 0);
245 C_rom_cst((arith) ch->ch_nrofentries);
246 for( ce = ch->ch_entries; ce; ce = ce->ce_next ) {
247 C_rom_cst(ce->ce_value);
248 C_rom_ilb(ce->ce_label);
251 C_lae_dlb(CaseDescrLab, (arith) 0);
255 C_df_ilb(exit_label);