[tree-ssa mudflap] C++ front-end hooks
Frank Ch. Eigler
fche@redhat.com
Mon Jan 13 23:09:00 GMT 2003
Hi -
The following patch adds some mudflap hooks to the C++ front-end.
It's just a start, but it already compiles & runs the C libmudflap test
suite properly. It was necessary to factor out some code from
gcc/tree-mudflap.c into front-end-specific parts, thus the new
"c-mudflap.c" and "cp-mudflap.c" files.
Index: ChangeLog.tree-ssa
+ 2003-01-13 Frank Ch. Eigler <fche@redhat.com>
+
+ Front-end generalization.
+ * Makefile.in (C_AND_OBJC_OBJS): Add c-mudflap.o and dependencies.
+ * tree-mudflap.c: Don't include "c-tree.h" any more.
+ (mf_init_extern_trees): Divert to mflang_lookup_decl().
+ (mf_enqueue_register_call, mf_flush_enqueued_calls): Move and rename
+ these functions.
+ * tree-mudflap.h: Declare new mflang_* routines.
+ * c-mudflap.c: New file with C front-end mflang_* routines.
+ * tree-nomudflap.c (*): Call internal_error instead of abort.
+
Index: cp/ChangeLog.tree-ssa
+ 2003-01-13 Frank Ch. Eigler <fche@redhat.com>
+
+ Prototype C++ mudflap support.
+ * Make-lang.in (CXX_OBJS): Add cp/cp-mudflap.o and dependencies.
+ * cp-mudflap.c: New file with C++ front-end mflang_* routines.
+ * decl2.c (finish_file): Divert to mudflap if appropriate.
+ * optimize.c (optimize_function): Ditto.
+
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.62
diff -c -p -r1.903.2.62 Makefile.in
*** Makefile.in 10 Jan 2003 22:38:36 -0000 1.903.2.62
--- Makefile.in 13 Jan 2003 23:04:33 -0000
*************** CXX_TARGET_OBJS=@cxx_target_objs@
*** 738,744 ****
C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
c-objc-common.o c-dump.o libcpp.a $(C_TARGET_OBJS) \
! c-simplify.o c-call-graph.o tree-mudflap.o c-pretty-print.o
# Language-specific object files for C.
C_OBJS = c-parse.o c-lang.o $(C_AND_OBJC_OBJS)
--- 738,744 ----
C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
c-objc-common.o c-dump.o libcpp.a $(C_TARGET_OBJS) \
! c-simplify.o c-call-graph.o tree-mudflap.o c-mudflap.o c-pretty-print.o
# Language-specific object files for C.
C_OBJS = c-parse.o c-lang.o $(C_AND_OBJC_OBJS)
*************** c-call-graph.o : c-call-graph.c $(CONFIG
*** 1460,1465 ****
--- 1460,1468 ----
tree-simple.o : tree-simple.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(EXPR_H) \
$(RTL_H) tree-simple.h $(TM_H) coretypes.h
tree-mudflap.o : $(CONFIG_H) errors.h $(SYSTEM_H) $(TREE_H) tree-inline.h \
+ $(C_TREE_H) $(C_COMMON_H) tree-simple.h diagnostic.h $(HASHTAB_H) \
+ output.h varray.h langhooks.h tree-mudflap.h $(TM_H) coretypes.h
+ c-mudflap.o : $(CONFIG_H) errors.h $(SYSTEM_H) $(TREE_H) tree-inline.h \
$(C_TREE_H) $(C_COMMON_H) tree-simple.h diagnostic.h $(HASHTAB_H) \
output.h varray.h langhooks.h tree-mudflap.h $(TM_H) coretypes.h
tree-nomudflap.o : $(CONFIG_H) errors.h $(SYSTEM_H) $(TREE_H) tree-inline.h \
Index: c-mudflap.c
===================================================================
RCS file: c-mudflap.c
diff -N c-mudflap.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- c-mudflap.c 13 Jan 2003 23:04:33 -0000
***************
*** 0 ****
--- 1,217 ----
+ /* Mudflap: narrow-pointer bounds-checking by tree rewriting:
+ C front-end interface.
+
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Frank Ch. Eigler <fche@redhat.com>
+ and Graydon Hoare <graydon@redhat.com>
+
+ This file is part of GCC.
+
+ 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
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ 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, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+ #include "config.h"
+ #include "errors.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "tree.h"
+ #include "tree-inline.h"
+ #include "c-tree.h"
+ #include "c-common.h"
+ #include "diagnostic.h"
+ #include "output.h"
+ #include "varray.h"
+ #include "tree-mudflap.h"
+ #include "target.h"
+ #include "flags.h"
+ #include "rtl.h"
+ #include "toplev.h"
+ #include "function.h"
+
+
+
+ /* ------------------------------------------------------------------------ */
+
+ static tree mx_flag PARAMS ((tree));
+
+ /* XXX: copied from tree-mudflap.c */
+ static tree
+ mx_flag (t)
+ tree t;
+ {
+ if (!t)
+ abort ();
+ #define MARK_TREE_MUDFLAPPED(tree) do { TREE_BOUNDED (tree) = 1; } while (0)
+ MARK_TREE_MUDFLAPPED(t);
+ return t;
+ }
+
+
+
+ /* ------------------------------------------------------------------------ */
+
+
+ /* Initialize the global tree nodes that correspond to mf-runtime.h
+ declarations. */
+ tree
+ mflang_lookup_decl (name)
+ const char* name;
+ {
+ tree decl = lookup_name (get_identifier (name));
+ if (decl == NULL_TREE)
+ internal_error ("mudflap: cannot find declaration of `%s' from mf-runtime.h",
+ name);
+
+ return decl;
+ }
+
+
+
+ /* Build and return EXPR_STMT for calling __mf_register on the object
+ given by the parameters. One odd thing: the object's address is
+ given by the given assembler label string (since that's all we may
+ know about a string literal, or the static data thingie may be out
+ of the future scope). To turn that into a validish C tree, we
+ create a weird synthetic VAR_DECL node.
+ */
+
+ tree
+ mflang_register_call (label, regsize, regtype, regname)
+ const char* label;
+ tree regsize;
+ tree regtype;
+ tree regname;
+ {
+ tree decltype, decl;
+ tree call_params;
+ tree call_stmt;
+
+ /* XXX: would be nicer not to duplicate these. */
+ tree mf_uintptr_type = TREE_TYPE (mflang_lookup_decl ("uintptr_t"));
+ tree mf_register_fndecl = mflang_lookup_decl ("__mf_register");
+
+ /* See gcc-checker's c-bounds.c (declare_private_statics) */
+ decltype = build_array_type (char_type_node, build_index_type (integer_zero_node));
+ decl = mx_flag (build_decl (VAR_DECL, get_identifier (label), decltype));
+
+ TREE_STATIC (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ TREE_ASM_WRITTEN (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ DECL_INITIAL (decl) = NULL_TREE;
+ layout_decl (decl, 0);
+ TREE_USED (decl) = 1;
+ SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
+ DECL_DEFER_OUTPUT (decl) = 1;
+ /* XXX: what else? */
+ /* rest_of_decl_compilation (decl, build_string (strlen (label) + 1, label), 1, 0); */
+ /* make_decl_rtl (decl, build_string (strlen (label) + 1, label)); */
+
+ call_params = tree_cons (NULL_TREE,
+ convert (mf_uintptr_type,
+ mx_flag (build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (decl)),
+ decl))),
+ tree_cons (NULL_TREE,
+ convert (mf_uintptr_type, regsize),
+ tree_cons (NULL_TREE,
+ regtype,
+ tree_cons (NULL_TREE,
+ regname,
+ NULL_TREE))));
+
+ call_stmt = build1 (EXPR_STMT, void_type_node,
+ build_function_call (mf_register_fndecl,
+ call_params));
+
+ return call_stmt;
+ }
+
+
+
+ /* Emit a synthetic CTOR function for the current file. Populate it
+ from the enqueued __mf_register calls. Call the RTL expanders
+ inline. */
+
+ void
+ mflang_flush_calls (enqueued_call_stmt_chain)
+ tree enqueued_call_stmt_chain;
+ {
+ /* See profile.c (output_func_start_profiler) */
+ tree fnname;
+ char *nmplus;
+ tree fndecl;
+ tree body;
+
+ /* Short-circuit! */
+ if (enqueued_call_stmt_chain == NULL_TREE)
+ return;
+
+ /* Create the COMPOUND_STMT that becomes the new function's body. */
+ body = make_node (COMPOUND_STMT);
+ COMPOUND_BODY (body) = enqueued_call_stmt_chain;
+ enqueued_call_stmt_chain = NULL_TREE;
+
+ /* Create a ctor function declaration. */
+ nmplus = concat (IDENTIFIER_POINTER (get_file_function_name ('I')), "_mudflap", NULL);
+ fnname = get_identifier (nmplus);
+ free (nmplus);
+ fndecl = build_decl (FUNCTION_DECL, fnname,
+ build_function_type (void_type_node, NULL_TREE));
+ DECL_EXTERNAL (fndecl) = 0;
+ TREE_PUBLIC (fndecl) = ! targetm.have_ctors_dtors;
+ TREE_USED (fndecl) = 1;
+ DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
+
+ /* Now compile the sucker as we go. This is a weird semi-inlined
+ form of the guts of the c-parse.y `fndef' production, and a hybrid
+ with c_expand_body. */
+
+ /* start_function */
+ fndecl = pushdecl (fndecl);
+ pushlevel (0);
+ rest_of_decl_compilation (fndecl, 0, 1, 0);
+ announce_function (fndecl);
+ current_function_decl = fndecl;
+ DECL_INITIAL (fndecl) = error_mark_node;
+ DECL_SAVED_TREE (fndecl) = body;
+ make_decl_rtl (fndecl, NULL);
+
+ /* store_parm_decls */
+ init_function_start (fndecl, input_filename, lineno);
+ cfun->x_whole_function_mode_p = 1;
+
+ /* finish_function */
+ poplevel (1, 0, 1);
+ BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+
+ /* c_expand_body */
+ expand_function_start (fndecl, 0);
+ expand_stmt (DECL_SAVED_TREE (fndecl));
+ if (lang_expand_function_end)
+ (*lang_expand_function_end) ();
+ expand_function_end (input_filename, lineno, 0);
+ rest_of_compilation (fndecl);
+ if (! quiet_flag)
+ fflush (asm_out_file);
+ current_function_decl = NULL_TREE;
+ if (targetm.have_ctors_dtors)
+ (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
+ else
+ static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+ }
Index: tree-mudflap.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-mudflap.c,v
retrieving revision 1.1.2.28
diff -c -p -r1.1.2.28 tree-mudflap.c
*** tree-mudflap.c 24 Dec 2002 03:14:36 -0000 1.1.2.28
--- tree-mudflap.c 13 Jan 2003 23:04:33 -0000
***************
*** 1,5 ****
/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
! Copyright (C) 2001, 2002 Free Software Foundation, Inc.
Contributed by Frank Ch. Eigler <fche@redhat.com>
and Graydon Hoare <graydon@redhat.com>
--- 1,5 ----
/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
! Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Contributed by Frank Ch. Eigler <fche@redhat.com>
and Graydon Hoare <graydon@redhat.com>
*************** Software Foundation, 59 Temple Place - S
*** 28,36 ****
#include "tm.h"
#include "tree.h"
#include "tree-inline.h"
- #include "c-tree.h"
- #include "c-common.h"
#include "tree-simple.h"
#include "diagnostic.h"
#include "hashtab.h"
#include "output.h"
--- 28,35 ----
#include "tm.h"
#include "tree.h"
#include "tree-inline.h"
#include "tree-simple.h"
+ #include "c-common.h"
#include "diagnostic.h"
#include "hashtab.h"
#include "output.h"
*************** static void mf_decl_cache_locals PARAMS
*** 54,61 ****
static void mf_decl_clear_locals PARAMS ((void));
static tree mf_varname_tree PARAMS ((tree));
static tree mf_file_function_line_tree PARAMS ((const char *, int));
- static void mf_enqueue_register_call PARAMS ((const char*, tree, tree, tree));
- static void mf_flush_enqueued_calls PARAMS ((void));
static tree mf_mostly_copy_tree_r PARAMS ((tree *, int *, void *));
static tree mx_flag PARAMS ((tree));
static tree mx_xfn_indirect_ref PARAMS ((tree *, int *, void *));
--- 53,58 ----
*************** mudflap_c_function (t)
*** 109,244 ****
}
- /* ------------------------------------------------------------------------ */
-
-
- /* Remember given node as a static of some kind: global data,
- function-scope static, or an anonymous constant. Its assembler
- label is given.
- */
-
-
- /* A list of globals whose incomplete declarations we encountered.
- Instead of emitting the __mf_register call for them here, it's
- delayed until program finish time. If they're still incomplete by
- then, warnings are emitted. */
-
- static GTY (()) varray_type deferred_static_decls;
- static GTY (()) varray_type deferred_static_decl_labels;
- static int deferred_static_decls_init;
-
- /* What I really want is a std::map<union tree_node,std::string> .. :-( */
-
-
- void
- mudflap_enqueue_decl (obj, label)
- tree obj;
- const char *label;
- {
- if (TREE_MUDFLAPPED_P (obj))
- return;
-
- /*
- fprintf (stderr, "enqueue_decl obj=`");
- print_generic_expr (stderr, obj, 0);
- fprintf (stderr, "' label=`%s'\n", label);
- */
-
- if (COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (obj)))
- {
- /* NB: the above condition doesn't require TREE_USED or
- TREE_ADDRESSABLE. That's because this object may be a global
- only used from other compilation units. XXX: Maybe static
- objects could require those attributes being set. */
- mf_enqueue_register_call (label,
- size_in_bytes (TREE_TYPE (obj)),
- build_int_2 (3, 0), /* __MF_TYPE_STATIC */
- mf_varname_tree (obj));
- }
- else
- {
- unsigned i;
- int found_p;
-
- if (! deferred_static_decls_init)
- {
- deferred_static_decls_init = 1;
- VARRAY_TREE_INIT (deferred_static_decls, 10, "deferred static list");
- VARRAY_CHAR_PTR_INIT (deferred_static_decl_labels, 10, "label list");
- }
-
- /* Ugh, linear search... */
- found_p = 0;
- for (i=0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
- if (VARRAY_TREE (deferred_static_decls, i) == obj)
- found_p = 1;
-
- if (found_p)
- warning_with_decl (obj, "mudflap cannot track lifetime of `%s'",
- IDENTIFIER_POINTER (DECL_NAME (obj)));
- else
- {
- VARRAY_PUSH_TREE (deferred_static_decls, obj);
- VARRAY_PUSH_CHAR_PTR (deferred_static_decl_labels, (char *) label);
- }
- }
- }
-
-
- void
- mudflap_enqueue_constant (obj, label)
- tree obj;
- const char *label;
- {
- if (TREE_MUDFLAPPED_P (obj))
- return;
-
- if (TREE_CODE (obj) == STRING_CST)
- {
- mf_enqueue_register_call (label,
- build_int_2 (TREE_STRING_LENGTH (obj), 0),
- build_int_2 (3, 0), /* __MF_TYPE_STATIC */
- mx_flag (fix_string_type
- (build_string (15, "string literal"))));
- }
- else
- {
- mf_enqueue_register_call (label,
- size_in_bytes (TREE_TYPE (obj)),
- build_int_2 (3, 0), /* __MF_TYPE_STATIC */
- mx_flag (fix_string_type
- (build_string (9, "constant"))));
- }
- }
-
-
-
- /* Emit any file-wide instrumentation. */
- void
- mudflap_finish_file ()
- {
- /* Try to give the deferred objects one final try. */
- if (deferred_static_decls_init)
- {
- unsigned i;
-
- for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
- {
- tree obj = VARRAY_TREE (deferred_static_decls, i);
- const char *label = VARRAY_CHAR_PTR (deferred_static_decl_labels, i);
-
- /* Call enqueue_decl again on the same object it has previously
- put into the table. (It won't modify the table this time, so
- infinite iteration is not a problem.) */
- mudflap_enqueue_decl (obj, label);
- }
-
- VARRAY_CLEAR (deferred_static_decls);
- VARRAY_CLEAR (deferred_static_decl_labels);
- }
-
- mf_flush_enqueued_calls ();
- }
/* global tree nodes */
--- 106,111 ----
*************** static GTY (()) tree mf_unregister_fndec
*** 269,292 ****
static void
mf_init_extern_trees ()
{
- tree tmp;
-
static int done = 0;
- if (done) return;
! #define mf_lookup_name(id) \
! (tmp = lookup_name (id), \
! (tmp ? tmp : (internal_error ("mudflap: cannot find declarations from mf-runtime.h"), tmp)))
! mf_uintptr_type = TREE_TYPE (mf_lookup_name (get_identifier ("uintptr_t")));
! mf_cache_struct_type = xref_tag (RECORD_TYPE, get_identifier ("__mf_cache"));
mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
! mf_cache_array_decl = mx_flag (mf_lookup_name (get_identifier ("__mf_lookup_cache")));
! mf_cache_shift_decl = mx_flag (mf_lookup_name (get_identifier ("__mf_lc_shift")));
! mf_cache_mask_decl = mx_flag (mf_lookup_name (get_identifier ("__mf_lc_mask")));
! mf_check_fndecl = mf_lookup_name (get_identifier ("__mf_check"));
! mf_register_fndecl = mf_lookup_name (get_identifier ("__mf_register"));
! mf_unregister_fndecl = mf_lookup_name (get_identifier ("__mf_unregister"));
done = 1;
}
--- 136,154 ----
static void
mf_init_extern_trees ()
{
static int done = 0;
! if (done) return;
! mf_uintptr_type = TREE_TYPE (mflang_lookup_decl ("uintptr_t"));
! mf_cache_array_decl = mx_flag (mflang_lookup_decl ("__mf_lookup_cache"));
! mf_cache_struct_type = TREE_TYPE (TREE_TYPE (mf_cache_array_decl));
mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
! mf_cache_shift_decl = mx_flag (mflang_lookup_decl ("__mf_lc_shift"));
! mf_cache_mask_decl = mx_flag (mflang_lookup_decl ("__mf_lc_mask"));
! mf_check_fndecl = mflang_lookup_decl ("__mf_check");
! mf_register_fndecl = mflang_lookup_decl ("__mf_register");
! mf_unregister_fndecl = mflang_lookup_decl ("__mf_unregister");
done = 1;
}
*************** mf_xform_decls (fnbody, fnparams)
*** 1187,1330 ****
/* ------------------------------------------------------------------------ */
! /* global variable transform */
/* A chain of EXPR_STMTs for calling __mf_register() at initialization
time. */
! static GTY (()) tree enqueued_call_stmt_chain = NULL_TREE;
! /* Build and enqueue EXPR_STMT for calling __mf_register on the object
! given by the parameters. One odd thing: the object's address is
! given by the given assembler label string (since that's all we may
! know about a string literal, or the static data thingie may be out
! of the future scope). To turn that into a validish C tree, we
! create a weird synthetic VAR_DECL node.
! */
! static void
! mf_enqueue_register_call (label, regsize, regtype, regname)
! const char* label;
! tree regsize;
! tree regtype;
! tree regname;
{
- tree decltype, decl;
- tree call_params;
tree call_stmt;
! mf_init_extern_trees ();
!
! /* See gcc-checker's c-bounds.c (declare_private_statics) */
! decltype = build_array_type (char_type_node, build_index_type (integer_zero_node));
! decl = mx_flag (build_decl (VAR_DECL, get_identifier (label), decltype));
!
! TREE_STATIC (decl) = 1;
! TREE_READONLY (decl) = 1;
! TREE_ASM_WRITTEN (decl) = 1;
! DECL_IGNORED_P (decl) = 1;
! DECL_INITIAL (decl) = NULL_TREE;
! layout_decl (decl, 0);
! TREE_USED (decl) = 1;
! SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
! DECL_DEFER_OUTPUT (decl) = 1;
! /* XXX: what else? */
! /* rest_of_decl_compilation (decl, build_string (strlen (label) + 1, label), 1, 0); */
! /* make_decl_rtl (decl, build_string (strlen (label) + 1, label)); */
!
! call_params = tree_cons (NULL_TREE,
! convert (mf_uintptr_type,
! mx_flag (build1 (ADDR_EXPR,
! build_pointer_type (TREE_TYPE (decl)),
! decl))),
! tree_cons (NULL_TREE,
! convert (mf_uintptr_type, regsize),
! tree_cons (NULL_TREE,
! regtype,
! tree_cons (NULL_TREE,
! regname,
! NULL_TREE))));
!
! call_stmt = build1 (EXPR_STMT, void_type_node,
! build_function_call (mf_register_fndecl,
! call_params));
/* Link this call into the chain. */
TREE_CHAIN (call_stmt) = enqueued_call_stmt_chain;
enqueued_call_stmt_chain = call_stmt;
}
- /* Emit a synthetic CTOR function for the current file. Populate it
- from the enqueued __mf_register calls. Call the RTL expanders
- inline. */
! static void
! mf_flush_enqueued_calls ()
{
! /* See profile.c (output_func_start_profiler) */
! tree fnname;
! char *nmplus;
! tree fndecl;
! tree body;
! /* Short-circuit! */
! if (enqueued_call_stmt_chain == NULL_TREE)
! return;
! /* Create the COMPOUND_STMT that becomes the new function's body. */
! body = make_node (COMPOUND_STMT);
! COMPOUND_BODY (body) = enqueued_call_stmt_chain;
! enqueued_call_stmt_chain = NULL_TREE;
!
! /* Create a ctor function declaration. */
! nmplus = concat (IDENTIFIER_POINTER (get_file_function_name ('I')), "_mudflap", NULL);
! fnname = get_identifier (nmplus);
! free (nmplus);
! fndecl = build_decl (FUNCTION_DECL, fnname,
! build_function_type (void_type_node, NULL_TREE));
! DECL_EXTERNAL (fndecl) = 0;
! TREE_PUBLIC (fndecl) = ! targetm.have_ctors_dtors;
! TREE_USED (fndecl) = 1;
! DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
!
! /* Now compile the sucker as we go. This is a weird semi-inlined
! form of the guts of the c-parse.y `fndef' production, and a hybrid
! with c_expand_body. */
!
! /* start_function */
! fndecl = pushdecl (fndecl);
! pushlevel (0);
! rest_of_decl_compilation (fndecl, 0, 1, 0);
! announce_function (fndecl);
! current_function_decl = fndecl;
! DECL_INITIAL (fndecl) = error_mark_node;
! DECL_SAVED_TREE (fndecl) = body;
! make_decl_rtl (fndecl, NULL);
!
! /* store_parm_decls */
! init_function_start (fndecl, input_filename, lineno);
! cfun->x_whole_function_mode_p = 1;
!
! /* finish_function */
! poplevel (1, 0, 1);
! BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
!
! /* c_expand_body */
! expand_function_start (fndecl, 0);
! expand_stmt (DECL_SAVED_TREE (fndecl));
! if (lang_expand_function_end)
! (*lang_expand_function_end) ();
! expand_function_end (input_filename, lineno, 0);
! rest_of_compilation (fndecl);
! if (! quiet_flag)
! fflush (asm_out_file);
! current_function_decl = NULL_TREE;
! if (targetm.have_ctors_dtors)
! (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
! DEFAULT_INIT_PRIORITY);
! else
! static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
}
--- 1049,1193 ----
/* ------------------------------------------------------------------------ */
!
!
! /* Remember given node as a static of some kind: global data,
! function-scope static, or an anonymous constant. Its assembler
! label is given.
! */
!
!
! /* A list of globals whose incomplete declarations we encountered.
! Instead of emitting the __mf_register call for them here, it's
! delayed until program finish time. If they're still incomplete by
! then, warnings are emitted. */
!
! static GTY (()) varray_type deferred_static_decls;
! static GTY (()) varray_type deferred_static_decl_labels;
! static int deferred_static_decls_init;
!
! /* What I really want is a std::map<union tree_node,std::string> .. :-( */
/* A chain of EXPR_STMTs for calling __mf_register() at initialization
time. */
! static GTY (()) tree enqueued_call_stmt_chain;
! void
! mudflap_enqueue_decl (obj, label)
! tree obj;
! const char *label;
! {
! if (TREE_MUDFLAPPED_P (obj))
! return;
! /*
! fprintf (stderr, "enqueue_decl obj=`");
! print_generic_expr (stderr, obj, 0);
! fprintf (stderr, "' label=`%s'\n", label);
! */
!
! if (COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (obj)))
! {
! /* NB: the above condition doesn't require TREE_USED or
! TREE_ADDRESSABLE. That's because this object may be a global
! only used from other compilation units. XXX: Maybe static
! objects could require those attributes being set. */
! tree call_stmt =
! mflang_register_call (label,
! size_in_bytes (TREE_TYPE (obj)),
! build_int_2 (3, 0), /* __MF_TYPE_STATIC */
! mf_varname_tree (obj));
!
! /* Link this call into the chain. */
! TREE_CHAIN (call_stmt) = enqueued_call_stmt_chain;
! enqueued_call_stmt_chain = call_stmt;
! }
! else
! {
! unsigned i;
! int found_p;
!
! if (! deferred_static_decls_init)
! {
! deferred_static_decls_init = 1;
! VARRAY_TREE_INIT (deferred_static_decls, 10, "deferred static list");
! VARRAY_CHAR_PTR_INIT (deferred_static_decl_labels, 10, "label list");
! }
!
! /* Ugh, linear search... */
! found_p = 0;
! for (i=0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
! if (VARRAY_TREE (deferred_static_decls, i) == obj)
! found_p = 1;
!
! if (found_p)
! warning_with_decl (obj, "mudflap cannot track lifetime of `%s'",
! IDENTIFIER_POINTER (DECL_NAME (obj)));
! else
! {
! VARRAY_PUSH_TREE (deferred_static_decls, obj);
! VARRAY_PUSH_CHAR_PTR (deferred_static_decl_labels, (char *) label);
! }
! }
! }
!
!
! void
! mudflap_enqueue_constant (obj, label)
! tree obj;
! const char *label;
{
tree call_stmt;
! if (TREE_MUDFLAPPED_P (obj))
! return;
+ call_stmt =
+ (TREE_CODE (obj) == STRING_CST)
+ ? mflang_register_call (label,
+ build_int_2 (TREE_STRING_LENGTH (obj), 0),
+ build_int_2 (3, 0), /* __MF_TYPE_STATIC */
+ mx_flag (fix_string_type
+ (build_string (15, "string literal"))))
+ : mflang_register_call (label,
+ size_in_bytes (TREE_TYPE (obj)),
+ build_int_2 (3, 0), /* __MF_TYPE_STATIC */
+ mx_flag (fix_string_type
+ (build_string (9, "constant"))));
+
/* Link this call into the chain. */
TREE_CHAIN (call_stmt) = enqueued_call_stmt_chain;
enqueued_call_stmt_chain = call_stmt;
}
! /* Emit any file-wide instrumentation. */
! void
! mudflap_finish_file ()
{
! /* Try to give the deferred objects one final try. */
! if (deferred_static_decls_init)
! {
! unsigned i;
! for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
! {
! tree obj = VARRAY_TREE (deferred_static_decls, i);
! const char *label = VARRAY_CHAR_PTR (deferred_static_decl_labels, i);
! /* Call enqueue_decl again on the same object it has previously
! put into the table. (It won't modify the table this time, so
! infinite iteration is not a problem.) */
! mudflap_enqueue_decl (obj, label);
! }
!
! VARRAY_CLEAR (deferred_static_decls);
! VARRAY_CLEAR (deferred_static_decl_labels);
! }
!
! mflang_flush_calls (enqueued_call_stmt_chain);
}
Index: tree-mudflap.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-mudflap.h,v
retrieving revision 1.1.2.2
diff -c -p -r1.1.2.2 tree-mudflap.h
*** tree-mudflap.h 20 Aug 2002 19:21:40 -0000 1.1.2.2
--- tree-mudflap.h 13 Jan 2003 23:04:33 -0000
***************
*** 1,5 ****
/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
! Copyright (C) 2001, 2002 Free Software Foundation, Inc.
Contributed by Frank Ch. Eigler <fche@redhat.com>
This file is part of GCC.
--- 1,5 ----
/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
! Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Frank Ch. Eigler <fche@redhat.com>
This file is part of GCC.
*************** extern void mudflap_c_function PARAMS ((
*** 26,30 ****
--- 26,36 ----
extern void mudflap_enqueue_decl PARAMS ((tree, const char *));
extern void mudflap_enqueue_constant PARAMS ((tree, const char *));
extern void mudflap_finish_file PARAMS ((void));
+
+ /* To be provided by a front-end interface module. */
+ extern tree mflang_lookup_decl PARAMS ((const char *));
+ extern tree mflang_register_call PARAMS ((const char*, tree, tree, tree));
+ extern void mflang_flush_calls PARAMS ((tree));
+
#endif /* TREE_MUDFLAP_H */
Index: tree-nomudflap.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-nomudflap.c,v
retrieving revision 1.1.2.4
diff -c -p -r1.1.2.4 tree-nomudflap.c
*** tree-nomudflap.c 3 Dec 2002 22:54:34 -0000 1.1.2.4
--- tree-nomudflap.c 13 Jan 2003 23:04:33 -0000
*************** mudflap_enqueue_decl (obj, label)
*** 58,64 ****
tree obj ATTRIBUTE_UNUSED;
const char *label ATTRIBUTE_UNUSED;
{
! abort ();
}
--- 58,64 ----
tree obj ATTRIBUTE_UNUSED;
const char *label ATTRIBUTE_UNUSED;
{
! internal_error ("mudflap: this language is not supported");
}
*************** mudflap_enqueue_constant (obj, label)
*** 67,73 ****
tree obj ATTRIBUTE_UNUSED;
const char *label ATTRIBUTE_UNUSED;
{
! abort ();
}
--- 67,73 ----
tree obj ATTRIBUTE_UNUSED;
const char *label ATTRIBUTE_UNUSED;
{
! internal_error ("mudflap: this language is not supported");
}
*************** mudflap_enqueue_constant (obj, label)
*** 77,83 ****
void
mudflap_finish_file ()
{
! abort ();
}
--- 77,83 ----
void
mudflap_finish_file ()
{
! internal_error ("mudflap: this language is not supported");
}
Index: cp/Make-lang.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/Make-lang.in,v
retrieving revision 1.115.2.19
diff -c -p -r1.115.2.19 Make-lang.in
*** cp/Make-lang.in 3 Jan 2003 01:57:28 -0000 1.115.2.19
--- cp/Make-lang.in 13 Jan 2003 23:04:34 -0000
*************** CXX_OBJS = cp/call.o cp/decl.o cp/expr.o
*** 87,93 ****
cp/class.o cp/decl2.o cp/error.o cp/lex.o cp/parse.o cp/ptree.o cp/rtti.o \
cp/spew.o cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o \
! cp/optimize.o cp/mangle.o cp/cp-lang.o cp/cp-simplify.o
# Use loose warnings for this front end.
cp-warn =
--- 87,94 ----
cp/class.o cp/decl2.o cp/error.o cp/lex.o cp/parse.o cp/ptree.o cp/rtti.o \
cp/spew.o cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o \
! cp/optimize.o cp/mangle.o cp/cp-lang.o cp/cp-simplify.o \
! tree-mudflap.o cp/cp-mudflap.o
# Use loose warnings for this front end.
cp-warn =
*************** cp/parse.o: cp/parse.c $(CXX_TREE_H) $(T
*** 277,282 ****
--- 278,285 ----
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
$(srcdir)/cp/parse.c $(OUTPUT_OPTION)
cp/cp-simplify.o: cp/cp-simplify.c $(CXX_TREE_H) toplev.h c-common.h \
+ $(TM_H) coretypes.h
+ cp/cp-mudflap.o: cp/cp-mudflap.c $(CXX_TREE_H) toplev.h c-common.h \
$(TM_H) coretypes.h
#
Index: cp/cp-mudflap.c
===================================================================
RCS file: cp/cp-mudflap.c
diff -N cp/cp-mudflap.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- cp/cp-mudflap.c 13 Jan 2003 23:04:34 -0000
***************
*** 0 ****
--- 1,218 ----
+ /* Mudflap: narrow-pointer bounds-checking by tree rewriting:
+ C++ front-end interface.
+
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Frank Ch. Eigler <fche@redhat.com>
+ and Graydon Hoare <graydon@redhat.com>
+
+ This file is part of GCC.
+
+ 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
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ 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, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+
+ #include "config.h"
+ #include "errors.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "tree.h"
+ #include "tree-inline.h"
+ #include "cp-tree.h"
+ #include "c-common.h"
+ #include "diagnostic.h"
+ #include "output.h"
+ #include "varray.h"
+ #include "tree-mudflap.h"
+ #include "target.h"
+ #include "flags.h"
+ #include "rtl.h"
+ #include "toplev.h"
+
+
+
+ /* ------------------------------------------------------------------------ */
+
+ static tree mx_flag PARAMS ((tree));
+
+ /* XXX: copied from tree-mudflap.c */
+ static tree
+ mx_flag (t)
+ tree t;
+ {
+ if (!t)
+ abort ();
+ #define MARK_TREE_MUDFLAPPED(tree) do { TREE_BOUNDED (tree) = 1; } while (0)
+ MARK_TREE_MUDFLAPPED(t);
+ return t;
+ }
+
+
+
+ /* ------------------------------------------------------------------------ */
+
+
+
+ /* Initialize the global tree nodes that correspond to mf-runtime.h
+ declarations. */
+ tree
+ mflang_lookup_decl (name)
+ const char* name;
+ {
+ tree decl = lookup_name (get_identifier (name), 1);
+ if (decl == NULL_TREE)
+ internal_error ("mudflap: cannot find declaration of `%s' from mf-runtime.h",
+ name);
+
+ return decl;
+ }
+
+
+
+ /* Build and return EXPR_STMT for calling __mf_register on the object
+ given by the parameters. One odd thing: the object's address is
+ given by the given assembler label string (since that's all we may
+ know about a string literal, or the static data thingie may be out
+ of the future scope). To turn that into a validish C tree, we
+ create a weird synthetic VAR_DECL node.
+ */
+
+ tree
+ mflang_register_call (label, regsize, regtype, regname)
+ const char* label;
+ tree regsize;
+ tree regtype;
+ tree regname;
+ {
+ tree decltype, decl;
+ tree call_params;
+ tree call_stmt;
+
+ /* XXX: would be nicer not to duplicate these. */
+ tree mf_uintptr_type = TREE_TYPE (mflang_lookup_decl ("uintptr_t"));
+ tree mf_register_fndecl = mflang_lookup_decl ("__mf_register");
+
+ /* See gcc-checker's c-bounds.c (declare_private_statics) */
+ decltype = build_array_type (char_type_node, build_index_type (integer_zero_node));
+ decl = mx_flag (build_decl (VAR_DECL, get_identifier (label), decltype));
+
+ TREE_STATIC (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ TREE_ASM_WRITTEN (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ DECL_INITIAL (decl) = NULL_TREE;
+ layout_decl (decl, 0);
+ TREE_USED (decl) = 1;
+ SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
+ DECL_DEFER_OUTPUT (decl) = 1;
+ /* XXX: what else? */
+ /* rest_of_decl_compilation (decl, build_string (strlen (label) + 1, label), 1, 0); */
+ /* make_decl_rtl (decl, build_string (strlen (label) + 1, label)); */
+
+ call_params = tree_cons (NULL_TREE,
+ convert (mf_uintptr_type,
+ mx_flag (build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (decl)),
+ decl))),
+ tree_cons (NULL_TREE,
+ convert (mf_uintptr_type, regsize),
+ tree_cons (NULL_TREE,
+ regtype,
+ tree_cons (NULL_TREE,
+ regname,
+ NULL_TREE))));
+
+ call_stmt = build1 (EXPR_STMT, void_type_node,
+ build_function_call (mf_register_fndecl,
+ call_params));
+
+ return call_stmt;
+ }
+
+
+
+ /* Emit a synthetic CTOR function for the current file. Populate it
+ from the enqueued __mf_register calls. Call the RTL expanders
+ inline. */
+
+ void
+ mflang_flush_calls (enqueued_call_stmt_chain)
+ tree enqueued_call_stmt_chain;
+ {
+ /* See profile.c (output_func_start_profiler) */
+ tree fnname;
+ char *nmplus;
+ tree fndecl;
+ tree body;
+
+ /* Short-circuit! */
+ if (enqueued_call_stmt_chain == NULL_TREE)
+ return;
+
+ /* Create the COMPOUND_STMT that becomes the new function's body. */
+ body = make_node (COMPOUND_STMT);
+ COMPOUND_BODY (body) = enqueued_call_stmt_chain;
+ enqueued_call_stmt_chain = NULL_TREE;
+
+ /* Create a ctor function declaration. */
+ nmplus = concat (IDENTIFIER_POINTER (get_file_function_name ('I')), "_mudflap", NULL);
+ fnname = get_identifier (nmplus);
+ free (nmplus);
+ fndecl = build_decl (FUNCTION_DECL, fnname,
+ build_function_type (void_type_node, NULL_TREE));
+ DECL_EXTERNAL (fndecl) = 0;
+ TREE_PUBLIC (fndecl) = ! targetm.have_ctors_dtors;
+ TREE_USED (fndecl) = 1;
+ DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
+
+ /* Now compile the sucker as we go. This is a weird semi-inlined
+ form of the guts of the c-parse.y `fndef' production, and a hybrid
+ with c_expand_body. */
+
+ /* start_function */
+ fndecl = pushdecl (fndecl);
+ pushlevel (0);
+ rest_of_decl_compilation (fndecl, 0, 1, 0);
+ announce_function (fndecl);
+ current_function_decl = fndecl;
+ DECL_INITIAL (fndecl) = error_mark_node;
+ DECL_SAVED_TREE (fndecl) = body;
+ make_decl_rtl (fndecl, NULL);
+
+ /* store_parm_decls */
+ init_function_start (fndecl, input_filename, lineno);
+ cfun->x_whole_function_mode_p = 1;
+
+ /* finish_function */
+ poplevel (1, 0, 1);
+ BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+
+ /* c_expand_body */
+ expand_function_start (fndecl, 0);
+ expand_stmt (DECL_SAVED_TREE (fndecl));
+ if (lang_expand_function_end)
+ (*lang_expand_function_end) ();
+ expand_function_end (input_filename, lineno, 0);
+ rest_of_compilation (fndecl);
+ if (! quiet_flag)
+ fflush (asm_out_file);
+ current_function_decl = NULL_TREE;
+
+ if (targetm.have_ctors_dtors)
+ (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
+ else
+ static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+ }
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.540.2.20
diff -c -p -r1.540.2.20 decl2.c
*** cp/decl2.c 3 Jan 2003 01:57:34 -0000 1.540.2.20
--- cp/decl2.c 13 Jan 2003 23:04:34 -0000
*************** Boston, MA 02111-1307, USA. */
*** 47,52 ****
--- 47,54 ----
#include "cpplib.h"
#include "target.h"
#include "c-common.h"
+ #include "tree-mudflap.h"
+
extern cpp_reader *parse_in;
/* This structure contains information about the initializations
*************** finish_file ()
*** 2714,2719 ****
--- 2716,2725 ----
timevar_push (TV_VARCONST);
emit_support_tinfos ();
+
+ /* Emit mudflap static registration function. */
+ if (flag_mudflap)
+ mudflap_finish_file ();
do
{
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/optimize.c,v
retrieving revision 1.81.10.11
diff -c -p -r1.81.10.11 optimize.c
*** cp/optimize.c 3 Jan 2003 01:57:36 -0000 1.81.10.11
--- cp/optimize.c 13 Jan 2003 23:04:34 -0000
*************** Software Foundation, 59 Temple Place - S
*** 36,41 ****
--- 36,42 ----
#include "hashtab.h"
#include "debug.h"
#include "tree-inline.h"
+ #include "tree-mudflap.h"
#include "flags.h"
#include "langhooks.h"
#include "diagnostic.h"
*************** optimize_function (tree fn)
*** 84,89 ****
--- 85,100 ----
{
/* Debugging dump after simplification. */
dump_function (TDI_simple, fn);
+
+ if (flag_mudflap)
+ {
+ mudflap_c_function (fn);
+
+ /* Simplify mudflap instrumentation. FIXME Long term: Would it
+ be better for mudflap to simplify each tree as it generates
+ them? */
+ simplify_function_tree (fn);
+ }
/* Invoke the SSA tree optimizer. */
if (optimize >= 1 && 0)
More information about the Gcc-patches
mailing list