tree-mudflap.c (mf_build_check_statement_for): Reorganize to take check-base and -limit arguments.

2004-10-02  Frank Ch. Eigler  <fche@redhat.com>

	* tree-mudflap.c (mf_build_check_statement_for): Reorganize to
	take check-base and -limit arguments.
	(mf_xform_derefs_1): Reorganize slightly to pass proper base/limit
	check ranges for ARRAY_REF and COMPONENT_REF.
	(execute_mudflap_fnction_ops, ..._decls): Limit unnecessary
	instrumentation.

2004-10-02  Frank Ch. Eigler  <fche@redhat.com>

	* testsuite/libmudflap.c/pass50-frag.c, fail33-frag.c, fail34-frag.c:
	New tests for proper base/limit checking for aggregates.

From-SVN: r88432
This commit is contained in:
Frank Ch. Eigler 2004-10-02 23:12:49 +00:00 committed by Frank Ch. Eigler
parent 7848dfcac1
commit fefbfa2166
6 changed files with 144 additions and 17 deletions

View file

@ -1,3 +1,12 @@
2004-10-02 Frank Ch. Eigler <fche@redhat.com>
* tree-mudflap.c (mf_build_check_statement_for): Reorganize to
take check-base and -limit arguments.
(mf_xform_derefs_1): Reorganize slightly to pass proper base/limit
check ranges for ARRAY_REF and COMPONENT_REF.
(execute_mudflap_fnction_ops, ..._decls): Limit unnecessary
instrumentation.
2004-10-02 Joseph S. Myers <jsm@polyomino.org.uk>
* c-objc-common.c (c_tree_printer): Correct description of %E.

View file

