/* __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 <jakub@redhat.com>
#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"
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;
}
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);
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)
&& 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
&& 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;
}
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;
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))
{
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,
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;
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;
}
{
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);
{
tree basevar = gimple_assign_rhs1 (stmt);
tree cst = gimple_assign_rhs2 (stmt);
-
+
gcc_assert (TREE_CODE (cst) == INTEGER_CST);
if (integer_zerop (cst))
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);
}
}