/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Frank Ch. Eigler <fche@redhat.com>
and Graydon Hoare <graydon@redhat.com>
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "hard-reg-set.h"
-#include "rtl.h"
#include "tree.h"
#include "tm_p.h"
#include "basic-block.h"
#include "tree-pass.h"
#include "hashtab.h"
#include "diagnostic.h"
-#include <demangle.h>
+#include "demangle.h"
#include "langhooks.h"
#include "ggc.h"
#include "cgraph.h"
-#include "toplev.h"
#include "gimple.h"
/* Internal function decls */
tree struct_type = make_node (RECORD_TYPE);
DECL_CONTEXT (fieldlo) = struct_type;
DECL_CONTEXT (fieldhi) = struct_type;
- TREE_CHAIN (fieldlo) = fieldhi;
+ DECL_CHAIN (fieldlo) = fieldhi;
TYPE_FIELDS (struct_type) = fieldlo;
TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
layout_type (struct_type);
return struct_type;
}
-#define build_function_type_0(rtype) \
- build_function_type (rtype, void_list_node)
-#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))))
-#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)))))
-
/* Initialize the global tree nodes that correspond to mf-runtime.h
declarations. */
void
mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
mf_check_register_fntype =
- build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
- integer_type_node, mf_const_string_type);
+ build_function_type_list (void_type_node, ptr_type_node, size_type_node,
+ integer_type_node, mf_const_string_type, NULL_TREE);
mf_unregister_fntype =
- build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
- integer_type_node);
+ build_function_type_list (void_type_node, ptr_type_node, size_type_node,
+ integer_type_node, NULL_TREE);
mf_init_fntype =
- build_function_type_0 (void_type_node);
+ build_function_type_list (void_type_node, NULL_TREE);
mf_set_options_fntype =
- build_function_type_1 (integer_type_node, mf_const_string_type);
+ build_function_type_list (integer_type_node, mf_const_string_type, NULL_TREE);
mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
mf_cache_array_type);
mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options",
mf_set_options_fntype);
}
-#undef build_function_type_4
-#undef build_function_type_3
-#undef build_function_type_1
-#undef build_function_type_0
/* ------------------------------------------------------------------------ */
/* This is the second part of the mudflap instrumentation. It works on
low-level GIMPLE using the CFG, because we want to run this pass after
tree optimizations have been performed, but we have to preserve the CFG
- for expansion from trees to RTL.
- Below is the list of transformations performed on statements in the
+ for expansion from trees to RTL.
+ Below is the list of transformations performed on statements in the
current function.
1) Memory reference transforms: Perform the mudflap indirection-related
u = build3 (COMPONENT_REF, mf_uintptr_type,
build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
- TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
+ DECL_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
v = mf_limit;
is necessary. Or we may have an innocent "a.b.c"
expression that must not be instrumented. We need to
recurse all the way down the nesting structure to figure it
- out: looking just at the outer node is not enough. */
+ out: looking just at the outer node is not enough. */
tree var;
int component_ref_only = (TREE_CODE (t) == COMPONENT_REF);
/* If we have a bitfield component reference, we must note the
&& (TREE_CODE (var) == ARRAY_REF
|| TREE_CODE (var) == COMPONENT_REF))
elt = var;
-
+
if (TREE_CODE (var) == ARRAY_REF)
{
component_ref_only = 0;
}
else if (TREE_CODE (var) == COMPONENT_REF)
var = TREE_OPERAND (var, 0);
- else if (INDIRECT_REF_P (var))
+ else if (INDIRECT_REF_P (var)
+ || TREE_CODE (var) == MEM_REF)
{
base = TREE_OPERAND (var, 0);
break;
&& TREE_CODE (var) != STRING_CST)
return;
}
- else
+ else
{
- gcc_assert (TREE_CODE (var) == VAR_DECL
+ gcc_assert (TREE_CODE (var) == VAR_DECL
|| TREE_CODE (var) == PARM_DECL
|| TREE_CODE (var) == RESULT_DECL
|| TREE_CODE (var) == STRING_CST);
if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
size = DECL_SIZE_UNIT (field);
-
+
if (elt)
elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)),
elt);
size_int (-1));
break;
+ case MEM_REF:
+ addr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (TREE_OPERAND (t, 1)),
+ TREE_OPERAND (t, 0),
+ fold_convert (sizetype, TREE_OPERAND (t, 1)));
+ base = addr;
+ limit = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node,
+ fold_build2_loc (location,
+ 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;
mf_build_check_statement_for (base, limit, iter, location, dirflag);
}
-/* Transform
- 1) Memory references.
- 2) BUILTIN_ALLOCA calls.
+/* Transform
+ 1) Memory references.
+ 2) BUILTIN_ALLOCA calls.
*/
static void
mf_xform_statements (void)
case GIMPLE_CALL:
{
tree fndecl = gimple_call_fndecl (s);
- if (fndecl && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA))
+ if (fndecl && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA))
gimple_call_set_cannot_inline (s, true);
}
break;
-
+
default:
;
}
while (decl != NULL_TREE)
{
- if (mf_decl_eligible_p (decl)
+ if (mf_decl_eligible_p (decl)
/* Not already processed. */
&& ! mf_marked_p (decl)
/* Automatic variable. */
gimplified when we got here. */
size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
gcc_assert (is_gimple_val (size));
-
+
unregister_fncall_param =
mf_mark (build1 (ADDR_EXPR,
unregister_fncall = gimple_build_call (mf_unregister_fndecl, 3,
unregister_fncall_param,
size,
- build_int_cst (NULL_TREE, 3));
+ integer_three_node);
variable_name = mf_varname_tree (decl);
register_fncall = gimple_build_call (mf_register_fndecl, 4,
register_fncall_param,
size,
- build_int_cst (NULL_TREE, 3),
+ integer_three_node,
variable_name);
-
+
/* Accumulate the two calls. */
gimple_set_location (register_fncall, location);
mf_mark (decl);
}
- decl = TREE_CHAIN (decl);
+ decl = DECL_CHAIN (decl);
}
/* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
arg,
convert (size_type_node, object_size),
/* __MF_TYPE_STATIC */
- build_int_cst (NULL_TREE, 4),
+ build_int_cst (NULL_TREE, 4),
varname);
append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
tree ctor_statements = NULL_TREE;
/* No need to continue when there were errors. */
- if (errorcount != 0 || sorrycount != 0)
+ if (seen_error ())
return;
/* Insert a call to __mf_init. */
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)
{
{
size_t i;
tree obj;
- for (i = 0; VEC_iterate (tree, deferred_static_decls, i, obj); i++)
+ FOR_EACH_VEC_ELT (tree, deferred_static_decls, i, obj)
{
gcc_assert (DECL_P (obj));
DECL_NAME (obj));
continue;
}
-
- mudflap_register_call (obj,
+
+ mudflap_register_call (obj,
size_in_bytes (TREE_TYPE (obj)),
mf_varname_tree (obj));
}
enqueued_call_stmt_chain = NULL_TREE;
}
- cgraph_build_static_cdtor ('I', ctor_statements,
+ cgraph_build_static_cdtor ('I', ctor_statements,
MAX_RESERVED_INIT_PRIORITY-1);
}
return flag_mudflap != 0;
}
-struct gimple_opt_pass pass_mudflap_1 =
+struct gimple_opt_pass pass_mudflap_1 =
{
{
GIMPLE_PASS,
}
};
-struct gimple_opt_pass pass_mudflap_2 =
+struct gimple_opt_pass pass_mudflap_2 =
{
{
GIMPLE_PASS,