tree result;
/* Add FILENAME[:LINENUMBER]. */
- if (xloc.file == NULL && current_function_decl != NULL_TREE)
- xloc.file = DECL_SOURCE_FILE (current_function_decl);
- if (xloc.file == NULL)
- xloc.file = "<unknown file>";
+ file = xloc.file;
+ if (file == NULL && current_function_decl != NULL_TREE)
+ file = DECL_SOURCE_FILE (current_function_decl);
+ if (file == NULL)
+ file = "<unknown file>";
if (xloc.line > 0)
{
/* extern void __mf_init (); */
static GTY (()) tree mf_init_fndecl;
+/* extern int __mf_set_options (const char*); */
+static GTY (()) tree mf_set_options_fndecl;
+
+
/* Helper for mudflap_init: construct a decl with the given category,
name, and type, mark it an external reference, and pushdecl it. */
static inline tree
#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))))
tree mf_check_register_fntype;
tree mf_unregister_fntype;
tree mf_init_fntype;
+ tree mf_set_options_fntype;
if (done)
return;
integer_type_node);
mf_init_fntype =
build_function_type_0 (void_type_node);
+ mf_set_options_fntype =
+ build_function_type_1 (integer_type_node, mf_const_string_type);
mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
mf_cache_array_type);
mf_unregister_fntype);
mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
mf_init_fntype);
+ 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
&& 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. */
+ && DECL_VALUE_EXPR (decl) == NULL
/* Don't process the same decl twice. */
&& ! mf_marked_p (decl))
{
tree unregister_fncall, unregister_fncall_params;
tree register_fncall, register_fncall_params;
- if (DECL_DEFER_OUTPUT (decl))
- {
- /* Oh no ... it's probably a variable-length array (VLA).
- The size and address cannot be computed by merely
- looking at the DECL. See gimplify_decl_stmt for the
- method by which VLA declarations turn into calls to
- BUILT_IN_STACK_ALLOC. We assume that multiple
- VLAs declared later in the same block get allocation
- code later than the others. */
- tree stack_alloc_call = NULL_TREE;
-
- while(! tsi_end_p (initially_stmts))
- {
- tree t = tsi_stmt (initially_stmts);
-
- tree call = NULL_TREE;
- if (TREE_CODE (t) == CALL_EXPR)
- call = t;
- else if (TREE_CODE (t) == MODIFY_EXPR &&
- TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
- call = TREE_OPERAND (t, 1);
- else if (TREE_CODE (t) == TRY_FINALLY_EXPR)
- {
- /* We hope that this is the try/finally block sometimes
- constructed by gimplify_bind_expr() for a BIND_EXPR
- that contains VLAs. This very naive recursion
- appears to be sufficient. */
- initially_stmts = tsi_start (TREE_OPERAND (t, 0));
- }
-
- if (call != NULL_TREE)
- {
- if (TREE_CODE (TREE_OPERAND(call, 0)) == ADDR_EXPR &&
- TREE_OPERAND (TREE_OPERAND (call, 0), 0) ==
- implicit_built_in_decls [BUILT_IN_STACK_ALLOC])
- {
- tree stack_alloc_args = TREE_OPERAND (call, 1);
- tree stack_alloc_op1 = TREE_VALUE (stack_alloc_args);
- tree stack_alloc_op2 = TREE_VALUE (TREE_CHAIN (stack_alloc_args));
-
- if (TREE_CODE (stack_alloc_op1) == ADDR_EXPR &&
- TREE_OPERAND (stack_alloc_op1, 0) == decl)
- {
- /* Got it! */
- size = stack_alloc_op2;
- stack_alloc_call = call;
- /* Advance iterator to point past this allocation call. */
- tsi_next (&initially_stmts);
- break;
- }
- }
- }
-
- tsi_next (&initially_stmts);
- }
-
- if (stack_alloc_call == NULL_TREE)
- {
- warning ("mudflap cannot handle variable-sized declaration `%s'",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- break;
- }
- }
- else
- {
- size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
- }
+ size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
/* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
unregister_fncall_params =
call_stmt = build_function_call_expr (mf_register_fndecl, args);
- /* Add an initial __mf_init() call to the list of registration calls. */
- if (enqueued_call_stmt_chain == NULL_TREE)
- {
- tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
- append_to_statement_list (call2_stmt, &enqueued_call_stmt_chain);
- }
-
append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
}
void
mudflap_finish_file (void)
{
+ tree ctor_statements = NULL_TREE;
+
/* Try to give the deferred objects one final try. */
if (deferred_static_decls)
{
VARRAY_CLEAR (deferred_static_decls);
}
+ /* Insert a call to __mf_init. */
+ {
+ tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
+ 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);
+ append_to_statement_list (call_stmt, &ctor_statements);
+ }
+
+ /* Append all the enqueued registration calls. */
if (enqueued_call_stmt_chain)
{
- cgraph_build_static_cdtor ('I', enqueued_call_stmt_chain,
- MAX_RESERVED_INIT_PRIORITY-1);
- enqueued_call_stmt_chain = 0;
+ append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
+ enqueued_call_stmt_chain = NULL_TREE;
}
+
+ cgraph_build_static_cdtor ('I', ctor_statements,
+ MAX_RESERVED_INIT_PRIORITY-1);
}