X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-object-size.c;h=2e8ba2699a060c595ec8d4ebd6a15427b22a8d5d;hb=d7c8f51ae98aa11b3d8c48a505de187bb16250e1;hp=5b9fe38e96bb776edaa7d9a361cd37df6882cb84;hpb=ffbeca59aadc215e559e3dcac8ed918f1844dc8e;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index 5b9fe38e96b..2e8ba2699a0 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -1,5 +1,5 @@ /* __builtin_object_size (ptr, object_size_type) computation - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Jakub Jelinek @@ -24,8 +24,10 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "diagnostic-core.h" #include "toplev.h" -#include "diagnostic.h" +#include "tree-pretty-print.h" +#include "gimple-pretty-print.h" #include "tree-flow.h" #include "tree-pass.h" #include "tree-ssa-propagate.h" @@ -140,6 +142,10 @@ compute_object_offset (const_tree expr, const_tree var) off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t); break; + case MEM_REF: + gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR); + return TREE_OPERAND (expr, 1); + default: return error_mark_node; } @@ -165,15 +171,21 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, pt_var = get_base_address (pt_var); if (pt_var - && TREE_CODE (pt_var) == INDIRECT_REF + && TREE_CODE (pt_var) == MEM_REF && TREE_CODE (TREE_OPERAND (pt_var, 0)) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (pt_var, 0)))) { unsigned HOST_WIDE_INT sz; - if (!osi) - sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0), - object_size_type); + if (!osi || (object_size_type & 1) != 0) + { + sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0), + object_size_type & ~1); + if (host_integerp (TREE_OPERAND (pt_var, 1), 0)) + sz -= TREE_INT_CST_LOW (TREE_OPERAND (pt_var, 1)); + else + sz = offset_limit; + } else { tree var = TREE_OPERAND (pt_var, 0); @@ -184,6 +196,10 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)]; else sz = unknown[object_size_type]; + if (host_integerp (TREE_OPERAND (pt_var, 1), 0)) + sz -= TREE_INT_CST_LOW (TREE_OPERAND (pt_var, 1)); + else + sz = offset_limit; } if (sz != unknown[object_size_type] && sz < offset_limit) @@ -224,7 +240,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, && tree_int_cst_lt (pt_var_size, TYPE_SIZE_UNIT (TREE_TYPE (var))))) var = pt_var; - else if (var != pt_var && TREE_CODE (pt_var) == INDIRECT_REF) + else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF) { tree v = var; /* For &X->fld, compute object size only if fld isn't the last @@ -274,8 +290,8 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) == RECORD_TYPE) { - tree fld_chain = TREE_CHAIN (TREE_OPERAND (v, 1)); - for (; fld_chain; fld_chain = TREE_CHAIN (fld_chain)) + tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1)); + for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain)) if (TREE_CODE (fld_chain) == FIELD_DECL) break; @@ -327,12 +343,14 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, } if (var != pt_var && pt_var_size - && TREE_CODE (pt_var) == INDIRECT_REF + && TREE_CODE (pt_var) == MEM_REF && bytes != error_mark_node) { tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var); if (bytes2 != error_mark_node) { + bytes2 = size_binop (PLUS_EXPR, bytes2, + TREE_OPERAND (pt_var, 1)); if (TREE_CODE (bytes2) == INTEGER_CST && tree_int_cst_lt (pt_var_size, bytes2)) bytes2 = size_zero_node; @@ -381,7 +399,7 @@ alloc_object_size (const_gimple call, int object_size_type) if (TREE_CHAIN (p)) arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1; } - + if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (callee)) { @@ -397,10 +415,10 @@ alloc_object_size (const_gimple call, int object_size_type) if (arg1 < 0 || arg1 >= (int)gimple_call_num_args (call) || TREE_CODE (gimple_call_arg (call, arg1)) != INTEGER_CST - || (arg2 >= 0 + || (arg2 >= 0 && (arg2 >= (int)gimple_call_num_args (call) || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST))) - return unknown[object_size_type]; + return unknown[object_size_type]; if (arg2 >= 0) bytes = size_binop (MULT_EXPR, @@ -745,10 +763,20 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple stmt) unsigned HOST_WIDE_INT bytes; tree op0, op1; - gcc_assert (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR); - - op0 = gimple_assign_rhs1 (stmt); - op1 = gimple_assign_rhs2 (stmt); + if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) + { + op0 = gimple_assign_rhs1 (stmt); + op1 = gimple_assign_rhs2 (stmt); + } + else if (gimple_assign_rhs_code (stmt) == ADDR_EXPR) + { + tree rhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); + gcc_assert (TREE_CODE (rhs) == MEM_REF); + op0 = TREE_OPERAND (rhs, 0); + op1 = TREE_OPERAND (rhs, 1); + } + else + gcc_unreachable (); if (object_sizes[object_size_type][varno] == unknown[object_size_type]) return false; @@ -861,9 +889,8 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) if (osi->pass == 0) { - if (! bitmap_bit_p (osi->visited, varno)) + if (bitmap_set_bit (osi->visited, varno)) { - bitmap_set_bit (osi->visited, varno); object_sizes[object_size_type][varno] = (object_size_type & 2) ? -1 : 0; } @@ -896,13 +923,14 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) { case GIMPLE_ASSIGN: { - if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) + tree rhs = gimple_assign_rhs1 (stmt); + if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR + || (gimple_assign_rhs_code (stmt) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF)) reexamine = plus_stmt_object_size (osi, var, stmt); else if (gimple_assign_single_p (stmt) || gimple_assign_unary_nop_p (stmt)) { - tree rhs = gimple_assign_rhs1 (stmt); - if (TREE_CODE (rhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (rhs))) reexamine = merge_object_sizes (osi, var, rhs, 0); @@ -1111,7 +1139,7 @@ check_for_plus_in_loops (struct object_size_info *osi, tree var) { tree basevar = gimple_assign_rhs1 (stmt); tree cst = gimple_assign_rhs2 (stmt); - + gcc_assert (TREE_CODE (cst) == INTEGER_CST); if (integer_zerop (cst)) @@ -1203,7 +1231,8 @@ compute_object_sizes (void) result = fold_convert (size_type_node, integer_minus_one_node); else if (object_size_type < 4) - result = size_zero_node; + result = fold_convert (size_type_node, + integer_zero_node); } }