/* Tree lowering pass. This pass converts the GENERIC functions-as-trees
tree representation into the GIMPLE form.
- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Major work done by Sebastian Pop <s.pop@laposte.net>,
Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
#include "output.h"
#include "ggc.h"
#include "diagnostic-core.h"
-#include "toplev.h"
#include "target.h"
#include "pointer-set.h"
#include "splay-tree.h"
if (!operand_equal_p (t1, t2, 0))
return 0;
+#ifdef ENABLE_CHECKING
/* Only allow them to compare equal if they also hash equal; otherwise
results are nondeterminate, and we fail bootstrap comparison. */
gcc_assert (gimple_tree_hash (p1) == gimple_tree_hash (p2));
+#endif
return 1;
}
i = VEC_index (constructor_elt, elts, 1)->value;
if (r == NULL || i == NULL)
{
- tree zero = fold_convert (TREE_TYPE (type), integer_zero_node);
+ tree zero = build_zero_cst (TREE_TYPE (type));
if (r == NULL)
r = zero;
if (i == NULL)
/* If the operand is a memory input, it should be an lvalue. */
if (!allows_reg && allows_mem)
{
+ tree inputv = TREE_VALUE (link);
+ STRIP_NOPS (inputv);
+ if (TREE_CODE (inputv) == PREDECREMENT_EXPR
+ || TREE_CODE (inputv) == PREINCREMENT_EXPR
+ || TREE_CODE (inputv) == POSTDECREMENT_EXPR
+ || TREE_CODE (inputv) == POSTINCREMENT_EXPR)
+ TREE_VALUE (link) = error_mark_node;
tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
is_gimple_lvalue, fb_lvalue | fb_mayfail);
mark_addressable (TREE_VALUE (link));
For local variables TYPE_SIZE_UNIT might not be gimplified yet,
in this case omp_notice_variable will be called later
on when it is gimplified. */
- else if (! (flags & GOVD_LOCAL))
+ else if (! (flags & GOVD_LOCAL)
+ && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
}
else if (lang_hooks.decls.omp_privatize_by_reference (decl))
ret = gimplify_omp_atomic (expr_p, pre_p);
break;
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ /* Classified as tcc_expression. */
+ goto expr_2;
+
+ case FMA_EXPR:
+ /* Classified as tcc_expression. */
+ goto expr_3;
+
case POINTER_PLUS_EXPR:
/* Convert ((type *)A)+offset into &A->field_of_type_and_offset.
The second is gimple immediate saving a need for extra statement.
break;
}
+ expr_3:
+ {
+ enum gimplify_status r0, r1, r2;
+
+ r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
+ r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
+ r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
+
+ ret = MIN (MIN (r0, r1), r2);
+ break;
+ }
+
case tcc_declaration:
case tcc_constant:
ret = GS_ALL_DONE;
goto dont_recalculate;
default:
- gcc_assert (TREE_CODE (*expr_p) == TRUTH_AND_EXPR
- || TREE_CODE (*expr_p) == TRUTH_OR_EXPR
- || TREE_CODE (*expr_p) == TRUTH_XOR_EXPR);
- goto expr_2;
+ gcc_unreachable ();
}
recalculate_side_effects (*expr_p);
return outer_bind;
}
+typedef char *char_p; /* For DEF_VEC_P. */
+DEF_VEC_P(char_p);
+DEF_VEC_ALLOC_P(char_p,heap);
+
+/* Return whether we should exclude FNDECL from instrumentation. */
+
+static bool
+flag_instrument_functions_exclude_p (tree fndecl)
+{
+ VEC(char_p,heap) *vec;
+
+ vec = (VEC(char_p,heap) *) flag_instrument_functions_exclude_functions;
+ if (VEC_length (char_p, vec) > 0)
+ {
+ const char *name;
+ int i;
+ char *s;
+
+ name = lang_hooks.decl_printable_name (fndecl, 0);
+ FOR_EACH_VEC_ELT (char_p, vec, i, s)
+ if (strstr (name, s) != NULL)
+ return true;
+ }
+
+ vec = (VEC(char_p,heap) *) flag_instrument_functions_exclude_files;
+ if (VEC_length (char_p, vec) > 0)
+ {
+ const char *name;
+ int i;
+ char *s;
+
+ name = DECL_SOURCE_FILE (fndecl);
+ FOR_EACH_VEC_ELT (char_p, vec, i, s)
+ if (strstr (name, s) != NULL)
+ return true;
+ }
+
+ return false;
+}
+
/* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
node for the function we want to gimplify.
gimple new_bind;
gimple tf;
gimple_seq cleanup = NULL, body = NULL;
-
+ tree tmp_var;
+ gimple call;
+
+ x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+ call = gimple_build_call (x, 1, integer_zero_node);
+ tmp_var = create_tmp_var (ptr_type_node, "return_addr");
+ gimple_call_set_lhs (call, tmp_var);
+ gimplify_seq_add_stmt (&cleanup, call);
x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT];
- gimplify_seq_add_stmt (&cleanup, gimple_build_call (x, 0));
+ call = gimple_build_call (x, 2,
+ build_fold_addr_expr (current_function_decl),
+ tmp_var);
+ gimplify_seq_add_stmt (&cleanup, call);
tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
+ x = implicit_built_in_decls[BUILT_IN_RETURN_ADDRESS];
+ call = gimple_build_call (x, 1, integer_zero_node);
+ tmp_var = create_tmp_var (ptr_type_node, "return_addr");
+ gimple_call_set_lhs (call, tmp_var);
+ gimplify_seq_add_stmt (&body, call);
x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
- gimplify_seq_add_stmt (&body, gimple_build_call (x, 0));
+ call = gimple_build_call (x, 2,
+ build_fold_addr_expr (current_function_decl),
+ tmp_var);
+ gimplify_seq_add_stmt (&body, call);
gimplify_seq_add_stmt (&body, tf);
new_bind = gimple_build_bind (NULL, body, gimple_bind_block (bind));
/* Clear the block for BIND, since it is no longer directly inside
*stmts = NULL;
- if (is_gimple_val (expr))
+ /* gimple_test_f might be more strict than is_gimple_val, make
+ sure we pass both. Just checking gimple_test_f doesn't work
+ because most gimple predicates do not work recursively. */
+ if (is_gimple_val (expr)
+ && (*gimple_test_f) (expr))
return expr;
push_gimplify_context (&gctx);