/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Contributed by Frank Ch. Eigler <fche@redhat.com>
and Graydon Hoare <graydon@redhat.com>
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
return struct_type;
}
-#define build_function_type_0(rtype) \
+#define build_function_type_0(rtype) \
build_function_type (rtype, void_list_node)
-#define build_function_type_1(rtype, arg1) \
+#define build_function_type_1(rtype, arg1) \
build_function_type (rtype, tree_cons (0, arg1, void_list_node))
#define build_function_type_3(rtype, arg1, arg2, arg3) \
- build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
- tree_cons (0, arg3, void_list_node))))
+ build_function_type (rtype, \
+ tree_cons (0, arg1, \
+ tree_cons (0, arg2, \
+ tree_cons (0, arg3, \
+ void_list_node))))
#define build_function_type_4(rtype, arg1, arg2, arg3, arg4) \
- build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
- tree_cons (0, arg3, tree_cons (0, arg4, \
- void_list_node)))))
+ build_function_type (rtype, \
+ tree_cons (0, arg1, \
+ tree_cons (0, arg2, \
+ tree_cons (0, arg3, \
+ tree_cons (0, arg4, \
+ void_list_node)))))
/* Initialize the global tree nodes that correspond to mf-runtime.h
declarations. */
/* Build initialization nodes for the cache vars. We just load the
globals into the cache variables. */
- t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (mf_cache_shift_decl_l),
- mf_cache_shift_decl_l, mf_cache_shift_decl);
+ t = build_gimple_modify_stmt (mf_cache_shift_decl_l, mf_cache_shift_decl);
SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
gimplify_to_stmt_list (&t);
shift_init_stmts = t;
- t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (mf_cache_mask_decl_l),
- mf_cache_mask_decl_l, mf_cache_mask_decl);
+ t = build_gimple_modify_stmt (mf_cache_mask_decl_l, mf_cache_mask_decl);
SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
gimplify_to_stmt_list (&t);
mask_init_stmts = t;
mf_limit = create_tmp_var (mf_uintptr_type, "__mf_limit");
/* Build: __mf_base = (uintptr_t) <base address expression>. */
- t = build2 (GIMPLE_MODIFY_STMT, void_type_node, mf_base,
- convert (mf_uintptr_type, unshare_expr (base)));
+ t = build_gimple_modify_stmt (mf_base,
+ fold_convert (mf_uintptr_type,
+ unshare_expr (base)));
SET_EXPR_LOCUS (t, locus);
gimplify_to_stmt_list (&t);
head = tsi_start (t);
tsi = tsi_last (t);
/* Build: __mf_limit = (uintptr_t) <limit address expression>. */
- t = build2 (GIMPLE_MODIFY_STMT, void_type_node, mf_limit,
- convert (mf_uintptr_type, unshare_expr (limit)));
+ t = build_gimple_modify_stmt (mf_limit,
+ fold_convert (mf_uintptr_type,
+ unshare_expr (limit)));
SET_EXPR_LOCUS (t, locus);
gimplify_to_stmt_list (&t);
tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
/* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
& __mf_mask]. */
t = build2 (RSHIFT_EXPR, mf_uintptr_type, mf_base,
- (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
+ flag_mudflap_threads ? mf_cache_shift_decl
+ : mf_cache_shift_decl_l);
t = build2 (BIT_AND_EXPR, mf_uintptr_type, t,
- (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
+ flag_mudflap_threads ? mf_cache_mask_decl
+ : mf_cache_mask_decl_l);
t = build4 (ARRAY_REF,
TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
- t = build2 (GIMPLE_MODIFY_STMT, void_type_node, mf_elem, t);
+ t = build_gimple_modify_stmt (mf_elem, t);
SET_EXPR_LOCUS (t, locus);
gimplify_to_stmt_list (&t);
tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
can use as the condition for the conditional jump. */
t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
- t = build2 (GIMPLE_MODIFY_STMT, boolean_type_node, cond, t);
+ t = build_gimple_modify_stmt (cond, t);
gimplify_to_stmt_list (&t);
tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
/* Build the conditional jump. 'cond' is just a temporary so we can
simply build a void COND_EXPR. We do need labels in both arms though. */
- t = build3 (COND_EXPR, void_type_node, cond,
- build1 (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
- build1 (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
+ t = build3 (COND_EXPR, void_type_node, cond, NULL_TREE, NULL_TREE);
SET_EXPR_LOCUS (t, locus);
tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
refresh *_l vars.
This is the body of the conditional. */
-
- u = tree_cons (NULL_TREE,
- mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
- : *locus),
- NULL_TREE);
- u = tree_cons (NULL_TREE, dirflag, u);
+
+ u = mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION : *locus);
/* NB: we pass the overall [base..limit] range to mf_check. */
- u = tree_cons (NULL_TREE,
- fold_build2 (PLUS_EXPR, integer_type_node,
- fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
- integer_one_node),
- u);
- u = tree_cons (NULL_TREE, mf_base, u);
- t = build_function_call_expr (mf_check_fndecl, u);
+ v = fold_build2 (PLUS_EXPR, integer_type_node,
+ fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
+ integer_one_node);
+ t = build_call_expr (mf_check_fndecl, 4, mf_base, v, dirflag, u);
gimplify_to_stmt_list (&t);
head = tsi_start (t);
tsi = tsi_last (t);
if (! flag_mudflap_threads)
{
- t = build2 (GIMPLE_MODIFY_STMT, void_type_node,
- mf_cache_shift_decl_l, mf_cache_shift_decl);
+ t = build_gimple_modify_stmt (mf_cache_shift_decl_l,
+ mf_cache_shift_decl);
tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
- t = build2 (GIMPLE_MODIFY_STMT, void_type_node,
- mf_cache_mask_decl_l, mf_cache_mask_decl);
+ t = build_gimple_modify_stmt (mf_cache_mask_decl_l,
+ mf_cache_mask_decl);
tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
}
bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
*instr_bsi = bsi_start (join_bb);
- bsi_next (instr_bsi);
}
/* The decl must have its address taken. In the case of
arrays, this flag is also set if the indexes are not
compile-time known valid constants. */
- && TREE_ADDRESSABLE (decl) /* XXX: not sufficient: return-by-value structs! */
+ /* XXX: not sufficient: return-by-value structs! */
+ && TREE_ADDRESSABLE (decl)
/* The type of the variable must be complete. */
&& COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
/* The decl hasn't been decomposed somehow. */
while (1)
{
if (bitfield_ref_p && elt == NULL_TREE
- && (TREE_CODE (var) == ARRAY_REF || TREE_CODE (var) == COMPONENT_REF))
+ && (TREE_CODE (var) == ARRAY_REF
+ || TREE_CODE (var) == COMPONENT_REF))
elt = var;
if (TREE_CODE (var) == ARRAY_REF)
return;
else
{
- base = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (var)), var);
+ base = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (var)), var);
break;
}
}
size = DECL_SIZE_UNIT (field);
if (elt)
- elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)), elt);
+ elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)),
+ elt);
addr = fold_convert (ptr_type_node, elt ? elt : base);
- addr = fold_build2 (PLUS_EXPR, ptr_type_node,
- addr, fold_convert (ptr_type_node,
+ addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+ addr, fold_convert (sizetype,
byte_position (field)));
}
else
case INDIRECT_REF:
addr = TREE_OPERAND (t, 0);
base = addr;
- limit = fold_build2 (MINUS_EXPR, ptr_type_node,
- fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
- integer_one_node);
+ limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+ fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base,
+ size),
+ size_int (-1));
break;
case TARGET_MEM_REF:
addr = tree_mem_ref_addr (ptr_type_node, t);
base = addr;
- limit = fold_build2 (MINUS_EXPR, ptr_type_node,
- fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
- build_int_cst (ptr_type_node, 1));
+ limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+ fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base,
+ size),
+ size_int (-1));
break;
case ARRAY_RANGE_REF:
bpu = bitsize_int (BITS_PER_UNIT);
ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
- ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
+ ofs = fold_convert (sizetype, size_binop (TRUNC_DIV_EXPR, ofs, bpu));
size = convert (bitsizetype, TREE_OPERAND (t, 1));
size = size_binop (PLUS_EXPR, size, rem);
addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
addr = convert (ptr_type_node, addr);
- addr = fold_build2 (PLUS_EXPR, ptr_type_node, addr, ofs);
+ addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, ofs);
base = addr;
- limit = fold_build2 (MINUS_EXPR, ptr_type_node,
- fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
- integer_one_node);
+ limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+ fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
+ base, size),
+ size_int (-1));
}
break;
&& ! TREE_STATIC (decl))
{
tree size = NULL_TREE, variable_name;
- tree unregister_fncall, unregister_fncall_params;
- tree register_fncall, register_fncall_params;
+ tree unregister_fncall, unregister_fncall_param;
+ tree register_fncall, register_fncall_param;
size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
- /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
- unregister_fncall_params =
- tree_cons (NULL_TREE,
- convert (ptr_type_node,
- mf_mark (build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (decl)),
- decl))),
- tree_cons (NULL_TREE,
- size,
- tree_cons (NULL_TREE,
- /* __MF_TYPE_STACK */
- build_int_cst (NULL_TREE, 3),
- NULL_TREE)));
- /* __mf_unregister (...) */
- unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
- unregister_fncall_params);
-
- /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
+
+ unregister_fncall_param =
+ convert (ptr_type_node,
+ mf_mark (build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (decl)),
+ decl)));
+ /* __mf_unregister (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
+ unregister_fncall = build_call_expr (mf_unregister_fndecl, 3,
+ unregister_fncall_param,
+ size,
+ build_int_cst (NULL_TREE, 3));
+
+
variable_name = mf_varname_tree (decl);
- register_fncall_params =
- tree_cons (NULL_TREE,
- convert (ptr_type_node,
- mf_mark (build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (decl)),
- decl))),
- tree_cons (NULL_TREE,
- size,
- tree_cons (NULL_TREE,
- /* __MF_TYPE_STACK */
- build_int_cst (NULL_TREE, 3),
- tree_cons (NULL_TREE,
- variable_name,
- NULL_TREE))));
-
- /* __mf_register (...) */
- register_fncall = build_function_call_expr (mf_register_fndecl,
- register_fncall_params);
+ register_fncall_param =
+ convert (ptr_type_node,
+ mf_mark (build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (decl)),
+ decl)));
+ /* __mf_register (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK,
+ "name") */
+ register_fncall = build_call_expr (mf_register_fndecl, 4,
+ register_fncall_param,
+ size,
+ build_int_cst (NULL_TREE, 3),
+ variable_name);
+
/* Accumulate the two calls. */
/* ??? Set EXPR_LOCATION. */
IDENTIFIER_POINTER (DECL_NAME (decl)));
else
{
- tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
+ tsi_link_before (&initially_stmts, register_fncall,
+ TSI_SAME_STMT);
/* Accumulate the FINALLY piece. */
append_to_statement_list (unregister_fncall, &finally_stmts);
void **slot;
if (marked_trees == NULL)
- marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
+ marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer,
+ NULL);
slot = htab_find_slot (marked_trees, t, INSERT);
*slot = t;
static void
mudflap_register_call (tree obj, tree object_size, tree varname)
{
- tree arg, args, call_stmt;
-
- args = tree_cons (NULL_TREE, varname, NULL_TREE);
-
- arg = build_int_cst (NULL_TREE, 4); /* __MF_TYPE_STATIC */
- args = tree_cons (NULL_TREE, arg, args);
-
- arg = convert (size_type_node, object_size);
- args = tree_cons (NULL_TREE, arg, args);
+ tree arg, call_stmt;
arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
arg = convert (ptr_type_node, arg);
- args = tree_cons (NULL_TREE, arg, args);
- call_stmt = build_function_call_expr (mf_register_fndecl, args);
+ call_stmt = build_call_expr (mf_register_fndecl, 4,
+ arg,
+ convert (size_type_node, object_size),
+ /* __MF_TYPE_STATIC */
+ build_int_cst (NULL_TREE, 4),
+ varname);
append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
}
/* Insert a call to __mf_init. */
{
- tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
+ tree call2_stmt = build_call_expr (mf_init_fndecl, 0);
append_to_statement_list (call2_stmt, &ctor_statements);
}
/* If appropriate, call __mf_set_options to pass along read-ignore mode. */
if (flag_mudflap_ignore_reads)
{
- tree arg = tree_cons (NULL_TREE,
- mf_build_string ("-ignore-reads"), NULL_TREE);
- tree call_stmt = build_function_call_expr (mf_set_options_fndecl, arg);
+ tree arg = mf_build_string ("-ignore-reads");
+ tree call_stmt = build_call_expr (mf_set_options_fndecl, 1, arg);
append_to_statement_list (call_stmt, &ctor_statements);
}