Remove a few more warnings.
[suif.git] / src / basesuif / snoot / genop.cc
blob40c058e65c5e5c50767493167e5284f5c704c45b
1 /* file "genop.cc" */
3 /* Copyright (c) 1994 Stanford University
5 All rights reserved.
7 This software is provided under the terms described in
8 the "suif_copyright.h" include file. */
10 #include <suif_copyright.h>
13 * This file contains the implementation of the generalized operand class
14 * genop.
17 #include <limits.h>
18 #include "c.h"
20 typedef struct
22 sym_node_list *read_once;
23 sym_node_list *read_multiple;
24 } read_once_data;
26 const char *k_sequence_point;
27 const char *k_bit_field_info;
28 const char *k_type_name;
29 const char *k_type_source_coordinates;
30 const char *k_field_table;
31 const char *k_type_alignment;
32 const char *k_C_comment;
33 const char *k_source_coordinates;
34 const char *k_is_declared_reg;
35 const char *k_source_references;
36 const char *k_builtin_args;
37 const char *k_typedef_name;
39 boolean option_keep_comments = FALSE;
40 boolean option_mark_execution_points = FALSE;
41 boolean option_null_check = FALSE;
42 boolean option_keep_typedef_info = FALSE;
43 boolean option_force_enum_is_int = FALSE;
45 static proc_sym *bit_ref_symbol;
47 static void side_effect_list(tree_node_list *the_list,
48 tree_node_list_e *position, operand the_operand);
49 static void written_and_not_read(sym_node_list *sym_list,
50 tree_node_list *node_list);
51 static void find_temps_read_once(sym_node_list *sym_list,
52 tree_node_list *node_list);
53 static void prune_once_read_on_node_list(sym_node_list *read_once,
54 sym_node_list *read_multiple,
55 tree_node_list *node_list);
56 static void prune_once_read_on_node(tree_node *the_node, void *data);
57 static void prune_once_read_on_instr(instruction *the_instr, void *data);
58 static void remove_sym_from_list(sym_node_list *the_list, sym_node *symbol);
59 static void attempt_combination(sym_node_list *read_once,
60 tree_node_list *node_list);
61 static boolean instr_uses_var(instruction *the_instr, var_sym *the_var);
62 static void replace_operand(instruction *the_instr, operand old_operand,
63 operand new_operand);
64 static void prune_out_reads(sym_node_list *sym_list, instruction *the_instr);
65 static void remove_writes(sym_node_list *sym_list, tree_node_list *node_list);
66 static boolean symbol_in_list(sym_node_list *sym_list, sym_node *the_symbol);
67 static void eliminate_write(tree_instr *writer);
68 static void remove_symbols(sym_node_list *sym_list);
69 static void clean_field_refs_on_tree_node(tree_node *the_node, void *);
70 static operand clean_field_refs_on_operand(operand to_clean);
71 static instruction *clean_field_refs_on_instr(instruction *to_clean);
72 static operand expand_bit_field_ref(instruction *to_undo);
73 static operand undo_bit_field_on_instr(instruction *to_undo,
74 unsigned short *from,
75 unsigned short *to,
76 type_node **result_type);
77 static boolean instr_is_bit_field_ref(instruction *to_test);
79 boolean genop::is_addressable(void)
81 if (suif_operand().is_expr())
83 instruction *the_instr = suif_operand().instr();
84 assert(the_instr != NULL);
85 return (the_instr->opcode() == io_lod);
87 else if (suif_operand().is_symbol())
89 sym_node *symbol = suif_operand().symbol();
90 assert(symbol != NULL);
91 return symbol->is_userdef();
93 else
95 return FALSE;
99 type_node *genop::type(void)
101 return suif_operand().type();
104 tree_node_list *genop::side_effects_only(void)
106 tree_node_list *the_list = precomputation();
107 side_effect_list(the_list, NULL, suif_operand());
108 return the_list;
111 void genop::make_temporary(void)
113 type_node *this_type = type();
115 if (suif_operand().is_symbol())
117 sym_node *symbol = suif_operand().symbol();
118 assert(symbol != NULL);
119 if (!symbol->is_userdef())
120 return;
122 else if (suif_operand().is_expr())
124 instruction *the_instr = suif_operand().instr();
125 assert(the_instr != NULL);
126 if (the_instr->opcode() == io_ldc)
127 return;
129 else
131 return;
134 if (needconst)
136 immed const_value;
137 eval_status status = evaluate_as_const(&const_value);
138 boolean need_default_value = FALSE;
139 switch (status)
141 case EVAL_OVERFLOW:
142 warning("overflow in constant expression\n");
143 break;
144 case EVAL_OK:
145 break;
146 case EVAL_NOT_CONST:
147 error("expression must be constant\n");
148 need_default_value = TRUE;
149 break;
150 case EVAL_DIV_BY_ZERO:
151 error("division by zero in constant expression\n");
152 need_default_value = TRUE;
153 break;
154 case EVAL_UNKNOWN_AT_LINK:
155 error("constant expression cannot be computed at link time\n");
156 need_default_value = TRUE;
157 break;
158 default:
159 assert(FALSE);
162 if (need_default_value)
164 if (type()->unqual()->op() == TYPE_FLOAT)
165 const_value = immed(0.0);
166 else
167 const_value = immed(0);
170 if (suif_operand().is_expr())
171 delete suif_operand().instr();
173 in_ldc *new_ldc = new in_ldc(type(), operand(), const_value);
174 the_suif_operand = operand(new_ldc);
175 return;
178 if (is_boolean_type())
179 this_type = booleantype;
181 var_sym *temporary = get_current_symtab()->new_unique_var(this_type);
182 temporary->reset_userdef();
184 precomputation()->append(create_assignment(temporary, suif_operand()));
185 the_suif_operand = operand(temporary);
188 boolean genop::is_int_const(void)
190 if (!suif_operand().is_expr())
191 return FALSE;
192 instruction *the_instr = suif_operand().instr();
193 assert(the_instr != NULL);
194 if (the_instr->opcode() != io_ldc)
195 return FALSE;
196 in_ldc *the_ldc = (in_ldc *)the_instr;
197 return the_ldc->value().is_int_const();
200 boolean genop::is_boolean_type(void)
202 if (suif_operand().is_expr())
204 instruction *the_instr = suif_operand().instr();
205 switch(the_instr->opcode())
207 case io_seq:
208 case io_sne:
209 case io_sl:
210 case io_sle:
211 return TRUE;
212 default:
213 return FALSE;
216 else if (suif_operand().is_symbol())
218 sym_node *symbol = suif_operand().symbol();
219 assert(symbol != NULL);
220 if (symbol->is_userdef())
221 return FALSE;
223 assert(symbol->is_var());
224 var_sym *the_var = (var_sym *)symbol;
225 return (the_var->type() == booleantype);
227 else
229 return FALSE;
233 /* Checks for a ``null pointer constant'' as defined by ANSI/ISO 9899,
234 * Section 6.2.2.3, paragraph 3. */
235 boolean genop::is_null_pointer_constant(void)
237 if (!precomputation()->is_empty())
238 return FALSE;
239 if (!suif_operand().is_expr())
240 return FALSE;
241 instruction *the_instr = suif_operand().instr();
242 assert(the_instr != NULL);
243 while (the_instr->opcode() == io_cvt)
245 in_rrr *the_cvt = (in_rrr *)the_instr;
246 type_node *cvt_result = the_cvt->result_type();
247 if (!cvt_result->is_ptr())
248 break;
249 ptr_type *result_ptr = (ptr_type *)cvt_result;
250 type_node *result_ref = result_ptr->ref_type();
251 if (result_ref->op() != TYPE_VOID)
252 break;
253 operand new_op = the_cvt->src_op();
254 if (!new_op.is_expr())
255 break;
256 the_instr = new_op.instr();
258 if (the_instr->opcode() == io_ldc)
260 in_ldc *the_ldc = (in_ldc *)the_instr;
261 if (the_ldc->value() == immed(0))
262 return TRUE;
265 #ifndef DEAL_WITH_GCC_BRAIN_DAMAGE
266 genop test_genop(operand(the_instr), precomputation());
267 #else
269 // gcc version 2.7.2 gets a parse error on the code above. It looks
270 // like the same parsing bug in gcc as noted other places where the
271 // DEAL_WITH_GCC_BRAIN_DAMAGE flag is used. A work-around folows.
273 operand instr_op(the_instr);
274 genop test_genop(instr_op, precomputation());
275 #endif
276 if (!test_genop.is_integral_constant_expression())
277 return FALSE;
278 immed immed_value;
279 eval_status result = evaluate_as_const(&immed_value);
280 return ((result == EVAL_OK) && (immed_value == immed(0)));
283 /* Checks for an ``integral constant expression'' as defined by
284 * ANSI/ISO 9899, Section 6.4, sub-section ``Semantics'', paragraph
285 * 2. */
286 boolean genop::is_integral_constant_expression(void)
288 if (!precomputation()->is_empty())
289 return FALSE;
290 if (!suif_operand().is_expr())
291 return FALSE;
292 instruction *the_instr = suif_operand().instr();
293 assert(the_instr != NULL);
294 while (the_instr->opcode() == io_cvt)
296 in_rrr *the_cvt = (in_rrr *)the_instr;
297 if (the_cvt->result_type()->op() != TYPE_INT)
298 return FALSE;
299 operand new_op = the_cvt->src_op();
300 if (!new_op.is_expr())
301 return FALSE;
302 the_instr = new_op.instr();
303 if (new_op.type()->op() == TYPE_FLOAT)
305 if (the_instr->opcode() != io_ldc)
306 return FALSE;
307 in_ldc *the_ldc = (in_ldc *)the_instr;
308 return the_ldc->value().is_float_const();
310 if (new_op.type()->op() != TYPE_INT)
311 return FALSE;
313 if (the_instr->opcode() != io_ldc)
314 return FALSE;
315 in_ldc *the_ldc = (in_ldc *)the_instr;
316 return the_ldc->value().is_int_const();
319 void genop::make_bit_field_ref(unsigned short from, unsigned short to,
320 type_node *result_type)
322 instruction *function =
323 new in_ldc(voidtype->ptr_to(), operand(), immed(bit_ref_symbol));
324 in_cal *the_call =
325 new in_cal(result_type, operand(), operand(function), 3);
326 the_call->set_argument(0, suif_operand());
327 the_call->set_argument(1, operand(new in_ldc(inttype, operand(),
328 immed((int)from))));
329 the_call->set_argument(2, operand(new in_ldc(inttype, operand(),
330 immed((int)to))));
331 the_suif_operand = operand(the_call);
334 boolean genop::is_bit_field_ref(void)
336 if (!suif_operand().is_expr())
337 return FALSE;
338 instruction *the_instr = suif_operand().instr();
339 assert(the_instr != NULL);
341 return instr_is_bit_field_ref(the_instr);
344 void genop::undo_bit_field_ref(unsigned short *from, unsigned short *to,
345 type_node **result_type)
347 assert(suif_operand().is_expr());
348 instruction *the_instr = suif_operand().instr();
349 assert(the_instr != NULL);
351 the_suif_operand =
352 undo_bit_field_on_instr(the_instr, from, to, result_type);
355 void genop::double_bit_field_ref(genop *op1, genop *op2)
357 assert(is_bit_field_ref());
359 assert(suif_operand().is_expr());
360 instruction *the_instr = suif_operand().instr();
361 assert(the_instr != NULL);
362 assert(the_instr->opcode() == io_cal);
363 in_cal *old_call = (in_cal *)the_instr;
365 assert(old_call->num_args() == 3);
366 operand base_pointer = old_call->argument(0);
367 base_pointer.remove();
368 genop base_genop(base_pointer, precomputation());
369 base_genop.make_temporary();
371 in_cal *new_call =
372 new in_cal(old_call->result_type(), operand(),
373 old_call->addr_op().clone(), 3);
374 new_call->set_argument(0, base_genop.suif_operand().clone());
375 new_call->set_argument(1, old_call->argument(1).clone());
376 new_call->set_argument(2, old_call->argument(2).clone());
378 old_call->set_argument(0, base_genop.suif_operand());
380 *op1 = genop(operand(old_call), base_genop.precomputation());
381 *op2 = genop(operand(new_call), new tree_node_list);
384 void genop::deallocate(void)
386 delete precomputation();
387 if (suif_operand().is_expr())
388 delete suif_operand().instr();
391 void genop::clean_up_bit_field_refs(void)
393 precomputation()->map(&clean_field_refs_on_tree_node, NULL);
394 the_suif_operand = clean_field_refs_on_operand(suif_operand());
397 eval_status genop::evaluate_as_const(immed *result)
399 if (!precomputation()->is_empty())
400 return EVAL_NOT_CONST;
402 suppress_array_folding = FALSE;
403 eval_status status = evaluate_const_expr(suif_operand(), result);
404 suppress_array_folding = TRUE;
405 return status;
408 extern void init_annotes(void)
410 k_type_alignment = lexicon->enter("type alignment")->sp;
412 ANNOTE(k_sequence_point, "sequence point", TRUE);
413 ANNOTE(k_bit_field_info, "bit field info", FALSE);
414 ANNOTE(k_type_name, "type name", FALSE);
415 ANNOTE(k_type_source_coordinates, "type source coordinates", FALSE);
416 ANNOTE(k_field_table, "field table", FALSE);
417 ANNOTE(k_C_comment, "C comment", TRUE);
418 ANNOTE(k_source_coordinates, "source coordinates", TRUE);
419 ANNOTE(k_is_declared_reg, "is declared reg", FALSE);
420 ANNOTE(k_source_references, "source references", TRUE);
421 ANNOTE(k_builtin_args, "builtin args", TRUE);
422 ANNOTE(k_typedef_name, "typedef name", TRUE);
425 extern void init_bit_ref(void)
427 /* Note that we don't install this since it will never be written out --
428 it's just a placeholder */
429 bit_ref_symbol =
430 new proc_sym(func(inttype), src_unknown, "00bit_field_ref");
433 extern tree_node *last_action_node(tree_node_list *the_node_list)
435 return last_action_before(the_node_list, NULL);
438 extern tree_node *last_action_before(tree_node_list *the_node_list,
439 tree_node *the_node)
441 if (the_node_list == NULL)
442 return NULL;
444 if (the_node_list->is_empty())
445 return NULL;
447 tree_node_list_e *current_element = the_node_list->tail();
449 if (the_node != NULL)
451 while (current_element != NULL)
453 tree_node_list_e *old_element = current_element;
454 current_element = current_element->prev();
455 if (old_element->contents == the_node)
456 break;
460 while (current_element != NULL)
462 tree_node *this_node = current_element->contents;
463 switch (this_node->kind())
465 case TREE_INSTR:
467 tree_instr *the_tree_instr = (tree_instr *)this_node;
468 instruction *the_instr = the_tree_instr->instr();
469 assert(the_instr != NULL);
470 if ((the_instr->opcode() != io_mrk) &&
471 (the_instr->opcode() != io_nop))
473 return this_node;
475 break;
477 case TREE_BLOCK:
479 tree_block *the_block = (tree_block *)this_node;
480 tree_node *last_in_block = last_action_node(the_block->body());
481 if (last_in_block != NULL)
482 return last_in_block;
484 default:
485 return this_node;
487 current_element = current_element->prev();
489 return NULL;
492 extern boolean operand_may_have_side_effects(operand the_operand)
494 if (the_operand.is_symbol())
496 sym_node *the_symbol = the_operand.symbol();
497 assert(the_symbol != NULL);
498 if (!the_symbol->is_var())
499 return TRUE;
500 var_sym *the_var = (var_sym *)the_symbol;
501 return any_part_volatile(the_var->type());
503 else if (the_operand.is_expr())
505 instruction *the_instr = the_operand.instr();
506 if (the_instr->opcode() == io_cal)
508 return TRUE;
510 else if (the_instr->opcode() == io_lod)
512 in_rrr *the_rrr = (in_rrr *)the_instr;
513 operand address = the_rrr->src_addr_op();
514 type_node *addr_type = address.type();
515 addr_type = addr_type->unqual();
516 if (!addr_type->is_ptr())
517 return TRUE;
518 ptr_type *the_ptr_type = (ptr_type *)addr_type;
519 if (any_part_volatile(the_ptr_type->ref_type()))
520 return TRUE;
522 else if (the_instr->opcode() == io_str)
524 return TRUE;
526 else if (the_instr->opcode() == io_memcpy)
528 return TRUE;
531 int num_srcs = the_instr->num_srcs();
532 for (int src_num = 0; src_num < num_srcs; ++src_num)
534 if (operand_may_have_side_effects(the_instr->src_op(src_num)))
535 return TRUE;
537 return FALSE;
539 else if (the_operand.is_null())
541 return FALSE;
543 else
545 return TRUE;
549 extern boolean is_same_operand(operand op1, operand op2)
551 if (op1.is_symbol())
553 if (!op2.is_symbol())
554 return FALSE;
555 return (op1.symbol() == op2.symbol());
557 else if (op1.is_expr())
559 if (!op2.is_expr())
560 return FALSE;
561 instruction *instr1 = op1.instr();
562 instruction *instr2 = op2.instr();
563 assert(instr1 != NULL);
564 assert(instr2 != NULL);
565 if (instr1->opcode() != instr2->opcode())
566 return FALSE;
567 if (!instr1->result_type()->is_same(instr2->result_type()))
568 return FALSE;
569 if (instr1->opcode() == io_ldc)
571 in_ldc *ldc1 = (in_ldc *)instr1;
572 in_ldc *ldc2 = (in_ldc *)instr2;
573 return (ldc1->value() == ldc2->value());
575 else
577 unsigned num_srcs = instr1->num_srcs();
578 if (num_srcs != instr2->num_srcs())
579 return FALSE;
580 for (unsigned src_num = 0; src_num < num_srcs; ++src_num)
582 if (!is_same_operand(instr1->src_op(src_num),
583 instr2->src_op(src_num)))
585 return FALSE;
588 return TRUE;
591 else
593 return FALSE;
597 extern void comment_text(char *comment_string)
599 if (!option_keep_comments)
600 return;
602 suif_object *mark_object;
603 if (curr_list == NULL)
605 mark_object = outf;
607 else
609 in_rrr *new_mark = new in_rrr(io_mrk);
610 curr_list->append(new tree_instr(new_mark));
611 mark_object = new_mark;
614 immed_list *new_annote = new immed_list;
615 new_annote->append(immed(comment_string));
616 mark_object->append_annote(k_C_comment, new_annote);
619 extern immed_list *coordinate_to_immeds(Coordinate the_coordinate)
621 immed_list *result = new immed_list;
622 result->append(immed((the_coordinate.file == NULL) ?
623 "" : the_coordinate.file));
624 result->append(immed((int)the_coordinate.x));
625 result->append(immed((int)the_coordinate.y));
626 return result;
629 extern Coordinate *immeds_to_coordinate(immed_list *the_immeds)
631 static Coordinate result;
633 if (the_immeds == NULL)
634 return NULL;
636 immed_list_iter the_iter(the_immeds);
638 if (the_iter.is_empty())
639 return NULL;
640 immed file_immed = the_iter.step();
641 if (!file_immed.is_string())
642 return NULL;
643 result.file = file_immed.string();
645 if (the_iter.is_empty())
646 return NULL;
647 immed x_immed = the_iter.step();
648 if (!x_immed.is_integer())
649 return NULL;
650 result.x = x_immed.integer();
652 if (the_iter.is_empty())
653 return NULL;
654 immed y_immed = the_iter.step();
655 if (!y_immed.is_integer())
656 return NULL;
657 result.y = y_immed.integer();
659 if (!the_iter.is_empty())
660 return NULL;
661 return &result;
664 extern void remove_unused_temps(tree_node_list *the_list)
666 assert(the_list != NULL);
668 sym_node_list unused;
669 written_and_not_read(&unused, the_list);
670 remove_writes(&unused, the_list);
671 remove_symbols(&unused);
673 sym_node_list read_once;
674 find_temps_read_once(&read_once, the_list);
675 attempt_combination(&read_once, the_list);
677 while (!read_once.is_empty())
679 sym_node_list_e *this_element = read_once.head();
680 read_once.remove(this_element);
681 delete this_element;
685 extern immed immed_and_type_for_C_intconst(char *C_intconst,
686 type_node **the_type)
688 char *digit_start = C_intconst;
689 int radix;
690 if (*digit_start == '0')
692 ++digit_start;
693 if ((*digit_start == 'X') || (*digit_start == 'x'))
695 ++digit_start;
696 radix = 16;
698 else
700 radix = 8;
703 else
705 radix = 10;
708 i_integer const_value(digit_start, radix);
709 immed result_value = ii_to_immed(const_value);
711 if (the_type != NULL)
713 char *follow = digit_start;
714 while (TRUE)
716 if (((*follow >= '0') && (*follow <= '9')) ||
717 ((*follow >= 'a') && (*follow <= 'f')) ||
718 ((*follow >= 'A') && (*follow <= 'F')))
720 ++follow;
722 else
724 break;
728 int l_count = 0;
729 boolean u_suffix = FALSE;
731 while (TRUE)
733 if ((!u_suffix) && ((*follow == 'u') || (*follow == 'U')))
734 u_suffix = TRUE;
735 else if ((l_count < 2) && ((*follow == 'l') || (*follow == 'L')))
736 ++l_count;
737 else
738 break;
739 ++follow;
743 * See ANSI/ISO 9899-1990, section 6.1.3.2, second paragraph
744 * of ``Semantics'' section.
746 if ((l_count == 2) && u_suffix)
748 *the_type = unsignedlonglong;
750 else if (l_count == 2)
752 if (immed_fits(result_value, longlong))
753 *the_type = longlong;
754 else
755 *the_type = unsignedlonglong;
757 else if ((l_count >= 1) && u_suffix)
759 if (immed_fits(result_value, unsignedlong))
760 *the_type = unsignedlong;
761 else
762 *the_type = unsignedlonglong;
764 else if (l_count >= 1)
766 if (immed_fits(result_value, longtype))
767 *the_type = longtype;
768 else if (immed_fits(result_value, unsignedlong))
769 *the_type = unsignedlong;
770 else if (immed_fits(result_value, longlong))
771 *the_type = longlong;
772 else
773 *the_type = unsignedlonglong;
775 else if (u_suffix)
777 if (immed_fits(result_value, unsignedtype))
778 *the_type = unsignedtype;
779 else if (immed_fits(result_value, unsignedlong))
780 *the_type = unsignedlong;
781 else
782 *the_type = unsignedlonglong;
784 else
786 if (radix == 10)
788 if (immed_fits(result_value, inttype))
789 *the_type = inttype;
790 else if (immed_fits(result_value, longtype))
791 *the_type = longtype;
792 else if (immed_fits(result_value, unsignedlong))
793 *the_type = unsignedlong;
794 else if (immed_fits(result_value, longlong))
795 *the_type = longlong;
796 else
797 *the_type = unsignedlonglong;
799 else
801 if (immed_fits(result_value, inttype))
802 *the_type = inttype;
803 else if (immed_fits(result_value, unsignedtype))
804 *the_type = unsignedtype;
805 else if (immed_fits(result_value, longtype))
806 *the_type = longtype;
807 else if (immed_fits(result_value, unsignedlong))
808 *the_type = unsignedlong;
809 else if (immed_fits(result_value, longlong))
810 *the_type = longlong;
811 else
812 *the_type = unsignedlonglong;
816 if (!immed_fits(result_value, *the_type))
818 warning("overflow in constant `%s'\n", C_intconst);
819 eval_status status = fit_immed(&result_value, *the_type);
820 assert(status == EVAL_OVERFLOW);
824 return result_value;
827 extern immed immed_and_type_for_C_floatconst(char *C_floatconst,
828 type_node **the_type)
830 char *follow = (char *)cp;
831 assert(follow > C_floatconst);
832 --follow;
833 type_node *result_type;
834 if ((*follow == 'f') || (*follow == 'F'))
835 result_type = floattype;
836 else if ((*follow == 'l') || (*follow == 'L'))
837 result_type = longdouble;
838 else
839 result_type = doubletype;
841 if (the_type != NULL)
842 *the_type = result_type;
844 assert(result_type->op() == TYPE_FLOAT);
845 if (native_floating_arithmetic_ok((base_type *)result_type))
847 double double_value = 0;
848 follow = C_floatconst;
850 double_value = strtod(C_floatconst, NULL);
851 return immed(double_value);
853 else
855 char *mantissa = new char[((char *)cp - C_floatconst) + 1];
856 i_integer additional_exponent(0);
858 follow = C_floatconst;
859 char *follow_mantissa = mantissa;
861 while ((*follow >= '0') && (*follow <= '9'))
863 *follow_mantissa = *follow;
864 ++follow_mantissa;
865 ++additional_exponent;
866 ++follow;
869 if (*follow == '.')
871 ++follow;
872 while ((*follow >= '0') && (*follow <= '9'))
874 *follow_mantissa = *follow;
875 ++follow_mantissa;
876 ++follow;
880 while ((follow_mantissa > mantissa) && (*(follow_mantissa - 1) == '0'))
881 --follow_mantissa;
883 *follow_mantissa = 0;
885 follow_mantissa = mantissa;
886 while (*follow_mantissa == '0')
888 ++follow_mantissa;
889 --additional_exponent;
892 i_integer exponent(0);
894 if ((*follow == 'e') || (*follow == 'E'))
896 ++follow;
897 exponent.read(follow);
900 exponent += (additional_exponent - 1);
902 unsigned long exponent_length =
903 exponent.written_length().c_unsigned_long();
904 char *result_string =
905 new char[strlen(follow_mantissa) + exponent_length + 8];
907 char *follow_result = result_string;
908 if (*follow_mantissa == 0)
910 *follow_result = '0';
912 else
914 *follow_result = *follow_mantissa;
915 ++follow_mantissa;
917 ++follow_result;
919 *follow_result = '.';
920 ++follow_result;
922 if (*follow_mantissa == 0)
924 *follow_result = '0';
925 ++follow_result;
927 else
929 while (*follow_mantissa != 0)
931 *follow_result = *follow_mantissa;
932 ++follow_result;
933 ++follow_mantissa;
937 *follow_result = 'e';
938 ++follow_result;
940 if (!exponent.is_negative())
942 *follow_result = '+';
943 ++follow_result;
946 exponent.write(follow_result);
948 immed result_value = immed(im_extended_float, result_string);
950 delete[] result_string;
951 delete[] mantissa;
953 return result_value;
957 static void side_effect_list(tree_node_list *the_list,
958 tree_node_list_e *position, operand the_operand)
960 assert(the_list != NULL);
962 tree_node_list *side_effects = reduce_to_side_effects(the_operand);
963 if (side_effects != NULL)
965 the_list->insert_before(side_effects, position);
966 delete side_effects;
970 static void written_and_not_read(sym_node_list *sym_list,
971 tree_node_list *node_list)
973 assert(sym_list != NULL);
974 if (node_list == NULL)
975 return;
977 tree_node_list_iter the_iter(node_list);
978 while (!the_iter.is_empty())
980 tree_node *this_node = the_iter.step();
981 switch (this_node->kind())
983 case TREE_INSTR:
985 tree_instr *this_tree_instr = (tree_instr *)this_node;
986 instruction *this_instr = this_tree_instr->instr();
987 assert(this_instr != NULL);
988 prune_out_reads(sym_list, this_instr);
990 operand destination = this_instr->dst_op();
991 if (!destination.is_symbol())
992 break;
994 sym_node *this_symbol = destination.symbol();
995 assert(this_symbol != NULL);
996 if (this_symbol->is_userdef())
997 break;
999 if (sym_list->lookup(this_symbol) == NULL)
1000 sym_list->append(this_symbol);
1002 break;
1004 case TREE_IF:
1006 tree_if *the_if = (tree_if *)this_node;
1007 written_and_not_read(sym_list, the_if->header());
1008 written_and_not_read(sym_list, the_if->then_part());
1009 written_and_not_read(sym_list, the_if->else_part());
1010 break;
1012 default:
1014 * This should never happen since this function should only be
1015 * called on lists of instructions and tree_if's.
1017 assert(FALSE);
1022 static void find_temps_read_once(sym_node_list *sym_list,
1023 tree_node_list *node_list)
1025 sym_node_list read_multiple;
1026 prune_once_read_on_node_list(sym_list, &read_multiple, node_list);
1028 while (!read_multiple.is_empty())
1030 sym_node_list_e *this_element = read_multiple.head();
1031 read_multiple.remove(this_element);
1032 delete this_element;
1036 static void prune_once_read_on_node_list(sym_node_list *read_once,
1037 sym_node_list *read_multiple,
1038 tree_node_list *node_list)
1040 read_once_data read_data;
1041 read_data.read_once = read_once;
1042 read_data.read_multiple = read_multiple;
1044 node_list->map(&prune_once_read_on_node, &read_data);
1047 static void prune_once_read_on_node(tree_node *the_node, void *data)
1049 assert(the_node != NULL);
1050 if (!the_node->is_instr())
1051 return;
1053 tree_instr *the_tree_instr = (tree_instr *)the_node;
1054 the_tree_instr->instr_map(&prune_once_read_on_instr, data);
1057 static void prune_once_read_on_instr(instruction *the_instr, void *data)
1059 assert(the_instr != NULL);
1060 assert(data != NULL);
1062 read_once_data *read_data = (read_once_data *)data;
1064 unsigned num_srcs = the_instr->num_srcs();
1065 for (unsigned src_num = 0; src_num < num_srcs; ++src_num)
1067 operand source = the_instr->src_op(src_num);
1068 if (source.is_symbol())
1070 var_sym *the_var = source.symbol();
1071 if (!the_var->is_userdef())
1073 sym_node_list_e *the_element =
1074 read_data->read_multiple->lookup(the_var);
1075 if (the_element == NULL)
1077 the_element = read_data->read_once->lookup(the_var);
1078 if (the_element == NULL)
1080 read_data->read_once->append(the_var);
1082 else
1084 read_data->read_once->remove(the_element);
1085 delete the_element;
1086 read_data->read_multiple->append(the_var);
1093 if (the_instr->opcode() == io_ldc)
1095 in_ldc *the_ldc = (in_ldc *)the_instr;
1096 immed value = the_ldc->value();
1097 if (value.is_symbol())
1099 sym_node *the_symbol = value.symbol();
1100 if (!the_symbol->is_userdef())
1102 remove_sym_from_list(read_data->read_once, the_symbol);
1103 read_data->read_multiple->append(the_symbol);
1109 static void remove_sym_from_list(sym_node_list *the_list, sym_node *symbol)
1111 assert(symbol != NULL);
1112 sym_node_list_e *the_element = the_list->lookup(symbol);
1113 if (the_element != NULL)
1115 the_list->remove(the_element);
1116 delete the_element;
1117 return;
1121 static void attempt_combination(sym_node_list *read_once,
1122 tree_node_list *node_list)
1124 assert(read_once != NULL);
1125 assert(node_list != NULL);
1127 tree_node_list_iter node_iter(node_list);
1128 while (!node_iter.is_empty())
1130 tree_node *first_node = node_iter.step();
1131 assert(first_node != NULL);
1132 if (!first_node->is_instr())
1133 continue;
1134 tree_instr *first_instr_node = (tree_instr *)first_node;
1135 instruction *first_instr = first_instr_node->instr();
1136 assert(first_instr != NULL);
1138 if (node_iter.is_empty())
1139 break;
1140 tree_node *second_node = node_iter.peek();
1141 assert(second_node != NULL);
1142 if (!second_node->is_instr())
1143 continue;
1144 tree_instr *second_instr_node = (tree_instr *)second_node;
1145 instruction *second_instr = second_instr_node->instr();
1146 assert(second_instr != NULL);
1148 operand first_destination = first_instr->dst_op();
1149 if (!first_destination.is_symbol())
1150 continue;
1151 var_sym *the_var = first_destination.symbol();
1152 assert(the_var != NULL);
1153 sym_node_list_e *the_list_e = read_once->lookup(the_var);
1154 if (the_list_e == NULL)
1155 continue;
1157 if (!instr_uses_var(second_instr, the_var))
1158 continue;
1160 first_instr_node->remove_instr(first_instr);
1161 node_list->remove(first_instr_node->list_e());
1162 delete first_instr_node->list_e();
1163 delete first_instr_node;
1165 first_instr->set_dst(operand());
1166 operand new_operand(first_instr);
1167 if (first_instr->opcode() == io_cpy)
1169 in_rrr *first_rrr = (in_rrr *)first_instr;
1170 new_operand = first_rrr->src_op();
1171 new_operand.remove();
1172 delete first_rrr;
1175 replace_operand(second_instr, operand(the_var), new_operand);
1177 read_once->remove(the_list_e);
1178 delete the_list_e;
1179 the_var->parent()->remove_sym(the_var);
1180 delete the_var;
1184 static boolean instr_uses_var(instruction *the_instr, var_sym *the_var)
1186 assert(the_instr != NULL);
1188 unsigned num_srcs = the_instr->num_srcs();
1189 for (unsigned src_num = 0; src_num < num_srcs; ++src_num)
1191 operand this_source = the_instr->src_op(src_num);
1192 if (this_source == operand(the_var))
1193 return TRUE;
1194 if (this_source.is_expr())
1196 if (instr_uses_var(this_source.instr(), the_var))
1197 return TRUE;
1200 return FALSE;
1203 static void replace_operand(instruction *the_instr, operand old_operand,
1204 operand new_operand)
1206 assert(the_instr != NULL);
1208 unsigned num_srcs = the_instr->num_srcs();
1209 for (unsigned src_num = 0; src_num < num_srcs; ++src_num)
1211 operand this_source = the_instr->src_op(src_num);
1212 if (this_source == old_operand)
1214 the_instr->set_src_op(src_num, new_operand);
1215 return;
1217 if (this_source.is_expr())
1218 replace_operand(this_source.instr(), old_operand, new_operand);
1222 static void prune_out_reads(sym_node_list *sym_list, instruction *the_instr)
1224 assert(sym_list != NULL);
1225 assert(the_instr != NULL);
1227 if (sym_list->is_empty())
1228 return;
1230 int num_srcs = the_instr->num_srcs();
1231 for (int src_num = 0; src_num < num_srcs; ++src_num)
1233 operand this_op = the_instr->src_op(src_num);
1234 if (this_op.is_symbol())
1236 sym_node *this_symbol = this_op.symbol();
1237 assert(this_symbol != NULL);
1238 sym_node_list_e *this_element;
1239 sym_node_list_e *next_element = sym_list->head();
1240 while (next_element != NULL)
1242 this_element = next_element;
1243 next_element = this_element->next();
1244 sym_node *test_sym = this_element->contents;
1245 if (test_sym == this_symbol)
1247 sym_list->remove(this_element);
1248 delete this_element;
1251 if (sym_list->is_empty())
1252 return;
1254 else if (this_op.is_expr())
1256 instruction *this_instr = this_op.instr();
1257 assert(this_instr != NULL);
1258 prune_out_reads(sym_list, this_instr);
1260 if (this_instr->opcode() == io_ldc)
1262 in_ldc *this_ldc = (in_ldc *)this_instr;
1263 immed value = this_ldc->value();
1264 if (value.is_symbol())
1266 sym_node_list_e *this_element =
1267 sym_list->lookup(value.symbol());
1268 if (this_element != NULL)
1270 sym_list->remove(this_element);
1271 delete this_element;
1279 static void remove_writes(sym_node_list *sym_list, tree_node_list *node_list)
1281 assert(sym_list != NULL);
1282 if (node_list == NULL)
1283 return;
1285 if (sym_list->is_empty())
1286 return;
1288 tree_node_list_iter the_iter(node_list);
1289 while (!the_iter.is_empty())
1291 tree_node *this_node = the_iter.step();
1292 switch (this_node->kind())
1294 case TREE_INSTR:
1296 tree_instr *this_tree_instr = (tree_instr *)this_node;
1297 instruction *this_instr = this_tree_instr->instr();
1298 assert(this_instr != NULL);
1300 operand destination = this_instr->dst_op();
1301 if (!destination.is_symbol())
1302 break;
1304 sym_node *this_symbol = destination.symbol();
1305 assert(this_symbol != NULL);
1306 if (!symbol_in_list(sym_list, this_symbol))
1307 break;
1309 eliminate_write(this_tree_instr);
1310 break;
1312 case TREE_IF:
1314 tree_if *the_if = (tree_if *)this_node;
1315 remove_writes(sym_list, the_if->header());
1316 remove_writes(sym_list, the_if->then_part());
1317 remove_writes(sym_list, the_if->else_part());
1318 break;
1320 default:
1322 * This should never happen since this function should only be
1323 * called on lists of instructions and tree_if's.
1325 assert(FALSE);
1330 static boolean symbol_in_list(sym_node_list *sym_list, sym_node *the_symbol)
1332 return (sym_list->lookup(the_symbol) != NULL);
1335 static void eliminate_write(tree_instr *writer)
1337 tree_node_list_e *the_element = writer->list_e();
1338 assert(the_element != NULL);
1339 tree_node_list *the_list = writer->parent();
1340 assert(the_list != NULL);
1341 instruction *the_instr = writer->instr();
1342 assert(the_instr != NULL);
1344 writer->remove_instr(the_instr);
1345 the_instr->set_dst(operand());
1346 side_effect_list(the_list, the_element, operand(the_instr));
1347 the_list->remove(the_element);
1348 delete writer;
1349 delete the_element;
1352 static void remove_symbols(sym_node_list *sym_list)
1354 assert(sym_list != NULL);
1356 sym_node_list_e *this_element;
1357 sym_node_list_e *next_element = sym_list->head();
1358 while (next_element != NULL)
1360 this_element = next_element;
1361 next_element = this_element->next();
1362 sym_node *the_symbol = this_element->contents;
1363 assert(the_symbol != NULL);
1364 the_symbol->parent()->remove_sym(the_symbol);
1365 delete the_symbol;
1366 sym_list->remove(this_element);
1367 delete this_element;
1369 assert(sym_list->is_empty());
1372 static void clean_field_refs_on_tree_node(tree_node *the_node, void *)
1374 assert(the_node != NULL);
1375 if (!the_node->is_instr())
1376 return;
1378 tree_instr *the_tree_instr = (tree_instr *)the_node;
1379 instruction *old_instr = the_tree_instr->instr();
1380 assert(old_instr != NULL);
1381 the_tree_instr->remove_instr(old_instr);
1382 instruction *new_instr = clean_field_refs_on_instr(old_instr);
1383 the_tree_instr->set_instr(new_instr);
1386 static operand clean_field_refs_on_operand(operand to_clean)
1388 if (!to_clean.is_expr())
1389 return to_clean;
1390 return operand(clean_field_refs_on_instr(to_clean.instr()));
1393 static instruction *clean_field_refs_on_instr(instruction *to_clean)
1395 operand destination = to_clean->dst_op();
1397 unsigned num_srcs = to_clean->num_srcs();
1398 for (unsigned src_num = 0; src_num < num_srcs; ++src_num)
1400 operand old_operand = to_clean->src_op(src_num);
1401 old_operand.remove();
1402 to_clean->set_src_op(src_num,
1403 clean_field_refs_on_operand(old_operand));
1406 if (instr_is_bit_field_ref(to_clean))
1408 operand new_operand = expand_bit_field_ref(to_clean);
1409 instruction *new_instr;
1410 if (new_operand.is_expr())
1412 new_instr = new_operand.instr();
1414 else
1416 new_instr = new in_rrr(io_cpy, new_operand.type(), operand(),
1417 new_operand);
1419 if (destination.is_symbol())
1421 new_instr->set_dst(destination);
1423 return new_instr;
1425 else
1427 return to_clean;
1431 static operand expand_bit_field_ref(instruction *to_undo)
1433 unsigned short bit_field_from;
1434 unsigned short bit_field_to;
1435 type_node *result_type;
1436 operand address =
1437 undo_bit_field_on_instr(to_undo, &bit_field_from, &bit_field_to,
1438 &result_type);
1439 int right_amount = result_type->size() - (bit_field_to - bit_field_from);
1440 int left_amount = right_amount - field_right;
1442 in_rrr *the_load =
1443 new in_rrr(io_lod, unsignedtype, operand(), address);
1444 in_rrr *the_lsl =
1445 new in_rrr(io_lsl, unsignedtype, operand(), operand(the_load),
1446 operand(new in_ldc(unsignedtype, operand(),
1447 immed(left_amount))));
1448 in_rrr *pre_asr;
1449 if_ops right_shift_op;
1450 if (result_type == unsignedtype)
1452 pre_asr = the_lsl;
1453 right_shift_op = io_lsr;
1455 else
1457 pre_asr = new in_rrr(io_cvt, result_type, operand(), operand(the_lsl));
1458 right_shift_op = io_asr;
1460 in_rrr *the_asr =
1461 new in_rrr(right_shift_op, result_type, operand(),
1462 operand(pre_asr),
1463 operand(new in_ldc(unsignedtype, operand(),
1464 immed(right_amount))));
1465 return operand(the_asr);
1468 static operand undo_bit_field_on_instr(instruction *to_undo,
1469 unsigned short *from,
1470 unsigned short *to,
1471 type_node **result_type)
1473 assert(to_undo != NULL);
1474 assert(to_undo->opcode() == io_cal);
1475 in_cal *the_call = (in_cal *)to_undo;
1477 operand result = the_call->argument(0);
1478 result.remove();
1480 operand from_operand = the_call->argument(1);
1481 assert(from_operand.is_expr());
1482 instruction *from_instr = from_operand.instr();
1483 assert(from_instr != NULL);
1484 assert(from_instr->opcode() == io_ldc);
1485 in_ldc *from_ldc = (in_ldc *)from_instr;
1486 immed from_value = from_ldc->value();
1487 assert(from_value.is_integer());
1488 *from = from_value.integer();
1490 operand to_operand = the_call->argument(2);
1491 assert(to_operand.is_expr());
1492 instruction *to_instr = to_operand.instr();
1493 assert(to_instr != NULL);
1494 assert(to_instr->opcode() == io_ldc);
1495 in_ldc *to_ldc = (in_ldc *)to_instr;
1496 immed to_value = to_ldc->value();
1497 assert(to_value.is_integer());
1498 *to = to_value.integer();
1500 *result_type = the_call->result_type();
1502 delete to_undo;
1503 return result;
1506 static boolean instr_is_bit_field_ref(instruction *to_test)
1508 assert(to_test != NULL);
1510 if (to_test->opcode() != io_cal)
1511 return FALSE;
1512 in_cal *the_call = (in_cal *)to_test;
1513 operand address = the_call->addr_op();
1515 if (!address.is_expr())
1516 return FALSE;
1517 instruction *addr_instr = address.instr();
1518 assert(addr_instr != NULL);
1520 if (addr_instr->opcode() != io_ldc)
1521 return FALSE;
1522 in_ldc *the_ldc = (in_ldc *)addr_instr;
1523 immed value = the_ldc->value();
1525 if (!value.is_symbol())
1526 return FALSE;
1528 return (value.symbol() == bit_ref_symbol);