diff options
Diffstat (limited to 'gcc/expr-rewriter.c')
-rw-r--r-- | gcc/expr-rewriter.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/gcc/expr-rewriter.c b/gcc/expr-rewriter.c index 6ea2b42c580..f0e517662ba 100644 --- a/gcc/expr-rewriter.c +++ b/gcc/expr-rewriter.c @@ -3,9 +3,154 @@ #include <string> #include <map> +bool +ExprTypeRewriter::is_interesting_type(tree t) +{ + const bool in_imap = _imap.find(t) != _imap.end(); + bool interesting = in_imap; + if (!interesting) return false; + + tree possibly_copy = (tree)_imap[t]; + const bool is_copy = possibly_copy == t; + interesting = !is_copy; + if (!interesting) return false; + + // Let's just do a quick sanity check + tree interesting_type = t; + const bool has_valid_suffix = strstr(TypeStringifier::get_type_identifier(interesting_type).c_str(), ".reorg"); + gcc_assert(has_valid_suffix); + return true; +} + +void +ExprTypeRewriter::handle_pointer_arithmetic_nonconstant(gimple *s, tree op_0, tree op_1) +{ + // _1 = _0 * 72 + // ... SNIP ... + // _2 = _1 + CONSTANT; + // ... SNIP ... + // _3 = &array + _2; < -- this is where we are + //enum tree_code code = TREE_CODE(op_1); + //assert_is_type(op_1, SSA_NAME); + + gimple *def_for_variable = SSA_NAME_DEF_STMT(op_1); + // It is possible that we are in a negation statement... + // Example: + // _2 = _1 * 72; + // ... SNIP ... + // _3 = -_2; < -- def_for_variable **might** be this stmt. + // ... SNIP ... + // _4 = &array + _3; + // Let's find out how many operands we have + unsigned num_operands = gimple_num_ops(def_for_variable); + // Here operands is kind of a minomer. + // operand 0 is the lhs + // operand 1 is the rhs + // I.e. lhs = (unary_operator) rhs; + const bool get_another_definition = num_operands == 2; + tree possibly_not_needed = get_another_definition ? gimple_op (def_for_variable, 1) : NULL; + def_for_variable = get_another_definition ? SSA_NAME_DEF_STMT(possibly_not_needed) : def_for_variable; + + // Example: + // _2 = _1 * 72; <-- Now we are here... + // ... SNIP ... + // _3 = -_2; + // ... SNIP ... + // _4 = &array + _3; + + enum tree_code code = gimple_expr_code (def_for_variable); + const bool is_mult_expr = MULT_EXPR == code; + bool is_valid_input = is_mult_expr; + gcc_assert(is_valid_input); + + tree op_0_earlier = gimple_assign_rhs1(def_for_variable); + tree op_1_earlier = gimple_assign_rhs2(def_for_variable); + + // We should be able to just call the constant implementation + //handle_pointer_arithmetic_constants(def_for_variable, op_0, op_1); + //However... + //these variables no longer hold the type needed for them to change correctly + //so, let's do it from here... + + assert_is_type(op_1_earlier, INTEGER_CST); + + // op_0 is the variable + // That means that the reorg_type is + tree reorg_type_tree = TREE_TYPE(op_0); + tree reorg_inner_type = TREE_TYPE(reorg_type_tree); + tree reorg_type_size_tree = TYPE_SIZE_UNIT(reorg_inner_type); + int reorg_type_size_int = tree_to_shwi(reorg_type_size_tree); + // That means that the old type is + tree old_type_tree = (tree)_imap[reorg_type_tree]; + tree old_inner_type = TREE_TYPE(old_type_tree); + tree old_type_size_tree = TYPE_SIZE_UNIT(old_inner_type); + int old_type_size_int = tree_to_shwi(old_type_size_tree); + + tree old_integer_cst_tree = op_1_earlier; + int old_integer_cst_int = tree_to_uhwi(old_integer_cst_tree); + + int offset = old_integer_cst_int % old_type_size_int ; + int new_integer_cst_int = old_integer_cst_int / old_type_size_int * reorg_type_size_int + offset; + log("%d = %d / %d * %d + %d\n", new_integer_cst_int, old_integer_cst_int, old_type_size_int, reorg_type_size_int, offset); + + tree new_integer_cst_tree = build_int_cst(TREE_TYPE(old_integer_cst_tree), new_integer_cst_int); + gimple_set_op(def_for_variable, 2, new_integer_cst_tree); +} + +void +ExprTypeRewriter::handle_pointer_arithmetic_constants(gimple *s, tree p, tree i) +{ + // So, because we have already changed the type + // tree p will either be the original type + // if we do not need to modify this expression + // How do we know if we have an original type? + // It is when we don't have a type in our map + tree possibly_reorged_type = TREE_TYPE(p); + bool is_interesting_case = is_interesting_type(possibly_reorged_type); + if (!is_interesting_case) return; + + tree reorg_type = possibly_reorged_type; // this is the type of the variable + const_tree original_type = _imap[reorg_type]; + // If we are here, that means that our type has the ".reorg" suffix + const bool has_suffix = strstr(TypeStringifier::get_type_identifier(reorg_type).c_str(), ".reorg"); + bool is_valid_input = has_suffix; + gcc_assert(is_valid_input); + + // We need to know what size is the previous original type + tree inner_reorg_type = TREE_TYPE(reorg_type); + tree inner_orig_type = TREE_TYPE(original_type); + tree old_size_tree = TYPE_SIZE_UNIT(inner_orig_type); + int old_size_int = tree_to_shwi(old_size_tree); + tree new_size_tree = TYPE_SIZE_UNIT(inner_reorg_type); + int new_size_int = tree_to_shwi(new_size_tree); + tree old_integer_cst_tree = i; + int old_integer_cst_int = tree_to_uhwi(old_integer_cst_tree); + + int offset = old_integer_cst_int % old_size_int; + const bool is_modulo = offset == 0; + is_valid_input = is_modulo; + gcc_assert(is_valid_input); + + int new_integer_cst_int = old_integer_cst_int / old_size_int * new_size_int + offset; + log("%d = %d / %d * %d\n", new_integer_cst_int, old_integer_cst_int, old_size_int, new_size_int); + + tree new_integer_cst_tree = build_int_cst(TREE_TYPE(old_integer_cst_tree), new_integer_cst_int); + gimple_set_op(s, 2, new_integer_cst_tree); + + +} + void ExprTypeRewriter::_walk_post(const_tree e) { + const enum tree_code code = TREE_CODE(e); + log("tree_code_name = %s\n", get_tree_code_name(code)); + + if(dump_file) { + print_generic_expr(dump_file, (tree)e); + log("\n"); + } + gcc_assert(e); tree t = TREE_TYPE(e); const bool in_map = _map.find(t) != _map.end(); |