@ -407,7 +407,10 @@ mudflap_init (void)
static void
execute_mudflap_function_ops (void)
{
if (mf_marked_p (current_function_decl))
/* Don't instrument functions such as the synthetic constructor
built during mudflap_finish_file. */
if (mf_marked_p (current_function_decl) ||
DECL_ARTIFICIAL (current_function_decl))
return;
push_gimplify_context ();
@ -481,7 +484,7 @@ mf_decl_clear_locals (void)
}
static void
mf_build_check_statement_for (tree addr, tree size,
mf_build_check_statement_for (tree base, tree addr, tree limit,
block_stmt_iterator *instr_bsi,
location_t *locus, tree dirflag)
{
@ -494,6 +497,7 @@ mf_build_check_statement_for (tree addr, tree size,
tree mf_value;
tree mf_base;
tree mf_elem;
tree mf_limit;
/* We first need to split the current basic block, and start altering
the CFG. This allows us to insert the statements we're about to
@ -557,6 +561,7 @@ mf_build_check_statement_for (tree addr, tree size,
mf_value = create_tmp_var (ptrtype, "__mf_value");
mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
mf_limit = create_tmp_var (mf_uintptr_type, "__mf_limit");
/* Build: __mf_value = <address expression>. */
t = build (MODIFY_EXPR, void_type_node, mf_value, unshare_expr (addr));
@ -565,9 +570,16 @@ mf_build_check_statement_for (tree addr, tree size,
head = tsi_start (t);
tsi = tsi_last (t);
/* Build: __mf_base = (uintptr_t)__mf_value. */
/* Build: __mf_base = (uintptr_t) <base address expression>. */
t = build (MODIFY_EXPR, void_type_node, mf_base,
build1 (NOP_EXPR, mf_uintptr_type, mf_value));
convert (mf_uintptr_type, unshare_expr (base)));
SET_EXPR_LOCUS (t, locus);
gimplify_to_stmt_list (&t);
tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
/* Build: __mf_limit = (uintptr_t) <limit address expression>. */
t = build (MODIFY_EXPR, void_type_node, mf_limit,
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);
@ -590,7 +602,7 @@ mf_build_check_statement_for (tree addr, tree size,
/* Quick validity check.
if (__mf_elem->low > __mf_base
|| (__mf_elem_high < __mf_base + sizeof(T) - 1))
|| (__mf_elem_high < __mf_limit))
{
__mf_check ();
... and only if single-threaded:
@ -607,22 +619,19 @@ mf_build_check_statement_for (tree addr, tree size,
TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
t = build (GT_EXPR, boolean_type_node, t, mf_base);
/* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'.
/* Construct '__mf_elem->high < __mf_limit'.
First build:
1) u <-- '__mf_elem->high'
2) v <-- '__mf_base + sizeof (T) - 1'.
2) v <-- '__mf_limit'.
Then build 'u <-- (u < v). */
u = build (COMPONENT_REF, mf_uintptr_type,
build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
v = convert (mf_uintptr_type,
size_binop (MINUS_EXPR, size, size_one_node));
v = fold (build (PLUS_EXPR, mf_uintptr_type, mf_base, v));
v = mf_limit;
u = build (LT_EXPR, boolean_type_node, u, v);
@ -647,7 +656,7 @@ mf_build_check_statement_for (tree addr, tree size,
the conditional jump,
if (__mf_elem->low > __mf_base
|| (__mf_elem_high < __mf_base + sizeof(T) - 1))
|| (__mf_elem_high < __mf_limit))
The lowered GIMPLE tree representing this code is in the statement
list starting at 'head'.
@ -670,8 +679,14 @@ mf_build_check_statement_for (tree addr, tree size,
: *locus),
NULL_TREE);
u = tree_cons (NULL_TREE, dirflag, u);
u = tree_cons (NULL_TREE, size, u);
u = tree_cons (NULL_TREE, mf_value, u);
/* NB: we pass the overall [base..limit] range to mf_check,
not the [mf_value..mf_value+size-1] range. */
u = tree_cons (NULL_TREE,
fold (build (PLUS_EXPR, integer_type_node,
fold (build (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);
gimplify_to_stmt_list (&t);
head = tsi_start (t);
@ -701,7 +716,7 @@ static void
mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
location_t *locus, tree dirflag)
{
tree type, ptr_type, addr, size, t;
tree type, ptr_type, addr, base, size, limit, t;
/* Don't instrument read operations. */
if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
@ -756,12 +771,20 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
/* If we got here, we couldn't statically the check. */
ptr_type = build_pointer_type (type);
addr = build1 (ADDR_EXPR, ptr_type, t);
base = build1 (ADDR_EXPR, ptr_type, op0);
limit = fold (build (MINUS_EXPR, mf_uintptr_type,
fold (build2 (PLUS_EXPR, mf_uintptr_type, addr, size)),
integer_one_node));
}
break;
case INDIRECT_REF:
addr = TREE_OPERAND (t, 0);
ptr_type = TREE_TYPE (addr);
base = addr;
limit = fold (build (MINUS_EXPR, ptr_type_node,
fold (build (PLUS_EXPR, ptr_type_node, base, size)),
integer_one_node));
break;
case ARRAY_RANGE_REF:
@ -798,6 +821,12 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
ptr_type = build_pointer_type (type);
addr = build1 (ADDR_EXPR, ptr_type, t);
}
/* XXXXXX */
base = addr;
limit = fold (build (MINUS_EXPR, ptr_type_node,
fold (build (PLUS_EXPR, ptr_type_node, base, size)),
integer_one_node));
}
break;
@ -823,6 +852,11 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
addr = convert (ptr_type_node, addr);
addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs));
base = addr;
limit = fold (build (MINUS_EXPR, ptr_type_node,
fold (build (PLUS_EXPR, ptr_type_node, base, size)),
integer_one_node));
}
break;
@ -830,7 +864,7 @@ mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
return;
}
mf_build_check_statement_for (addr, size, iter, locus, dirflag);
mf_build_check_statement_for (base, addr, limit, iter, locus, dirflag);
}
static void
@ -891,7 +925,10 @@ mf_xform_derefs (void)
static void
execute_mudflap_function_decls (void)
{
if (mf_marked_p (current_function_decl))
/* Don't instrument functions such as the synthetic constructor
built during mudflap_finish_file. */
if (mf_marked_p (current_function_decl) ||
DECL_ARTIFICIAL (current_function_decl))
return;
push_gimplify_context ();

View file

@ -1,3 +1,8 @@
2004-10-02 Frank Ch. Eigler <fche@redhat.com>
* testsuite/libmudflap.c/pass50-frag.c, fail33-frag.c, fail34-frag.c:
New tests for proper base/limit checking for aggregates.
2004-09-15 Joseph S. Myers <jsm@polyomino.org.uk>
* testsuite/libmudflap.c/pass35-frag.c: Update expected message.

View file

@ -0,0 +1,25 @@
#include <stdlib.h>
#define SIZE 16
char b[SIZE];
char a[SIZE];
int main ()
{
int i, j=0;
int a_before_b = (& a[0] < & b[0]);
/* Rather than iterating linearly, which would allow loop unrolling
and mapping to pointer manipulation, we traverse the "joined"
arrays in some random order. */
for (i=0; i<SIZE*2; i++)
{
k=rand()%(SIZE*2))
j += (a_before_b ? a[k] : b[k]);
}
return j;
}
/* { dg-output "mudflap violation 1.*" } */
/* { dg-output "Nearby object.*" } */
/* { dg-output "mudflap object.*\[ab\]" } */
/* { dg-do run { xfail *-*-* } } */

View file

@ -0,0 +1,22 @@
#include <stdlib.h>
struct s
{
int a1[4];
};
struct s a, b;
int idx = 7; /* should pass to the next object */
int
main ()
{
int i, j=0;
int a_before_b = (& a < & b);
j = (a_before_b ? a.a1[idx] : b.a1[idx]);
return j;
}
/* { dg-output "mudflap violation 1.*" } */
/* { dg-output "Nearby object.*" } */
/* { dg-output "mudflap object.*\[ab\]" } */
/* { dg-do run { xfail *-*-* } } */

View file

@ -0,0 +1,29 @@
#include <stdlib.h>
struct a
{
int a1[5];
union
{
int b1[5];
struct
{
int c1;
int c2;
} b2[4];
} a2[8];
};
int i1 = 5;
int i2 = 2;
int i3 = 6;
int i4 = 0;
int
main ()
{
volatile struct a *k = calloc (1, sizeof (struct a));
k->a2[i1].b1[i2] = k->a2[i3].b2[i4].c2;
free ((void *) k);
return 0;
}