📄 genop.cc
字号:
/* file "genop.cc" *//* Copyright (c) 1994 Stanford University All rights reserved. This software is provided under the terms described in the "suif_copyright.h" include file. */#include <suif_copyright.h>/* * This file contains the implementation of the generalized operand class * genop. */#include <limits.h>#include "c.h"typedef struct { sym_node_list *read_once; sym_node_list *read_multiple; } read_once_data;char *k_sequence_point;char *k_bit_field_info;char *k_type_name;char *k_type_source_coordinates;char *k_field_table;char *k_type_alignment;char *k_C_comment;char *k_source_coordinates;char *k_is_declared_reg;char *k_source_references;char *k_builtin_args;char *k_typedef_name;boolean option_keep_comments = FALSE;boolean option_mark_execution_points = FALSE;boolean option_null_check = FALSE;boolean option_keep_typedef_info = FALSE;boolean option_force_enum_is_int = FALSE;static proc_sym *bit_ref_symbol;static void side_effect_list(tree_node_list *the_list, tree_node_list_e *position, operand the_operand);static void written_and_not_read(sym_node_list *sym_list, tree_node_list *node_list);static void find_temps_read_once(sym_node_list *sym_list, tree_node_list *node_list);static void prune_once_read_on_node_list(sym_node_list *read_once, sym_node_list *read_multiple, tree_node_list *node_list);static void prune_once_read_on_node(tree_node *the_node, void *data);static void prune_once_read_on_instr(instruction *the_instr, void *data);static void remove_sym_from_list(sym_node_list *the_list, sym_node *symbol);static void attempt_combination(sym_node_list *read_once, tree_node_list *node_list);static boolean instr_uses_var(instruction *the_instr, var_sym *the_var);static void replace_operand(instruction *the_instr, operand old_operand, operand new_operand);static void prune_out_reads(sym_node_list *sym_list, instruction *the_instr);static void remove_writes(sym_node_list *sym_list, tree_node_list *node_list);static boolean symbol_in_list(sym_node_list *sym_list, sym_node *the_symbol);static void eliminate_write(tree_instr *writer);static void remove_symbols(sym_node_list *sym_list);static void clean_field_refs_on_tree_node(tree_node *the_node, void *);static operand clean_field_refs_on_operand(operand to_clean);static instruction *clean_field_refs_on_instr(instruction *to_clean);static operand expand_bit_field_ref(instruction *to_undo);static operand undo_bit_field_on_instr(instruction *to_undo, unsigned short *from, unsigned short *to, type_node **result_type);static boolean instr_is_bit_field_ref(instruction *to_test);boolean genop::is_addressable(void) { if (suif_operand().is_expr()) { instruction *the_instr = suif_operand().instr(); assert(the_instr != NULL); return (the_instr->opcode() == io_lod); } else if (suif_operand().is_symbol()) { sym_node *symbol = suif_operand().symbol(); assert(symbol != NULL); return symbol->is_userdef(); } else { return FALSE; } }type_node *genop::type(void) { return suif_operand().type(); }tree_node_list *genop::side_effects_only(void) { tree_node_list *the_list = precomputation(); side_effect_list(the_list, NULL, suif_operand()); return the_list; }void genop::make_temporary(void) { type_node *this_type = type(); if (suif_operand().is_symbol()) { sym_node *symbol = suif_operand().symbol(); assert(symbol != NULL); if (!symbol->is_userdef()) return; } else if (suif_operand().is_expr()) { instruction *the_instr = suif_operand().instr(); assert(the_instr != NULL); if (the_instr->opcode() == io_ldc) return; } else { return; } if (needconst) { immed const_value; eval_status status = evaluate_as_const(&const_value); boolean need_default_value = FALSE; switch (status) { case EVAL_OVERFLOW: warning("overflow in constant expression\n"); break; case EVAL_OK: break; case EVAL_NOT_CONST: error("expression must be constant\n"); need_default_value = TRUE; break; case EVAL_DIV_BY_ZERO: error("division by zero in constant expression\n"); need_default_value = TRUE; break; case EVAL_UNKNOWN_AT_LINK: error("constant expression cannot be computed at link time\n"); need_default_value = TRUE; break; default: assert(FALSE); } if (need_default_value) { if (type()->unqual()->op() == TYPE_FLOAT) const_value = immed(0.0); else const_value = immed(0); } if (suif_operand().is_expr()) delete suif_operand().instr(); in_ldc *new_ldc = new in_ldc(type(), operand(), const_value); the_suif_operand = operand(new_ldc); return; } if (is_boolean_type()) this_type = booleantype; var_sym *temporary = get_current_symtab()->new_unique_var(this_type); temporary->reset_userdef(); precomputation()->append(create_assignment(temporary, suif_operand())); the_suif_operand = operand(temporary); }boolean genop::is_int_const(void) { if (!suif_operand().is_expr()) return FALSE; instruction *the_instr = suif_operand().instr(); assert(the_instr != NULL); if (the_instr->opcode() != io_ldc) return FALSE; in_ldc *the_ldc = (in_ldc *)the_instr; return the_ldc->value().is_int_const(); }boolean genop::is_boolean_type(void) { if (suif_operand().is_expr()) { instruction *the_instr = suif_operand().instr(); switch(the_instr->opcode()) { case io_seq: case io_sne: case io_sl: case io_sle: return TRUE; default: return FALSE; } } else if (suif_operand().is_symbol()) { sym_node *symbol = suif_operand().symbol(); assert(symbol != NULL); if (symbol->is_userdef()) return FALSE; assert(symbol->is_var()); var_sym *the_var = (var_sym *)symbol; return (the_var->type() == booleantype); } else { return FALSE; } }/* Checks for a ``null pointer constant'' as defined by ANSI/ISO 9899, * Section 6.2.2.3, paragraph 3. */boolean genop::is_null_pointer_constant(void) { if (!precomputation()->is_empty()) return FALSE; if (!suif_operand().is_expr()) return FALSE; instruction *the_instr = suif_operand().instr(); assert(the_instr != NULL); while (the_instr->opcode() == io_cvt) { in_rrr *the_cvt = (in_rrr *)the_instr; type_node *cvt_result = the_cvt->result_type(); if (!cvt_result->is_ptr()) break; ptr_type *result_ptr = (ptr_type *)cvt_result; type_node *result_ref = result_ptr->ref_type(); if (result_ref->op() != TYPE_VOID) break; operand new_op = the_cvt->src_op(); if (!new_op.is_expr()) break; the_instr = new_op.instr(); } if (the_instr->opcode() == io_ldc) { in_ldc *the_ldc = (in_ldc *)the_instr; if (the_ldc->value() == immed(0)) return TRUE; }#ifndef DEAL_WITH_GCC_BRAIN_DAMAGE genop test_genop(operand(the_instr), precomputation());#else//// gcc version 2.7.2 gets a parse error on the code above. It looks// like the same parsing bug in gcc as noted other places where the// DEAL_WITH_GCC_BRAIN_DAMAGE flag is used. A work-around folows.// operand instr_op(the_instr); genop test_genop(instr_op, precomputation());#endif if (!test_genop.is_integral_constant_expression()) return FALSE; immed immed_value; eval_status result = evaluate_as_const(&immed_value); return ((result == EVAL_OK) && (immed_value == immed(0))); }/* Checks for an ``integral constant expression'' as defined by * ANSI/ISO 9899, Section 6.4, sub-section ``Semantics'', paragraph * 2. */boolean genop::is_integral_constant_expression(void) { if (!precomputation()->is_empty()) return FALSE; if (!suif_operand().is_expr()) return FALSE; instruction *the_instr = suif_operand().instr(); assert(the_instr != NULL); while (the_instr->opcode() == io_cvt) { in_rrr *the_cvt = (in_rrr *)the_instr; if (the_cvt->result_type()->op() != TYPE_INT) return FALSE; operand new_op = the_cvt->src_op(); if (!new_op.is_expr()) return FALSE; the_instr = new_op.instr(); if (new_op.type()->op() == TYPE_FLOAT) { if (the_instr->opcode() != io_ldc) return FALSE; in_ldc *the_ldc = (in_ldc *)the_instr; return the_ldc->value().is_float_const(); } if (new_op.type()->op() != TYPE_INT) return FALSE; } if (the_instr->opcode() != io_ldc) return FALSE; in_ldc *the_ldc = (in_ldc *)the_instr; return the_ldc->value().is_int_const(); }void genop::make_bit_field_ref(unsigned short from, unsigned short to, type_node *result_type) { instruction *function = new in_ldc(voidtype->ptr_to(), operand(), immed(bit_ref_symbol)); in_cal *the_call = new in_cal(result_type, operand(), operand(function), 3); the_call->set_argument(0, suif_operand()); the_call->set_argument(1, operand(new in_ldc(inttype, operand(), immed((int)from)))); the_call->set_argument(2, operand(new in_ldc(inttype, operand(), immed((int)to)))); the_suif_operand = operand(the_call); }boolean genop::is_bit_field_ref(void) { if (!suif_operand().is_expr()) return FALSE; instruction *the_instr = suif_operand().instr(); assert(the_instr != NULL); return instr_is_bit_field_ref(the_instr); }void genop::undo_bit_field_ref(unsigned short *from, unsigned short *to, type_node **result_type) { assert(suif_operand().is_expr()); instruction *the_instr = suif_operand().instr(); assert(the_instr != NULL); the_suif_operand = undo_bit_field_on_instr(the_instr, from, to, result_type); }void genop::double_bit_field_ref(genop *op1, genop *op2) { assert(is_bit_field_ref()); assert(suif_operand().is_expr()); instruction *the_instr = suif_operand().instr(); assert(the_instr != NULL); assert(the_instr->opcode() == io_cal); in_cal *old_call = (in_cal *)the_instr; assert(old_call->num_args() == 3); operand base_pointer = old_call->argument(0); base_pointer.remove(); genop base_genop(base_pointer, precomputation()); base_genop.make_temporary(); in_cal *new_call = new in_cal(old_call->result_type(), operand(), old_call->addr_op().clone(), 3); new_call->set_argument(0, base_genop.suif_operand().clone()); new_call->set_argument(1, old_call->argument(1).clone()); new_call->set_argument(2, old_call->argument(2).clone()); old_call->set_argument(0, base_genop.suif_operand()); *op1 = genop(operand(old_call), base_genop.precomputation()); *op2 = genop(operand(new_call), new tree_node_list); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -