mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 22:51:06 +08:00
[multiple changes]
2009-04-14 Diego Novillo <dnovillo@google.com> Le-Chun Wu <lcwu@google.com> * configure.ac: Add --enable-plugin support. Define ENABLE_PLUGIN and PLUGINLIBS when specified. * Makefile.in (PLUGIN_H): Define. Export ENABLE_PLUGIN and GMPINC to site.exp. Add PLUGINLIBS to link command. Add/modify dependencies for plugin.o and files including plugin.h. (plugin.o): New. * config.in: Regenerate. * opts.c (common_handle_option): Handle OPT_fplugin_ and OPT_fplugin_arg_. 2009-04-14 Le-Chun Wu <lcwu@google.com> * tree-pass.h (register_one_dump_file): Add a prototype for register_one_dump_file. * toplev.c (compile_file): Call initialize_plugins. (do_compile): Call invoke_plugin_callbacks. (toplev_main): Call invoke_plugin_callbacks. * common.opt: Add -fplugin= and -fplugin-arg-. * gcc-plugin.h: New public header file for plugins to include. * plugin.c: New source file. * plugin.h: New internal header file. * passes.c (register_one_dump_file): Make it external. * c-parser.c (c_parser_declspecs): Call invoke_plugin_callbacks. 2009-04-14 Diego Novillo <dnovillo@google.com> * doc/plugins.texi: New. * doc/gccint.texi: Add reference to Plugins chapter. * doc/invoke.texi: Document -fplugin and -fplugin-arg * diagnostic.c (diagnostic_report_diagnostic): Warn about loaded plugins, if any. * timevar.def (TV_PLUGIN_INIT): Define. (TV_PLUGIN_RUN): Define. * plugin.c: Include timevar.h (plugins_active_p): New. (dump_active_plugins): New. (debug_active_plugins): New. cp/ChangeLog 2009-04-14 Le-Chun Wu <lcwu@google.com> * Make-lang.in: Modify dependencies of files including plugin.h. * decl.c (finish_function): Call invoke_plugin_callbacks. * parser.c (cp_parser_type_specifier): Call invoke_plugin_callbacks. From-SVN: r146059
This commit is contained in:
parent
5061725708
commit
68a607d814
@ -1,3 +1,47 @@
|
||||
2009-04-14 Diego Novillo <dnovillo@google.com>
|
||||
Le-Chun Wu <lcwu@google.com>
|
||||
|
||||
* configure.ac: Add --enable-plugin support.
|
||||
Define ENABLE_PLUGIN and PLUGINLIBS when specified.
|
||||
* Makefile.in (PLUGIN_H): Define.
|
||||
Export ENABLE_PLUGIN and GMPINC to site.exp.
|
||||
Add PLUGINLIBS to link command.
|
||||
Add/modify dependencies for plugin.o and files including plugin.h.
|
||||
(plugin.o): New.
|
||||
* config.in: Regenerate.
|
||||
|
||||
* opts.c (common_handle_option): Handle OPT_fplugin_ and
|
||||
OPT_fplugin_arg_.
|
||||
|
||||
2009-04-14 Le-Chun Wu <lcwu@google.com>
|
||||
|
||||
* tree-pass.h (register_one_dump_file): Add a prototype for
|
||||
register_one_dump_file.
|
||||
* toplev.c (compile_file): Call initialize_plugins.
|
||||
(do_compile): Call invoke_plugin_callbacks.
|
||||
(toplev_main): Call invoke_plugin_callbacks.
|
||||
* common.opt: Add -fplugin= and -fplugin-arg-.
|
||||
* gcc-plugin.h: New public header file for plugins to include.
|
||||
* plugin.c: New source file.
|
||||
* plugin.h: New internal header file.
|
||||
* passes.c (register_one_dump_file): Make it external.
|
||||
|
||||
* c-parser.c (c_parser_declspecs): Call invoke_plugin_callbacks.
|
||||
|
||||
2009-04-14 Diego Novillo <dnovillo@google.com>
|
||||
|
||||
* doc/plugins.texi: New.
|
||||
* doc/gccint.texi: Add reference to Plugins chapter.
|
||||
* doc/invoke.texi: Document -fplugin and -fplugin-arg
|
||||
* diagnostic.c (diagnostic_report_diagnostic): Warn about
|
||||
loaded plugins, if any.
|
||||
* timevar.def (TV_PLUGIN_INIT): Define.
|
||||
(TV_PLUGIN_RUN): Define.
|
||||
* plugin.c: Include timevar.h
|
||||
(plugins_active_p): New.
|
||||
(dump_active_plugins): New.
|
||||
(debug_active_plugins): New.
|
||||
|
||||
2009-04-14 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* config/sol2.h (LINK_ARCH32_SPEC_BASE): Use %R with absolute
|
||||
@ -21,7 +65,7 @@
|
||||
|
||||
2008-12-19 Diego Novillo <dnovillo@google.com>
|
||||
|
||||
* cgraph.c (dump_cgraph_node): Show memory address of NODE.
|
||||
* cgraph.c (dump_cgraph_node): Show memory address of NODE.
|
||||
|
||||
2000-04-14 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
|
@ -283,6 +283,9 @@ PPLINC = @PPLINC@
|
||||
CLOOGLIBS = @CLOOGLIBS@
|
||||
CLOOGINC = @CLOOGINC@
|
||||
|
||||
# Libs and linker option needed for plugin support
|
||||
PLUGINLIBS = @pluginlibs@
|
||||
|
||||
CPPLIB = ../libcpp/libcpp.a
|
||||
CPPINC = -I$(srcdir)/../libcpp/include
|
||||
|
||||
@ -872,6 +875,7 @@ EBIMAP_H = ebitmap.h sbitmap.h
|
||||
IPA_PROP_H = ipa-prop.h $(TREE_H) vec.h $(CGRAPH_H)
|
||||
GSTAB_H = gstab.h stab.def
|
||||
BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h
|
||||
PLUGIN_H = plugin.h gcc-plugin.h
|
||||
|
||||
#
|
||||
# Now figure out from those variables how to compile and link.
|
||||
@ -906,7 +910,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
|
||||
# How to link with both our special library facilities
|
||||
# and the system's installed libraries.
|
||||
LIBS = @LIBS@ $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBIBERTY) $(LIBDECNUMBER)
|
||||
BACKENDLIBS = $(CLOOGLIBS) $(PPLLIBS) $(GMPLIBS)
|
||||
BACKENDLIBS = $(CLOOGLIBS) $(PPLLIBS) $(GMPLIBS) $(PLUGINLIBS)
|
||||
# Any system libraries needed just for GNAT.
|
||||
SYSLIBS = @GNAT_LIBEXC@
|
||||
|
||||
@ -1148,6 +1152,7 @@ OBJS-common = \
|
||||
opts.o \
|
||||
params.o \
|
||||
passes.o \
|
||||
plugin.o \
|
||||
pointer-set.o \
|
||||
postreload-gcse.o \
|
||||
postreload.o \
|
||||
@ -1800,7 +1805,7 @@ c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
||||
c-parser.o : c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
||||
$(GGC_H) $(TIMEVAR_H) $(C_TREE_H) $(INPUT_H) $(FLAGS_H) $(TOPLEV_H) output.h \
|
||||
$(CPPLIB_H) gt-c-parser.h $(RTL_H) langhooks.h $(C_COMMON_H) $(C_PRAGMA_H) \
|
||||
vec.h $(TARGET_H) $(CGRAPH_H)
|
||||
vec.h $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H)
|
||||
|
||||
srcextra: gcc.srcextra lang.srcextra
|
||||
|
||||
@ -2422,11 +2427,12 @@ fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(GIMPLE_H)
|
||||
diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(TREE_H) version.h $(TM_P_H) $(FLAGS_H) $(INPUT_H) $(TOPLEV_H) intl.h \
|
||||
$(DIAGNOSTIC_H) langhooks.h $(LANGHOOKS_DEF_H) diagnostic.def opts.h
|
||||
$(DIAGNOSTIC_H) langhooks.h $(LANGHOOKS_DEF_H) diagnostic.def opts.h \
|
||||
$(PLUGIN_H)
|
||||
opts.o : opts.c opts.h options.h $(TOPLEV_H) $(CONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(EXPR_H) $(RTL_H) \
|
||||
output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
|
||||
$(FLAGS_H) $(PARAMS_H) tree-pass.h $(DBGCNT_H) debug.h varray.h
|
||||
$(FLAGS_H) $(PARAMS_H) tree-pass.h $(DBGCNT_H) debug.h varray.h $(PLUGIN_H)
|
||||
opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h intl.h
|
||||
targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
|
||||
@ -2443,7 +2449,7 @@ toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
||||
langhooks.h insn-flags.h $(CFGLAYOUT_H) $(CFGLOOP_H) hosthooks.h \
|
||||
$(CGRAPH_H) $(COVERAGE_H) alloc-pool.h $(GGC_H) $(INTEGRATE_H) \
|
||||
opts.h params.def tree-mudflap.h $(REAL_H) tree-pass.h $(GIMPLE_H) \
|
||||
tree-ssa-alias.h
|
||||
tree-ssa-alias.h $(PLUGIN_H)
|
||||
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
|
||||
-DTARGET_NAME=\"$(target_noncanonical)\" \
|
||||
-c $(srcdir)/toplev.c $(OUTPUT_OPTION)
|
||||
@ -2459,6 +2465,9 @@ passes.o : passes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
||||
$(GGC_H) $(INTEGRATE_H) $(CPPLIB_H) opts.h $(TREE_FLOW_H) $(TREE_INLINE_H) \
|
||||
gt-passes.h $(DF_H) $(PREDICT_H)
|
||||
|
||||
plugin.o : plugin.c $(PLUGIN_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
errors.h $(TOPLEV_H) $(TREE_H) tree-pass.h intl.h
|
||||
|
||||
main.o : main.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TOPLEV_H)
|
||||
|
||||
host-default.o : host-default.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
|
||||
@ -4247,6 +4256,10 @@ site.exp: ./config.status Makefile
|
||||
@echo "set TEST_GCC_EXEC_PREFIX \"$(libdir)/gcc/\"" >> ./tmp0
|
||||
@echo "set TESTING_IN_BUILD_TREE 1" >> ./tmp0
|
||||
@echo "set HAVE_LIBSTDCXX_V3 1" >> ./tmp0
|
||||
@if test "@enable_plugin@" = "yes" ; then \
|
||||
echo "set ENABLE_PLUGIN 1" >> ./tmp0; \
|
||||
echo "set GMPINC \"$(GMPINC)\"" >> ./tmp0; \
|
||||
fi
|
||||
# If newlib has been configured, we need to pass -B to gcc so it can find
|
||||
# newlib's crt0.o if it exists. This will cause a "path prefix not used"
|
||||
# message if it doesn't, but the testsuite is supposed to ignore the message -
|
||||
|
@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "langhooks-def.h"
|
||||
#include "pointer-set.h"
|
||||
#include "gimple.h"
|
||||
#include "plugin.h"
|
||||
|
||||
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
|
||||
enum decl_context
|
||||
@ -7261,6 +7262,9 @@ struct c_declspecs *
|
||||
declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
|
||||
{
|
||||
tree type = spec.spec;
|
||||
|
||||
invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type);
|
||||
|
||||
specs->non_sc_seen_p = true;
|
||||
specs->declspecs_seen_p = true;
|
||||
specs->type_seen_p = true;
|
||||
|
@ -57,6 +57,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "vec.h"
|
||||
#include "target.h"
|
||||
#include "cgraph.h"
|
||||
#include "plugin.h"
|
||||
|
||||
|
||||
/* Initialization routine for this file. */
|
||||
|
@ -854,6 +854,14 @@ fpie
|
||||
Common Report Var(flag_pie,1) VarExists
|
||||
Generate position-independent code for executables if possible (small mode)
|
||||
|
||||
fplugin=
|
||||
Common Joined RejectNegative
|
||||
Specify a plugin to load
|
||||
|
||||
fplugin-arg-
|
||||
Common Joined RejectNegative
|
||||
-fplugin-arg-<name>-<key>[=<value>] Specify argument <key>=<value> for plugin <name>
|
||||
|
||||
fpredictive-commoning
|
||||
Common Report Var(flag_predictive_commoning) Optimization
|
||||
Run predictive commoning optimization.
|
||||
|
@ -108,6 +108,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to enable plugin support. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef ENABLE_PLUGIN
|
||||
#endif
|
||||
|
||||
|
||||
/* Define if you want all operations on RTL (the basic data structure of the
|
||||
optimizer and back end) to be checked for dynamic type safety at runtime.
|
||||
This is quite expensive. */
|
||||
|
247
gcc/configure
vendored
247
gcc/configure
vendored
@ -458,7 +458,7 @@ ac_includes_default="\
|
||||
# include <unistd.h>
|
||||
#endif"
|
||||
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS STMP_FIXINC collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN OBJDUMP ac_ct_OBJDUMP ac_ct_AR STRIP ac_ct_STRIP lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump gcc_cv_readelf libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines use_gcc_stdint c_target_objs cxx_target_objs fortran_target_objs target_cpu_default GMPLIBS GMPINC PPLLIBS PPLINC CLOOGLIBS CLOOGINC LIBOBJS LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical build_libsubdir build_subdir host_subdir target_subdir GENINSRC CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE NO_MINUS_C_MINUS_O OUTPUT_OPTION CPP EGREP loose_warn strict_warn warn_cflags nocommon_flag TREEBROWSER valgrind_path valgrind_path_defines valgrind_command coverage_flags enable_multilib enable_decimal_float enable_fixed_point enable_shared TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE CROSS_SYSTEM_HEADER_DIR onestep PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI datarootdir docdir htmldir SET_MAKE AWK LN_S LN RANLIB ac_ct_RANLIB ranlib_flags INSTALL INSTALL_PROGRAM INSTALL_DATA make_compare_target have_mktemp_command MAKEINFO BUILD_INFO GENERATED_MANPAGES FLEX BISON NM AR COLLECT2_LIBS GNAT_LIBEXC LDEXP_LIB LIBICONV LTLIBICONV LIBICONV_DEP manext objext gthread_flags extra_modes_file extra_opt_files USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT CROSS ALL SYSTEM_HEADER_DIR inhibit_libc CC_FOR_BUILD BUILD_CFLAGS BUILD_LDFLAGS STMP_FIXINC collect2 LIBTOOL SED FGREP GREP LD DUMPBIN ac_ct_DUMPBIN OBJDUMP ac_ct_OBJDUMP ac_ct_AR STRIP ac_ct_STRIP lt_ECHO DSYMUTIL ac_ct_DSYMUTIL NMEDIT ac_ct_NMEDIT LIPO ac_ct_LIPO OTOOL ac_ct_OTOOL OTOOL64 ac_ct_OTOOL64 objdir enable_fast_install gcc_cv_as ORIGINAL_AS_FOR_TARGET gcc_cv_ld ORIGINAL_LD_FOR_TARGET gcc_cv_nm ORIGINAL_NM_FOR_TARGET gcc_cv_objdump gcc_cv_readelf libgcc_visibility GGC zlibdir zlibinc MAINT gcc_tooldir dollar slibdir subdirs srcdir all_compilers all_gtfiles all_lang_makefrags all_lang_makefiles all_languages all_selected_languages build_exeext build_install_headers_dir build_xm_file_list build_xm_include_list build_xm_defines build_file_translate check_languages cpp_install_dir xmake_file tmake_file extra_gcc_objs extra_headers_list extra_objs extra_parts extra_passes extra_programs float_h_file gcc_config_arguments gcc_gxx_include_dir host_exeext host_xm_file_list host_xm_include_list host_xm_defines out_host_hook_obj install lang_opt_files lang_specs_files lang_tree_files local_prefix md_file objc_boehm_gc out_file out_object_file thread_file tm_file_list tm_include_list tm_defines tm_p_file_list tm_p_include_list xm_file_list xm_include_list xm_defines use_gcc_stdint c_target_objs cxx_target_objs fortran_target_objs target_cpu_default GMPLIBS GMPINC PPLLIBS PPLINC CLOOGLIBS CLOOGINC pluginlibs enable_plugin LIBOBJS LTLIBOBJS'
|
||||
ac_subst_files='language_hooks'
|
||||
ac_pwd=`pwd`
|
||||
|
||||
@ -1084,6 +1084,7 @@ Optional Features:
|
||||
--enable-version-specific-runtime-libs
|
||||
specify that runtime libraries should be
|
||||
installed in a compiler-specific directory
|
||||
--enable-plugin enable plugin support
|
||||
|
||||
Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
@ -14348,13 +14349,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
|
||||
else
|
||||
lt_cv_nm_interface="BSD nm"
|
||||
echo "int some_variable = 0;" > conftest.$ac_ext
|
||||
(eval echo "\"\$as_me:14351: $ac_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:14352: $ac_compile\"" >&5)
|
||||
(eval "$ac_compile" 2>conftest.err)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:14354: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval echo "\"\$as_me:14355: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
|
||||
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
|
||||
cat conftest.err >&5
|
||||
(eval echo "\"\$as_me:14357: output\"" >&5)
|
||||
(eval echo "\"\$as_me:14358: output\"" >&5)
|
||||
cat conftest.out >&5
|
||||
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
|
||||
lt_cv_nm_interface="MS dumpbin"
|
||||
@ -15511,7 +15512,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 15514 "configure"' > conftest.$ac_ext
|
||||
echo '#line 15515 "configure"' > conftest.$ac_ext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@ -16810,11 +16811,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:16813: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:16814: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:16817: \$? = $ac_status" >&5
|
||||
echo "$as_me:16818: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -17149,11 +17150,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:17152: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:17153: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:17156: \$? = $ac_status" >&5
|
||||
echo "$as_me:17157: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -17254,11 +17255,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:17257: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:17258: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:17261: \$? = $ac_status" >&5
|
||||
echo "$as_me:17262: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@ -17309,11 +17310,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:17312: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:17313: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:17316: \$? = $ac_status" >&5
|
||||
echo "$as_me:17317: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@ -20121,7 +20122,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 20124 "configure"
|
||||
#line 20125 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -20217,7 +20218,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 20220 "configure"
|
||||
#line 20221 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -24680,6 +24681,220 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
# Check for plugin support
|
||||
# Check whether --enable-plugin or --disable-plugin was given.
|
||||
if test "${enable_plugin+set}" = set; then
|
||||
enableval="$enable_plugin"
|
||||
enable_plugin=$enableval
|
||||
else
|
||||
enable_plugin=yes; default_plugin=yes
|
||||
fi;
|
||||
|
||||
pluginlibs=
|
||||
if test x"$enable_plugin" = x"yes"; then
|
||||
# Check that the host supports -rdynamic and -ldl
|
||||
have_rdynamic=no
|
||||
have_dl=no
|
||||
saved_LDFLAGS="$LDFLAGS"
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS=
|
||||
|
||||
# Check -rdynamic
|
||||
LDFLAGS="$LDFLAGS -rdynamic"
|
||||
echo "$as_me:$LINENO: checking for -rdynamic" >&5
|
||||
echo $ECHO_N "checking for -rdynamic... $ECHO_C" >&6
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
echo "$as_me:$LINENO: result: yes" >&5
|
||||
echo "${ECHO_T}yes" >&6; have_rdynamic=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
echo "$as_me:$LINENO: result: no" >&5
|
||||
echo "${ECHO_T}no" >&6
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
if test x"$have_rdynamic" = x"yes" ; then
|
||||
pluginlibs="-rdynamic"
|
||||
fi
|
||||
|
||||
# Check -ldl
|
||||
LDFLAGS="$LDFLAGS -ldl"
|
||||
echo "$as_me:$LINENO: checking for -ldl" >&5
|
||||
echo $ECHO_N "checking for -ldl... $ECHO_C" >&6
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <dlfcn.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
volatile int f = 0; if (f) dlopen ("dummy", 0);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
echo "$as_me:$LINENO: result: yes" >&5
|
||||
echo "${ECHO_T}yes" >&6; have_dl=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
echo "$as_me:$LINENO: result: no" >&5
|
||||
echo "${ECHO_T}no" >&6
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
if test x"$have_dl" = x"yes"; then
|
||||
pluginlibs="$pluginlibs -ldl"
|
||||
fi
|
||||
|
||||
# Check that we can build shared objects with -fPIC -shared
|
||||
LDFLAGS="$LDFLAGS -fPIC -shared"
|
||||
echo "$as_me:$LINENO: checking for -fPIC -shared" >&5
|
||||
echo $ECHO_N "checking for -fPIC -shared... $ECHO_C" >&6
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
extern int X;
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return X == 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
echo "$as_me:$LINENO: result: yes" >&5
|
||||
echo "${ECHO_T}yes" >&6; have_pic_shared=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
echo "$as_me:$LINENO: result: no" >&5
|
||||
echo "${ECHO_T}no" >&6; have_pic_shared=no
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
if test x"$have_pic_shared" != x"yes"; then
|
||||
pluginlibs=
|
||||
enable_plugin=no
|
||||
fi
|
||||
|
||||
# If plugin support had been requested but not available, fail.
|
||||
if test x"$enable_plugin" = x"no" ; then
|
||||
if test x"$default_plugin" != x"yes"; then
|
||||
{ { echo "$as_me:$LINENO: error:
|
||||
Building GCC with plugin support requires a host that supports
|
||||
-fPIC, -shared, -ldl and -rdynamic." >&5
|
||||
echo "$as_me: error:
|
||||
Building GCC with plugin support requires a host that supports
|
||||
-fPIC, -shared, -ldl and -rdynamic." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
fi
|
||||
|
||||
LDFLAGS="$saved_LDFLAGS"
|
||||
LIBS="$saved_LIBS"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test x"$enable_plugin" = x"yes"; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define ENABLE_PLUGIN 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
# Configure the subdirectories
|
||||
# AC_CONFIG_SUBDIRS($subdirs)
|
||||
|
||||
@ -25524,6 +25739,8 @@ s,@PPLLIBS@,$PPLLIBS,;t t
|
||||
s,@PPLINC@,$PPLINC,;t t
|
||||
s,@CLOOGLIBS@,$CLOOGLIBS,;t t
|
||||
s,@CLOOGINC@,$CLOOGINC,;t t
|
||||
s,@pluginlibs@,$pluginlibs,;t t
|
||||
s,@enable_plugin@,$enable_plugin,;t t
|
||||
s,@LIBOBJS@,$LIBOBJS,;t t
|
||||
s,@LTLIBOBJS@,$LTLIBOBJS,;t t
|
||||
/@language_hooks@/r $language_hooks
|
||||
|
@ -3949,6 +3949,74 @@ if test "x${CLOOGLIBS}" != "x" ; then
|
||||
AC_DEFINE(HAVE_cloog, 1, [Define if cloog is in use.])
|
||||
fi
|
||||
|
||||
# Check for plugin support
|
||||
AC_ARG_ENABLE(plugin,
|
||||
[ --enable-plugin enable plugin support],
|
||||
enable_plugin=$enableval,
|
||||
enable_plugin=yes; default_plugin=yes)
|
||||
|
||||
pluginlibs=
|
||||
if test x"$enable_plugin" = x"yes"; then
|
||||
# Check that the host supports -rdynamic and -ldl
|
||||
have_rdynamic=no
|
||||
have_dl=no
|
||||
saved_LDFLAGS="$LDFLAGS"
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS=
|
||||
|
||||
# Check -rdynamic
|
||||
LDFLAGS="$LDFLAGS -rdynamic"
|
||||
AC_MSG_CHECKING([for -rdynamic])
|
||||
AC_TRY_LINK([],[return 0;],
|
||||
[AC_MSG_RESULT([yes]); have_rdynamic=yes],
|
||||
[AC_MSG_RESULT([no])])
|
||||
if test x"$have_rdynamic" = x"yes" ; then
|
||||
pluginlibs="-rdynamic"
|
||||
fi
|
||||
|
||||
# Check -ldl
|
||||
LDFLAGS="$LDFLAGS -ldl"
|
||||
AC_MSG_CHECKING([for -ldl])
|
||||
AC_TRY_LINK(
|
||||
[#include <dlfcn.h>],
|
||||
[volatile int f = 0; if (f) dlopen ("dummy", 0);],
|
||||
[AC_MSG_RESULT([yes]); have_dl=yes],
|
||||
[AC_MSG_RESULT([no])])
|
||||
if test x"$have_dl" = x"yes"; then
|
||||
pluginlibs="$pluginlibs -ldl"
|
||||
fi
|
||||
|
||||
# Check that we can build shared objects with -fPIC -shared
|
||||
LDFLAGS="$LDFLAGS -fPIC -shared"
|
||||
AC_MSG_CHECKING([for -fPIC -shared])
|
||||
AC_TRY_LINK(
|
||||
[extern int X;],[return X == 0;],
|
||||
[AC_MSG_RESULT([yes]); have_pic_shared=yes],
|
||||
[AC_MSG_RESULT([no]); have_pic_shared=no])
|
||||
if test x"$have_pic_shared" != x"yes"; then
|
||||
pluginlibs=
|
||||
enable_plugin=no
|
||||
fi
|
||||
|
||||
# If plugin support had been requested but not available, fail.
|
||||
if test x"$enable_plugin" = x"no" ; then
|
||||
if test x"$default_plugin" != x"yes"; then
|
||||
AC_MSG_ERROR([
|
||||
Building GCC with plugin support requires a host that supports
|
||||
-fPIC, -shared, -ldl and -rdynamic.])
|
||||
fi
|
||||
fi
|
||||
|
||||
LDFLAGS="$saved_LDFLAGS"
|
||||
LIBS="$saved_LIBS"
|
||||
fi
|
||||
|
||||
AC_SUBST(pluginlibs)
|
||||
AC_SUBST(enable_plugin)
|
||||
if test x"$enable_plugin" = x"yes"; then
|
||||
AC_DEFINE(ENABLE_PLUGIN, 1, [Define to enable plugin support.])
|
||||
fi
|
||||
|
||||
# Configure the subdirectories
|
||||
# AC_CONFIG_SUBDIRS($subdirs)
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
2009-04-14 Le-Chun Wu <lcwu@google.com>
|
||||
|
||||
* Make-lang.in: Modify dependencies of files including plugin.h.
|
||||
* decl.c (finish_function): Call invoke_plugin_callbacks.
|
||||
* parser.c (cp_parser_type_specifier): Call invoke_plugin_callbacks.
|
||||
|
||||
2009-04-14 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/39763
|
||||
|
@ -240,7 +240,7 @@ cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h debug.h langhooks.h \
|
||||
cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h \
|
||||
output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \
|
||||
cp/operators.def $(TM_P_H) $(TREE_INLINE_H) $(DIAGNOSTIC_H) $(C_PRAGMA_H) \
|
||||
debug.h gt-cp-decl.h $(TIMEVAR_H) $(TREE_FLOW_H) $(TARGET_H)
|
||||
debug.h gt-cp-decl.h $(TIMEVAR_H) $(TREE_FLOW_H) $(TARGET_H) $(PLUGIN_H)
|
||||
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) cp/decl.h $(EXPR_H) \
|
||||
output.h except.h toplev.h $(RTL_H) $(C_COMMON_H) gt-cp-decl2.h $(CGRAPH_H) \
|
||||
$(C_PRAGMA_H) $(TREE_DUMP_H) intl.h $(TARGET_H) $(GIMPLE_H)
|
||||
@ -292,7 +292,7 @@ cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h $(INTEGRATE_H) \
|
||||
cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) toplev.h $(REAL_H) \
|
||||
gt-cp-mangle.h $(TARGET_H) $(TM_P_H)
|
||||
cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_H) gt-cp-parser.h \
|
||||
output.h $(TARGET_H)
|
||||
output.h $(TARGET_H) $(PLUGIN_H)
|
||||
cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) toplev.h $(C_COMMON_H) \
|
||||
$(TM_H) coretypes.h pointer-set.h tree-iterator.h
|
||||
|
||||
|
@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "timevar.h"
|
||||
#include "tree-flow.h"
|
||||
#include "pointer-set.h"
|
||||
#include "plugin.h"
|
||||
|
||||
static tree grokparms (tree parmlist, tree *);
|
||||
static const char *redeclaration_error_message (tree, tree);
|
||||
@ -12354,6 +12355,7 @@ finish_function (int flags)
|
||||
if (!processing_template_decl)
|
||||
{
|
||||
struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
|
||||
invoke_plugin_callbacks (PLUGIN_CXX_CP_PRE_GENERICIZE, fndecl);
|
||||
cp_genericize (fndecl);
|
||||
/* Clear out the bits we don't need. */
|
||||
f->x_current_class_ptr = NULL;
|
||||
|
@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "target.h"
|
||||
#include "cgraph.h"
|
||||
#include "c-common.h"
|
||||
#include "plugin.h"
|
||||
|
||||
|
||||
/* The lexer. */
|
||||
@ -13890,6 +13891,8 @@ cp_parser_type_specifier_seq (cp_parser* parser,
|
||||
break;
|
||||
}
|
||||
|
||||
invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_specifier);
|
||||
|
||||
seen_type_specifier = true;
|
||||
/* The standard says that a condition can be:
|
||||
|
||||
|
@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "langhooks.h"
|
||||
#include "langhooks-def.h"
|
||||
#include "opts.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#define pedantic_warning_kind() (flag_pedantic_errors ? DK_ERROR : DK_WARNING)
|
||||
#define permissive_error_kind() (flag_permissive ? DK_WARNING : DK_ERROR)
|
||||
@ -371,6 +372,17 @@ diagnostic_report_diagnostic (diagnostic_context *context,
|
||||
|
||||
context->lock++;
|
||||
|
||||
if ((diagnostic->kind == DK_ERROR
|
||||
|| diagnostic->kind == DK_WARNING
|
||||
|| diagnostic->kind == DK_ICE)
|
||||
&& plugins_active_p ())
|
||||
{
|
||||
fnotice (stderr, "*** WARNING *** there are active plugins, do not report"
|
||||
" this as a bug unless you can reproduce it without enabling"
|
||||
" any plugins.\n");
|
||||
dump_active_plugins (stderr);
|
||||
}
|
||||
|
||||
if (diagnostic->kind == DK_ICE)
|
||||
{
|
||||
#ifndef ENABLE_CHECKING
|
||||
|
@ -122,6 +122,7 @@ Additional tutorial information is linked to from
|
||||
* Collect2:: How @code{collect2} works; how it finds @code{ld}.
|
||||
* Header Dirs:: Understanding the standard header file directories.
|
||||
* Type Information:: GCC's memory management; generating type information.
|
||||
* Plugins:: Extending the compiler with plugins.
|
||||
|
||||
* Funding:: How to help assure funding for free software.
|
||||
* GNU Project:: The GNU Project and GNU/Linux.
|
||||
@ -157,6 +158,7 @@ Additional tutorial information is linked to from
|
||||
@include collect2.texi
|
||||
@include headerdirs.texi
|
||||
@include gty.texi
|
||||
@include plugins.texi
|
||||
|
||||
@include funding.texi
|
||||
@include gnu.texi
|
||||
|
@ -163,7 +163,7 @@ in the following sections.
|
||||
@xref{Overall Options,,Options Controlling the Kind of Output}.
|
||||
@gccoptlist{-c -S -E -o @var{file} -combine -pipe -pass-exit-codes @gol
|
||||
-x @var{language} -v -### --help@r{[}=@var{class}@r{[},@dots{}@r{]]} --target-help @gol
|
||||
--version -wrapper@@@var{file}}
|
||||
--version -wrapper@@@var{file} -fplugin=@var{file} -fplugin-arg-@var{name}=@var{arg}}
|
||||
|
||||
@item C Language Options
|
||||
@xref{C Dialect Options,,Options Controlling C Dialect}.
|
||||
@ -1298,6 +1298,19 @@ gcc -c t.c -wrapper gdb,--args
|
||||
This will invoke all subprograms of gcc under "gdb --args",
|
||||
thus cc1 invocation will be "gdb --args cc1 ...".
|
||||
|
||||
@item -fplugin=@var{name}.so
|
||||
Load the plugin code in file @var{name}.so, assumed to be a
|
||||
shared object to be dlopen'd by the compiler. The base name of
|
||||
the shared object file is used to identify the plugin for the
|
||||
purposes of argument parsing (See
|
||||
@option{-fplugin-arg-@var{name}-@var{key}=@var{value}} below).
|
||||
Each plugin should define the callback functions specified in the
|
||||
Plugins API.
|
||||
|
||||
@item -fplugin-arg-@var{name}-@var{key}=@var{value}
|
||||
Define an argument called @var{key} with a value of @var{value}
|
||||
for the plugin called @var{name}.
|
||||
|
||||
@include @value{srcdir}/../libiberty/at-file.texi
|
||||
@end table
|
||||
|
||||
|
137
gcc/doc/plugins.texi
Normal file
137
gcc/doc/plugins.texi
Normal file
@ -0,0 +1,137 @@
|
||||
@c Copyright (c) 2009 Free Software Foundation, Inc.
|
||||
@c Free Software Foundation, Inc.
|
||||
@c This is part of the GCC manual.
|
||||
@c For copying conditions, see the file gcc.texi.
|
||||
|
||||
@node Plugins
|
||||
@chapter Plugins
|
||||
@cindex Plugins
|
||||
|
||||
@section Loading Plugins
|
||||
|
||||
Plugins are supported on platforms that support @option{-ld
|
||||
-rdynamic}. They are loaded by the compiler using @code{dlopen}
|
||||
and invoked at pre-determined locations in the compilation
|
||||
process.
|
||||
|
||||
Plugins are loaded with
|
||||
|
||||
@option{-fplugin=/path/to/NAME.so} @option{-fplugin-arg-NAME-<key1>[=<value1>]}
|
||||
|
||||
The plugin arguments are parsed by GCC and passed to respective
|
||||
plugins as key-value pairs. Multiple plugins can be invoked by
|
||||
specifying multiple @option{-fplugin} arguments.
|
||||
|
||||
|
||||
@section Plugin API
|
||||
|
||||
Plugins are activated by the compiler at specific events as defined in
|
||||
@file{gcc-plugin.h}. For each event of interest, the plugin should
|
||||
call @code{register_callback} specifying the name of the event and
|
||||
address of the callback function that will handle that event.
|
||||
|
||||
@subsection Plugin initialization
|
||||
|
||||
Every plugin should export a function called @code{plugin_init} that
|
||||
is called right after the plugin is loaded. This function is
|
||||
responsible for registering all the callbacks required by the plugin
|
||||
and do any other required initialization.
|
||||
|
||||
This function is called from @code{compile_file} right before invoking
|
||||
the parser. The arguments to @code{plugin_init} are:
|
||||
|
||||
@itemize @bullet
|
||||
@item @code{plugin_name}: Name of the plugin.
|
||||
@item @code{argc}: Number of arguments specified with @option{-fplugin-arg-...}.
|
||||
@item @code{argv}: Array of @code{argc} key-value pairs.
|
||||
@end itemize
|
||||
|
||||
If initialization fails, @code{plugin_init} must return a non-zero
|
||||
value. Otherwise, it should return 0.
|
||||
|
||||
@subsection Plugin callbacks
|
||||
|
||||
Callback functions have the following prototype:
|
||||
|
||||
@smallexample
|
||||
/* The prototype for a plugin callback function.
|
||||
gcc_data - event-specific data provided by GCC
|
||||
user_data - plugin-specific data provided by the plug-in. */
|
||||
typedef void (*plugin_callback_func)(void *gcc_data, void *user_data);
|
||||
@end smallexample
|
||||
|
||||
Callbacks can be invoked at the following pre-determined events:
|
||||
|
||||
|
||||
@smallexample
|
||||
enum plugin_event
|
||||
@{
|
||||
PLUGIN_PASS_MANAGER_SETUP, /* To hook into pass manager. */
|
||||
PLUGIN_FINISH_TYPE, /* After finishing parsing a type. */
|
||||
PLUGIN_FINISH_UNIT, /* Useful for summary processing. */
|
||||
PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */
|
||||
PLUGIN_FINISH, /* Called before GCC exits. */
|
||||
PLUGIN_EVENT_LAST /* Dummy event used for indexing callback
|
||||
array. */
|
||||
@};
|
||||
@end smallexample
|
||||
|
||||
To register a callback, the plugin calls @code{register_callback} with the arguments:
|
||||
|
||||
@itemize
|
||||
@item @code{char *name}: Plugin name.
|
||||
@item @code{enum plugin_event event}: The event code.
|
||||
@item @code{plugin_callback_func callback}: The function that handles @code{event}.
|
||||
@item @code{void *user_data}: Pointer to plugin-specific data.
|
||||
@end itemize
|
||||
|
||||
|
||||
@section Interacting with the pass manager
|
||||
|
||||
There needs to be a way to add/reorder/remove passes dynamically. This
|
||||
is useful for both analysis plugins (plugging in after a certain pass
|
||||
such as CFG or an IPA pass) and optimization plugins.
|
||||
|
||||
Basic support for inserting new passes or replacing existing passes is
|
||||
provided. A plugin registers a new pass with GCC by calling
|
||||
@code{register_callback} with the @code{PLUGIN_PASS_MANAGER_SETUP}
|
||||
event and a pointer to a @code{struct plugin_pass} object defined as follows
|
||||
|
||||
@smallexample
|
||||
enum pass_positioning_ops
|
||||
@{
|
||||
PASS_POS_INSERT_AFTER, // Insert after the reference pass.
|
||||
PASS_POS_INSERT_BEFORE, // Insert before the reference pass.
|
||||
PASS_POS_REPLACE // Replace the reference pass.
|
||||
@};
|
||||
|
||||
struct plugin_pass
|
||||
@{
|
||||
struct opt_pass *pass; /* New pass provided by the plugin. */
|
||||
const char *reference_pass_name; /* Name of the reference pass for hooking
|
||||
up the new pass. */
|
||||
int ref_pass_instance_number; /* Insert the pass at the specified
|
||||
instance number of the reference pass. */
|
||||
/* Do it for every instance if it is 0. */
|
||||
enum pass_positioning_ops pos_op; /* how to insert the new pass. */
|
||||
@};
|
||||
|
||||
|
||||
/* Sample plugin code that registers a new pass. */
|
||||
int
|
||||
plugin_init (const char *plugin_name, int argc, struct plugin_argument *argv)
|
||||
@{
|
||||
struct plugin_pass pass_info;
|
||||
|
||||
...
|
||||
|
||||
/* Code to fill in the pass_info object with new pass information. */
|
||||
|
||||
...
|
||||
|
||||
/* Register the new pass. */
|
||||
register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
|
||||
|
||||
...
|
||||
@}
|
||||
@end smallexample
|
98
gcc/gcc-plugin.h
Normal file
98
gcc/gcc-plugin.h
Normal file
@ -0,0 +1,98 @@
|
||||
/* Public header file for plugins to include.
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
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 3, 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 COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_PLUGIN_H
|
||||
#define GCC_PLUGIN_H
|
||||
|
||||
/* Event names. Keep in sync with plugin_event_name[]. */
|
||||
enum plugin_event
|
||||
{
|
||||
PLUGIN_PASS_MANAGER_SETUP, /* To hook into pass manager. */
|
||||
PLUGIN_FINISH_TYPE, /* After finishing parsing a type. */
|
||||
PLUGIN_FINISH_UNIT, /* Useful for summary processing. */
|
||||
PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */
|
||||
PLUGIN_FINISH, /* Called before GCC exits. */
|
||||
PLUGIN_EVENT_LAST /* Dummy event used for indexing callback
|
||||
array. */
|
||||
};
|
||||
|
||||
extern const char *plugin_event_name[];
|
||||
|
||||
struct plugin_argument
|
||||
{
|
||||
char *key; /* key of the argument. */
|
||||
char *value; /* value is optional and can be NULL. */
|
||||
};
|
||||
|
||||
enum pass_positioning_ops
|
||||
{
|
||||
PASS_POS_INSERT_AFTER, /* Insert after the reference pass. */
|
||||
PASS_POS_INSERT_BEFORE, /* Insert before the reference pass. */
|
||||
PASS_POS_REPLACE /* Replace the reference pass. */
|
||||
};
|
||||
|
||||
struct plugin_pass
|
||||
{
|
||||
struct opt_pass *pass; /* New pass provided by the plugin. */
|
||||
const char *reference_pass_name; /* Name of the reference pass for hooking
|
||||
up the new pass. */
|
||||
int ref_pass_instance_number; /* Insert the pass at the specified
|
||||
instance number of the reference pass.
|
||||
Do it for every instance if it is 0. */
|
||||
enum pass_positioning_ops pos_op; /* how to insert the new pass. */
|
||||
};
|
||||
|
||||
/* Function type for the plugin initialization routine. Each plugin module
|
||||
should define this as an externally-visible function with name
|
||||
"plugin_init."
|
||||
|
||||
PLUGIN_NAME - name of the plugin (useful for error reporting)
|
||||
ARGC - the size of the ARGV array
|
||||
ARGV - an array of key-value argument pair
|
||||
|
||||
Returns 0 if initialization finishes successfully. */
|
||||
|
||||
typedef int (*plugin_init_func) (const char *plugin_name,
|
||||
int argc, struct plugin_argument *argv);
|
||||
|
||||
/* Declaration for "plugin_init" function so that it doesn't need to be
|
||||
duplicated in every plugin. */
|
||||
extern int plugin_init (const char *, int, struct plugin_argument *);
|
||||
|
||||
/* Function type for a plugin callback routine.
|
||||
|
||||
GCC_DATA - event-specific data provided by GCC
|
||||
USER_DATA - plugin-specific data provided by the plugin */
|
||||
|
||||
typedef void (*plugin_callback_func) (void *gcc_data, void *user_data);
|
||||
|
||||
/* Called from the plugin's initialization code. Register a single callback.
|
||||
This function can be called multiple times.
|
||||
|
||||
PLUGIN_NAME - display name for this plugin
|
||||
EVENT - which event the callback is for
|
||||
CALLBACK - the callback to be called at the event
|
||||
USER_DATA - plugin-provided data */
|
||||
|
||||
extern void register_callback (const char *plugin_name,
|
||||
enum plugin_event event,
|
||||
plugin_callback_func callback,
|
||||
void *user_data);
|
||||
|
||||
#endif /* GCC_PLUGIN_H */
|
17
gcc/opts.c
17
gcc/opts.c
@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "tree-pass.h"
|
||||
#include "dbgcnt.h"
|
||||
#include "debug.h"
|
||||
#include "plugin.h"
|
||||
|
||||
/* Value of the -G xx switch, and whether it was passed or not. */
|
||||
unsigned HOST_WIDE_INT g_switch_value;
|
||||
@ -1766,6 +1767,22 @@ common_handle_option (size_t scode, const char *arg, int value,
|
||||
flag_peel_loops_set = true;
|
||||
break;
|
||||
|
||||
case OPT_fplugin_:
|
||||
#ifdef ENABLE_PLUGIN
|
||||
add_new_plugin (arg);
|
||||
#else
|
||||
error ("Plugin support is disabled. Configure with --enable-plugin.");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPT_fplugin_arg_:
|
||||
#ifdef ENABLE_PLUGIN
|
||||
parse_plugin_arg_opt (arg);
|
||||
#else
|
||||
error ("Plugin support is disabled. Configure with --enable-plugin.");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPT_fprofile_arcs:
|
||||
profile_arc_flag_set = true;
|
||||
break;
|
||||
|
@ -368,7 +368,7 @@ get_pass_for_id (int id)
|
||||
to do this depth first, and independent of whether the pass is
|
||||
enabled or not. */
|
||||
|
||||
static void
|
||||
void
|
||||
register_one_dump_file (struct opt_pass *pass)
|
||||
{
|
||||
char *dot_name, *flag_name, *glob_name;
|
||||
|
672
gcc/plugin.c
Normal file
672
gcc/plugin.c
Normal file
@ -0,0 +1,672 @@
|
||||
/* Support for GCC plugin mechanism.
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
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 3, 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 COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This file contains the support for GCC plugin mechanism based on the
|
||||
APIs described in doc/plugin.texi. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
|
||||
/* If plugin support is not enabled, do not try to execute any code
|
||||
that may reference libdl. The generic code is still compiled in to
|
||||
avoid including to many conditional compilation paths in the rest
|
||||
of the compiler. */
|
||||
#ifdef ENABLE_PLUGIN
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "coretypes.h"
|
||||
#include "toplev.h"
|
||||
#include "tree.h"
|
||||
#include "tree-pass.h"
|
||||
#include "intl.h"
|
||||
#include "plugin.h"
|
||||
#include "timevar.h"
|
||||
|
||||
/* Event names as strings. Keep in sync with enum plugin_event. */
|
||||
const char *plugin_event_name[] =
|
||||
{
|
||||
"PLUGIN_PASS_MANAGER_SETUP",
|
||||
"PLUGIN_FINISH_TYPE",
|
||||
"PLUGIN_FINISH_UNIT",
|
||||
"PLUGIN_CXX_CP_PRE_GENERICIZE",
|
||||
"PLUGIN_FINISH",
|
||||
"PLUGIN_EVENT_LAST"
|
||||
};
|
||||
|
||||
/* Object that keeps track of the plugin name and its arguments
|
||||
when parsing the command-line options -fplugin=/path/to/NAME.so and
|
||||
-fplugin-arg-NAME-<key>[=<value>]. */
|
||||
struct plugin_name_args
|
||||
{
|
||||
char *base_name;
|
||||
const char *full_name;
|
||||
int argc;
|
||||
struct plugin_argument *argv;
|
||||
};
|
||||
|
||||
/* Hash table for the plugin_name_args objects created during command-line
|
||||
parsing. */
|
||||
static htab_t plugin_name_args_tab = NULL;
|
||||
|
||||
/* List node for keeping track of plugin-registered callback. */
|
||||
struct callback_info
|
||||
{
|
||||
const char *plugin_name; /* Name of plugin that registers the callback. */
|
||||
plugin_callback_func func; /* Callback to be called. */
|
||||
void *user_data; /* plugin-specified data. */
|
||||
struct callback_info *next;
|
||||
};
|
||||
|
||||
/* An array of lists of 'callback_info' objects indexed by the event id. */
|
||||
static struct callback_info *plugin_callbacks[PLUGIN_EVENT_LAST] = { NULL };
|
||||
|
||||
/* List node for an inserted pass instance. We need to keep track of all
|
||||
the newly-added pass instances (with 'added_pass_nodes' defined below)
|
||||
so that we can register their dump files after pass-positioning is finished.
|
||||
Registering dumping files needs to be post-processed or the
|
||||
static_pass_number of the opt_pass object would be modified and mess up
|
||||
the dump file names of future pass instances to be added. */
|
||||
struct pass_list_node
|
||||
{
|
||||
struct opt_pass *pass;
|
||||
struct pass_list_node *next;
|
||||
};
|
||||
|
||||
static struct pass_list_node *added_pass_nodes = NULL;
|
||||
static struct pass_list_node *prev_added_pass_node;
|
||||
|
||||
#ifdef ENABLE_PLUGIN
|
||||
/* Each plugin should define an initialization function with exactly
|
||||
this name. */
|
||||
static const char *str_plugin_init_func_name = "plugin_init";
|
||||
#endif
|
||||
|
||||
/* Helper function for the hash table that compares the base_name of the
|
||||
existing entry (S1) with the given string (S2). */
|
||||
|
||||
static int
|
||||
htab_str_eq (const void *s1, const void *s2)
|
||||
{
|
||||
const struct plugin_name_args *plugin = (const struct plugin_name_args *) s1;
|
||||
return !strcmp (plugin->base_name, (const char *) s2);
|
||||
}
|
||||
|
||||
|
||||
/* Given a plugin's full-path name FULL_NAME, e.g. /pass/to/NAME.so,
|
||||
return NAME. */
|
||||
|
||||
static char *
|
||||
get_plugin_base_name (const char *full_name)
|
||||
{
|
||||
/* First get the base name part of the full-path name, i.e. NAME.so. */
|
||||
char *base_name = xstrdup (lbasename (full_name));
|
||||
|
||||
/* Then get rid of '.so' part of the name. */
|
||||
strip_off_ending (base_name, strlen (base_name));
|
||||
|
||||
return base_name;
|
||||
}
|
||||
|
||||
|
||||
/* Create a plugin_name_args object for the give plugin and insert it to
|
||||
the hash table. This function is called when -fplugin=/path/to/NAME.so
|
||||
option is processed. */
|
||||
|
||||
void
|
||||
add_new_plugin (const char* plugin_name)
|
||||
{
|
||||
struct plugin_name_args *plugin;
|
||||
void **slot;
|
||||
char *base_name = get_plugin_base_name (plugin_name);
|
||||
|
||||
/* If this is the first -fplugin= option we encounter, create
|
||||
'plugin_name_args_tab' hash table. */
|
||||
if (!plugin_name_args_tab)
|
||||
plugin_name_args_tab = htab_create (10, htab_hash_string, htab_str_eq,
|
||||
NULL);
|
||||
|
||||
slot = htab_find_slot (plugin_name_args_tab, base_name, INSERT);
|
||||
|
||||
/* If the same plugin (name) has been specified earlier, either emit an
|
||||
error or a warning message depending on if they have identical full
|
||||
(path) names. */
|
||||
if (*slot)
|
||||
{
|
||||
plugin = (struct plugin_name_args *) *slot;
|
||||
if (strcmp (plugin->full_name, plugin_name))
|
||||
error ("Plugin %s was specified with different paths:\n%s\n%s",
|
||||
plugin->base_name, plugin->full_name, plugin_name);
|
||||
return;
|
||||
}
|
||||
|
||||
plugin = XCNEW (struct plugin_name_args);
|
||||
plugin->base_name = base_name;
|
||||
plugin->full_name = plugin_name;
|
||||
|
||||
*slot = plugin;
|
||||
}
|
||||
|
||||
|
||||
/* Parse the -fplugin-arg-<name>-<key>[=<value>] option and create a
|
||||
'plugin_argument' object for the parsed key-value pair. ARG is
|
||||
the <name>-<key>[=<value>] part of the option. */
|
||||
|
||||
void
|
||||
parse_plugin_arg_opt (const char *arg)
|
||||
{
|
||||
size_t len = 0, name_len = 0, key_len = 0, value_len = 0;
|
||||
const char *ptr, *name_start = arg, *key_start = NULL, *value_start = NULL;
|
||||
char *name, *key, *value;
|
||||
void **slot;
|
||||
bool name_parsed = false, key_parsed = false;
|
||||
|
||||
/* Iterate over the ARG string and identify the starting character position
|
||||
of 'name', 'key', and 'value' and their lengths. */
|
||||
for (ptr = arg; *ptr; ++ptr)
|
||||
{
|
||||
/* Only the first '-' encountered is considered a separator between
|
||||
'name' and 'key'. All the subsequent '-'s are considered part of
|
||||
'key'. For example, given -fplugin-arg-foo-bar-primary-key=value,
|
||||
the plugin name is 'foo' and the key is 'bar-primary-key'. */
|
||||
if (*ptr == '-' && !name_parsed)
|
||||
{
|
||||
name_len = len;
|
||||
len = 0;
|
||||
key_start = ptr + 1;
|
||||
name_parsed = true;
|
||||
continue;
|
||||
}
|
||||
else if (*ptr == '=')
|
||||
{
|
||||
if (key_parsed)
|
||||
{
|
||||
error ("Malformed option -fplugin-arg-%s (multiple '=' signs)",
|
||||
arg);
|
||||
return;
|
||||
}
|
||||
key_len = len;
|
||||
len = 0;
|
||||
value_start = ptr + 1;
|
||||
key_parsed = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
++len;
|
||||
}
|
||||
|
||||
if (!key_start)
|
||||
{
|
||||
error ("Malformed option -fplugin-arg-%s (missing -<key>[=<value>])",
|
||||
arg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the option doesn't contain the 'value' part, LEN is the KEY_LEN.
|
||||
Otherwise, it is the VALUE_LEN. */
|
||||
if (!value_start)
|
||||
key_len = len;
|
||||
else
|
||||
value_len = len;
|
||||
|
||||
name = XNEWVEC (char, name_len + 1);
|
||||
strncpy (name, name_start, name_len);
|
||||
name[name_len] = '\0';
|
||||
|
||||
/* Check if the named plugin has already been specified earlier in the
|
||||
command-line. */
|
||||
if (plugin_name_args_tab
|
||||
&& ((slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT))
|
||||
!= NULL))
|
||||
{
|
||||
struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
|
||||
|
||||
key = XNEWVEC (char, key_len + 1);
|
||||
strncpy (key, key_start, key_len);
|
||||
key[key_len] = '\0';
|
||||
if (value_start)
|
||||
{
|
||||
value = XNEWVEC (char, value_len + 1);
|
||||
strncpy (value, value_start, value_len);
|
||||
value[value_len] = '\0';
|
||||
}
|
||||
else
|
||||
value = NULL;
|
||||
|
||||
/* Create a plugin_argument object for the parsed key-value pair.
|
||||
If there are already arguments for this plugin, we will need to
|
||||
adjust the argument array size by creating a new array and deleting
|
||||
the old one. If the performance ever becomes an issue, we can
|
||||
change the code by pre-allocating a larger array first. */
|
||||
if (plugin->argc > 0)
|
||||
{
|
||||
struct plugin_argument *args = XNEWVEC (struct plugin_argument,
|
||||
plugin->argc + 1);
|
||||
memcpy (args, plugin->argv,
|
||||
sizeof (struct plugin_argument) * plugin->argc);
|
||||
XDELETEVEC (plugin->argv);
|
||||
plugin->argv = args;
|
||||
++plugin->argc;
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_assert (plugin->argv == NULL);
|
||||
plugin->argv = XNEWVEC (struct plugin_argument, 1);
|
||||
plugin->argc = 1;
|
||||
}
|
||||
|
||||
plugin->argv[plugin->argc - 1].key = key;
|
||||
plugin->argv[plugin->argc - 1].value = value;
|
||||
}
|
||||
else
|
||||
error ("Plugin %s should be specified before -fplugin-arg-%s "
|
||||
"in the command line", name, arg);
|
||||
|
||||
/* We don't need the plugin's name anymore. Just release it. */
|
||||
XDELETEVEC (name);
|
||||
}
|
||||
|
||||
|
||||
/* Insert the plugin pass at the proper position. Return true if the pass
|
||||
is successfully added.
|
||||
|
||||
PLUGIN_PASS_INFO - new pass to be inserted
|
||||
PASS_LIST - root of the pass list to insert the new pass to */
|
||||
|
||||
static bool
|
||||
position_pass (struct plugin_pass *plugin_pass_info,
|
||||
struct opt_pass **pass_list)
|
||||
{
|
||||
struct opt_pass *pass = *pass_list, *prev_pass = NULL;
|
||||
bool success = false;
|
||||
|
||||
for ( ; pass; prev_pass = pass, pass = pass->next)
|
||||
{
|
||||
/* Check if the current pass is of the same type as the new pass and
|
||||
matches the name and the instance number of the reference pass. */
|
||||
if (pass->type == plugin_pass_info->pass->type
|
||||
&& pass->name
|
||||
&& !strcmp (pass->name, plugin_pass_info->reference_pass_name)
|
||||
&& ((plugin_pass_info->ref_pass_instance_number == 0)
|
||||
|| (plugin_pass_info->ref_pass_instance_number ==
|
||||
pass->static_pass_number)
|
||||
|| (plugin_pass_info->ref_pass_instance_number == 1
|
||||
&& pass->todo_flags_start & TODO_mark_first_instance)))
|
||||
{
|
||||
struct opt_pass *new_pass = plugin_pass_info->pass;
|
||||
struct pass_list_node *new_pass_node;
|
||||
|
||||
/* The following code (if-statement) is adopted from next_pass_1. */
|
||||
if (new_pass->static_pass_number)
|
||||
{
|
||||
new_pass = XNEW (struct opt_pass);
|
||||
memcpy (new_pass, plugin_pass_info->pass, sizeof (*new_pass));
|
||||
new_pass->next = NULL;
|
||||
|
||||
new_pass->todo_flags_start &= ~TODO_mark_first_instance;
|
||||
|
||||
plugin_pass_info->pass->static_pass_number -= 1;
|
||||
new_pass->static_pass_number =
|
||||
-plugin_pass_info->pass->static_pass_number;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_pass->todo_flags_start |= TODO_mark_first_instance;
|
||||
new_pass->static_pass_number = -1;
|
||||
}
|
||||
|
||||
/* Insert the new pass instance based on the positioning op. */
|
||||
switch (plugin_pass_info->pos_op)
|
||||
{
|
||||
case PASS_POS_INSERT_AFTER:
|
||||
new_pass->next = pass->next;
|
||||
pass->next = new_pass;
|
||||
break;
|
||||
case PASS_POS_INSERT_BEFORE:
|
||||
new_pass->next = pass;
|
||||
if (prev_pass)
|
||||
prev_pass->next = new_pass;
|
||||
else
|
||||
*pass_list = new_pass;
|
||||
break;
|
||||
case PASS_POS_REPLACE:
|
||||
new_pass->next = pass->next;
|
||||
if (prev_pass)
|
||||
prev_pass->next = new_pass;
|
||||
else
|
||||
*pass_list = new_pass;
|
||||
new_pass->sub = pass->sub;
|
||||
new_pass->tv_id = pass->tv_id;
|
||||
pass = new_pass;
|
||||
break;
|
||||
default:
|
||||
error ("Invalid pass positioning operation");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Save the newly added pass (instance) in the added_pass_nodes
|
||||
list so that we can register its dump file later. Note that
|
||||
we cannot register the dump file now because doing so will modify
|
||||
the static_pass_number of the opt_pass object and therefore
|
||||
mess up the dump file name of future instances. */
|
||||
new_pass_node = XCNEW (struct pass_list_node);
|
||||
new_pass_node->pass = new_pass;
|
||||
if (!added_pass_nodes)
|
||||
added_pass_nodes = new_pass_node;
|
||||
else
|
||||
prev_added_pass_node->next = new_pass_node;
|
||||
prev_added_pass_node = new_pass_node;
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (pass->sub && position_pass (plugin_pass_info, &pass->sub))
|
||||
success = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/* Hook into the pass lists (trees) a new pass registered by a plugin.
|
||||
|
||||
PLUGIN_NAME - display name for the plugin
|
||||
PASS_INFO - plugin pass information that specifies the opt_pass object,
|
||||
reference pass, instance number, and how to position
|
||||
the pass */
|
||||
|
||||
static void
|
||||
register_pass (const char *plugin_name, struct plugin_pass *pass_info)
|
||||
{
|
||||
if (!pass_info->pass)
|
||||
{
|
||||
error ("No pass specified when registering a new pass in plugin %s",
|
||||
plugin_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pass_info->reference_pass_name)
|
||||
{
|
||||
error ("No reference pass specified for positioning the pass "
|
||||
" from plugin %s", plugin_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try to insert the new pass to the pass lists. We need to check all
|
||||
three lists as the reference pass could be in one (or all) of them. */
|
||||
if (!position_pass (pass_info, &all_lowering_passes)
|
||||
&& !position_pass (pass_info, &all_ipa_passes)
|
||||
&& !position_pass (pass_info, &all_passes))
|
||||
error ("Failed to position pass %s registered by plugin %s. "
|
||||
"Cannot find the (specified instance of) reference pass %s",
|
||||
pass_info->pass->name, plugin_name, pass_info->reference_pass_name);
|
||||
else
|
||||
{
|
||||
/* OK, we have successfully inserted the new pass. We need to register
|
||||
the dump files for the newly added pass and its duplicates (if any).
|
||||
Because the registration of plugin passes happens after the
|
||||
command-line options are parsed, the options that specify single
|
||||
pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new
|
||||
plugin passes. Therefore we currently can only enable dumping of
|
||||
new plugin passes when the 'dump-all' flags (e.g. -fdump-tree-all)
|
||||
are specified. While doing so, we also delete the pass_list_node
|
||||
objects created during pass positioning. */
|
||||
while (added_pass_nodes)
|
||||
{
|
||||
struct pass_list_node *next_node = added_pass_nodes->next;
|
||||
enum tree_dump_index tdi;
|
||||
register_one_dump_file (added_pass_nodes->pass);
|
||||
if (added_pass_nodes->pass->type == SIMPLE_IPA_PASS
|
||||
|| added_pass_nodes->pass->type == IPA_PASS)
|
||||
tdi = TDI_ipa_all;
|
||||
else if (added_pass_nodes->pass->type == GIMPLE_PASS)
|
||||
tdi = TDI_tree_all;
|
||||
else
|
||||
tdi = TDI_rtl_all;
|
||||
/* Check if dump-all flag is specified. */
|
||||
if (get_dump_file_info (tdi)->state)
|
||||
get_dump_file_info (added_pass_nodes->pass->static_pass_number)
|
||||
->state = get_dump_file_info (tdi)->state;
|
||||
XDELETE (added_pass_nodes);
|
||||
added_pass_nodes = next_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called from the plugin's initialization code. Register a single callback.
|
||||
This function can be called multiple times.
|
||||
|
||||
PLUGIN_NAME - display name for this plugin
|
||||
EVENT - which event the callback is for
|
||||
CALLBACK - the callback to be called at the event
|
||||
USER_DATA - plugin-provided data */
|
||||
|
||||
void
|
||||
register_callback (const char *plugin_name,
|
||||
enum plugin_event event,
|
||||
plugin_callback_func callback,
|
||||
void *user_data)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case PLUGIN_PASS_MANAGER_SETUP:
|
||||
register_pass (plugin_name, (struct plugin_pass *) user_data);
|
||||
break;
|
||||
case PLUGIN_FINISH_TYPE:
|
||||
case PLUGIN_FINISH_UNIT:
|
||||
case PLUGIN_CXX_CP_PRE_GENERICIZE:
|
||||
case PLUGIN_FINISH:
|
||||
{
|
||||
struct callback_info *new_callback;
|
||||
if (!callback)
|
||||
{
|
||||
error ("Plugin %s registered a null callback function "
|
||||
"for event %s", plugin_name, plugin_event_name[event]);
|
||||
return;
|
||||
}
|
||||
new_callback = XNEW (struct callback_info);
|
||||
new_callback->plugin_name = plugin_name;
|
||||
new_callback->func = callback;
|
||||
new_callback->user_data = user_data;
|
||||
new_callback->next = plugin_callbacks[event];
|
||||
plugin_callbacks[event] = new_callback;
|
||||
}
|
||||
break;
|
||||
case PLUGIN_EVENT_LAST:
|
||||
default:
|
||||
error ("Unkown callback event registered by plugin %s",
|
||||
plugin_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Called from inside GCC. Invoke all plug-in callbacks registered with
|
||||
the specified event.
|
||||
|
||||
EVENT - the event identifier
|
||||
GCC_DATA - event-specific data provided by the compiler */
|
||||
|
||||
void
|
||||
invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
|
||||
{
|
||||
timevar_push (TV_PLUGIN_RUN);
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case PLUGIN_FINISH_TYPE:
|
||||
case PLUGIN_FINISH_UNIT:
|
||||
case PLUGIN_CXX_CP_PRE_GENERICIZE:
|
||||
case PLUGIN_FINISH:
|
||||
{
|
||||
/* Iterate over every callback registered with this event and
|
||||
call it. */
|
||||
struct callback_info *callback = plugin_callbacks[event];
|
||||
for ( ; callback; callback = callback->next)
|
||||
(*callback->func) (gcc_data, callback->user_data);
|
||||
}
|
||||
break;
|
||||
|
||||
case PLUGIN_PASS_MANAGER_SETUP:
|
||||
case PLUGIN_EVENT_LAST:
|
||||
default:
|
||||
gcc_assert (false);
|
||||
}
|
||||
|
||||
timevar_pop (TV_PLUGIN_RUN);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PLUGIN
|
||||
/* We need a union to cast dlsym return value to a function pointer
|
||||
as ISO C forbids assignment between function pointer and 'void *'.
|
||||
Use explicit union instead of __extension__(<union_cast>) for
|
||||
portability. */
|
||||
#define PTR_UNION_TYPE(TOTYPE) union { void *_q; TOTYPE _nq; }
|
||||
#define PTR_UNION_AS_VOID_PTR(NAME) (NAME._q)
|
||||
#define PTR_UNION_AS_CAST_PTR(NAME) (NAME._nq)
|
||||
|
||||
/* Routine to dlopen and initialize one plugin. This function is passed to
|
||||
(and called by) the hash table traverse routine. Return 1 for the
|
||||
htab_traverse to continue scan, 0 to stop.
|
||||
|
||||
SLOT - slot of the hash table element
|
||||
INFO - auxiliary pointer handed to hash table traverse routine
|
||||
(unused in this function) */
|
||||
|
||||
static int
|
||||
init_one_plugin (void **slot, void * ARG_UNUSED (info))
|
||||
{
|
||||
struct plugin_name_args *plugin = (struct plugin_name_args *) *slot;
|
||||
void *dl_handle;
|
||||
plugin_init_func plugin_init;
|
||||
char *err;
|
||||
PTR_UNION_TYPE (plugin_init_func) plugin_init_union;
|
||||
|
||||
dl_handle = dlopen (plugin->full_name, RTLD_NOW);
|
||||
if (!dl_handle)
|
||||
{
|
||||
error ("Cannot load plugin %s\n%s", plugin->full_name, dlerror ());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Clear any existing error. */
|
||||
dlerror ();
|
||||
|
||||
PTR_UNION_AS_VOID_PTR (plugin_init_union) =
|
||||
dlsym (dl_handle, str_plugin_init_func_name);
|
||||
plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union);
|
||||
|
||||
if ((err = dlerror ()) != NULL)
|
||||
{
|
||||
error ("Cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
|
||||
plugin->full_name, err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Call the plugin-provided initialization routine with the arguments. */
|
||||
if ((*plugin_init) (plugin->base_name, plugin->argc, plugin->argv))
|
||||
{
|
||||
error ("Fail to initialize plugin %s", plugin->full_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We can now delete the plugin_name_args object as it will no longer
|
||||
be used. Note that base_name and argv fields (both of which were also
|
||||
dynamically allocated) are not freed as they could still be used by
|
||||
the plugin code. */
|
||||
XDELETE (plugin);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* ENABLE_PLUGIN */
|
||||
|
||||
/* Main plugin initialization function. Called from compile_file() in
|
||||
toplev.c. */
|
||||
|
||||
void
|
||||
initialize_plugins (void)
|
||||
{
|
||||
/* If no plugin was specified in the command-line, simply return. */
|
||||
if (!plugin_name_args_tab)
|
||||
return;
|
||||
|
||||
timevar_push (TV_PLUGIN_INIT);
|
||||
|
||||
#ifdef ENABLE_PLUGIN
|
||||
/* Traverse and initialize each plugin specified in the command-line. */
|
||||
htab_traverse_noresize (plugin_name_args_tab, init_one_plugin, NULL);
|
||||
#endif
|
||||
|
||||
/* PLUGIN_NAME_ARGS_TAB is no longer needed, just delete it. */
|
||||
htab_delete (plugin_name_args_tab);
|
||||
plugin_name_args_tab = NULL;
|
||||
|
||||
timevar_pop (TV_PLUGIN_INIT);
|
||||
}
|
||||
|
||||
|
||||
/* Return true if plugins have been loaded. */
|
||||
|
||||
bool
|
||||
plugins_active_p (void)
|
||||
{
|
||||
enum plugin_event event;
|
||||
|
||||
for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
|
||||
if (plugin_callbacks[event])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Dump to FILE the names and associated events for all the active
|
||||
plugins. */
|
||||
|
||||
void
|
||||
dump_active_plugins (FILE *file)
|
||||
{
|
||||
enum plugin_event event;
|
||||
|
||||
if (!plugins_active_p ())
|
||||
return;
|
||||
|
||||
fprintf (stderr, "Event\t\tPlugins\n");
|
||||
for (event = PLUGIN_PASS_MANAGER_SETUP; event < PLUGIN_EVENT_LAST; event++)
|
||||
if (plugin_callbacks[event])
|
||||
{
|
||||
struct callback_info *ci;
|
||||
|
||||
fprintf (file, "%s\t", plugin_event_name[event]);
|
||||
|
||||
for (ci = plugin_callbacks[event]; ci; ci = ci->next)
|
||||
fprintf (file, "%s ", ci->plugin_name);
|
||||
|
||||
fprintf (file, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Dump active plugins to stderr. */
|
||||
|
||||
void
|
||||
debug_active_plugins (void)
|
||||
{
|
||||
dump_active_plugins (stderr);
|
||||
}
|
33
gcc/plugin.h
Normal file
33
gcc/plugin.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* Header file for internal GCC plugin mechanism.
|
||||
Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
|
||||
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 3, 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 COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef PLUGIN_H
|
||||
#define PLUGIN_H
|
||||
|
||||
#include "gcc-plugin.h"
|
||||
|
||||
extern void add_new_plugin (const char *);
|
||||
extern void parse_plugin_arg_opt (const char *);
|
||||
extern void invoke_plugin_callbacks (enum plugin_event, void *);
|
||||
extern void initialize_plugins (void);
|
||||
extern bool plugins_active_p (void);
|
||||
extern void dump_active_plugins (FILE *);
|
||||
extern void debug_active_plugins (void);
|
||||
|
||||
#endif /* PLUGIN_H */
|
@ -195,6 +195,8 @@ DEFTIMEVAR (TV_FINAL , "final")
|
||||
DEFTIMEVAR (TV_SYMOUT , "symout")
|
||||
DEFTIMEVAR (TV_VAR_TRACKING , "variable tracking")
|
||||
DEFTIMEVAR (TV_TREE_IFCOMBINE , "tree if-combine")
|
||||
DEFTIMEVAR (TV_PLUGIN_INIT , "plugin initialization")
|
||||
DEFTIMEVAR (TV_PLUGIN_RUN , "plugin execution")
|
||||
|
||||
/* Everything else in rest_of_compilation not included above. */
|
||||
DEFTIMEVAR (TV_REST_OF_COMPILATION , "rest of compilation")
|
||||
|
@ -85,6 +85,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "tree-pass.h"
|
||||
#include "gimple.h"
|
||||
#include "tree-ssa-alias.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
|
||||
#include "dwarf2out.h"
|
||||
@ -968,6 +969,7 @@ compile_file (void)
|
||||
init_final (main_input_filename);
|
||||
coverage_init (aux_base_name);
|
||||
statistics_init ();
|
||||
initialize_plugins ();
|
||||
|
||||
timevar_push (TV_PARSE);
|
||||
|
||||
@ -2241,6 +2243,9 @@ do_compile (void)
|
||||
compile_file ();
|
||||
|
||||
finalize ();
|
||||
|
||||
/* Invoke registered plugin callbacks. */
|
||||
invoke_plugin_callbacks (PLUGIN_FINISH_UNIT, NULL);
|
||||
}
|
||||
|
||||
/* Stop timing and print the times. */
|
||||
@ -2275,6 +2280,9 @@ toplev_main (unsigned int argc, const char **argv)
|
||||
if (warningcount || errorcount)
|
||||
print_ignored_options ();
|
||||
|
||||
/* Invoke registered plugin callbacks if any. */
|
||||
invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
|
||||
|
||||
if (errorcount || sorrycount)
|
||||
return (FATAL_EXIT_CODE);
|
||||
|
||||
|
@ -529,6 +529,7 @@ extern void execute_pass_list (struct opt_pass *);
|
||||
extern void execute_ipa_pass_list (struct opt_pass *);
|
||||
extern void print_current_pass (FILE *);
|
||||
extern void debug_pass (void);
|
||||
extern void register_one_dump_file (struct opt_pass *);
|
||||
extern bool function_called_by_processed_nodes_p (void);
|
||||
|
||||
/* Set to true if the pass is called the first time during compilation of the
|
||||
|
Loading…
x
Reference in New Issue
Block a user