This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: Add a check_pch_target_flags target hook


At the moment I'm trying to achieve the twin goals of:

  (a) getting rid of TARGET_SWITCHES and TARGET_OPTIONS; and
  (b) applying PCH validity checks to general .opt options.

This patch is another step along that road.

One thing that's blocking both (a) and (b) is the SH definition of
TARGET_PCH_VALID_P.  This implementation is basically a cut-&-paste
version of the default, but with special handling for target_flags.
Any change to default_get_pch_validity or default_pch_valid_p
could therefore break SH.

The patch below adds a new hook, check_pch_target_flags, that
specifically checks the validity of target_flags.  SH can then
use the default implementation of TARGET_PCH_VALID_P and override
this new hook instead.

One obvious approach would have been to move the current target_flags
code into a new function, default_check_pch_target_flags, and use it
as the default implementation of the hook.  However, the long-term
plan is to have a loop like:

   for (i = 0; i < cl_options_count; i++)
     if (option_affects_pch_p (i))
       ...check option validity...

This loop will be able to handle all types of option, and so for most
ports, there would be no point in handling target_flags as a special case.
SH is (hopefully) unusual in that the architecture/ABI checks are based
on specific masks rather than specific options.

So, rather than defaulting to a function, the new hook defaults to null.
This is just as easy for the current code to handle and means that any
future implementation of option_affects_pch_p() can simply return "false"
for a target_flags option when the hook is not null.

Also, the documentation for TARGET_GET_PCH_VALIDITY and TARGET_PCH_VALID_P
is a bit out of date, partly because of my changes, and partly because
of the flag_pic/flag_pie checks.  I've tried to rework it so that it'll
be more future-proof.

[ It might make sense for a later patch to get rid of TARGET_PCH_VALID_P
  and TARGET_GET_PCH_VALIDITY altogether.  I don't think we're at that
  stage yet though. ]

Bootstrapped & regression tested on i686-pc-linux-gnu.  Also tested by
building cc1 for sh-linux-gnu.  I checked that -Winvalid-pch was working
as expected for both targets.  OK to install?

Richard


	* doc/tm.texi (TARGET_GET_PCH_VALIDITY, TARGET_PCH_VALID_P): Tweak
	the documentation to make it more future-proof.
	(TARGET_CHECK_PCH_TARGET_FLAGS): Document this new hook.
	* target.h (gcc_target): Add check_pch_target_flags.
	* target-def.h (TARGET_CHECK_PCH_TARGET_FLAGS): New macro.
	(TARGET_INITIALIZER): Include it.
	* toplev.c (default_pch_valid_p): Use targetm.check_pch_target_flags.
	* config/sh/sh.h (sh_pch_valid_p): Delete.
	* config/sh/sh.c (TARGET_PCH_VALID_P, sh_pch_valid_p): Delete.
	(sh_check_pch_target_flags): New function.
	(TARGET_CHECK_PCH_TARGET_FLAGS): Override default.

Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.428
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.428 tm.texi
*** doc/tm.texi	25 May 2005 11:52:13 -0000	1.428
--- doc/tm.texi	27 May 2005 05:56:03 -0000
*************** Default: empty.
*** 8668,8691 ****
  @section Parameters for Precompiled Header Validity Checking
  @cindex parameters, precompiled headers
  
! @deftypefn {Target Hook} void * TARGET_GET_PCH_VALIDITY (size_t * @var{sz})
! Define this hook if your target needs to check a different collection
! of flags than the default, which is every flag defined by
! @code{TARGET_SWITCHES} and @code{TARGET_OPTIONS}.  It should return
! some data which will be saved in the PCH file and presented to
! @code{TARGET_PCH_VALID_P} later; it should set @code{SZ} to the size
! of the data.
! @end deftypefn
! 
! @deftypefn {Target Hook} const char * TARGET_PCH_VALID_P (const void * @var{data}, size_t @var{sz})
! Define this hook if your target needs to check a different collection of
! flags than the default, which is every flag defined by @code{TARGET_SWITCHES}
! and @code{TARGET_OPTIONS}.  It is given data which came from
! @code{TARGET_GET_PCH_VALIDITY} (in this version of this compiler, so there
! is no need for extensive validity checking).  It returns @code{NULL} if
! it is safe to load a PCH file with this data, or a suitable error message
! if not.  The error message will be presented to the user, so it should
! be localized.
  @end deftypefn
  
  @node C++ ABI
--- 8668,8699 ----
  @section Parameters for Precompiled Header Validity Checking
  @cindex parameters, precompiled headers
  
! @deftypefn {Target Hook} void *TARGET_GET_PCH_VALIDITY (size_t *@var{sz})
! This hook returns the data needed by @code{TARGET_PCH_VALID_P} and sets
! @samp{*@var{sz}} to the size of the data in bytes.
! @end deftypefn
! 
! @deftypefn {Target Hook} const char *TARGET_PCH_VALID_P (const void *@var{data}, size_t @var{sz})
! This hook checks whether the options used to create a PCH file are
! compatible with the current settings.  It returns @code{NULL}
! if so and a suitable error message if not.  Error messages will
! be presented to the user and must be localized using @samp{_(@var{msg})}.
! 
! @var{data} is the data that was returned by @code{TARGET_GET_PCH_VALIDITY}
! when the PCH file was created and @var{sz} is the size of that data in bytes.
! It's safe to assume that the data was created by the same version of the
! compiler, so no format checking is needed.
! 
! The default definition of @code{default_pch_valid_p} should be
! suitable for most targets.
! @end deftypefn
! 
! @deftypefn {Target Hook} const char *TARGET_CHECK_PCH_TARGET_FLAGS (int @var{pch_flags})
! If this hook is nonnull, the default implementation of
! @code{TARGET_PCH_VALID_P} will use it to check for compatible values
! of @code{target_flags}.  @var{pch_flags} specifies the value that
! @code{target_flags} had when the PCH file was created.  The return
! value is the same as for @code{TARGET_PCH_VALID_P}.
  @end deftypefn
  
  @node C++ ABI
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.134
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.134 target.h
*** target.h	25 May 2005 11:52:10 -0000	1.134
--- target.h	27 May 2005 05:56:03 -0000
*************** struct gcc_target
*** 485,490 ****
--- 485,495 ----
    void * (* get_pch_validity) (size_t *);
    const char * (* pch_valid_p) (const void *, size_t);
  
+   /* If nonnull, this function checks whether a PCH file with the
+      given set of target flags can be used.  It returns NULL if so,
+      otherwise it returns an error message.  */
+   const char *(*check_pch_target_flags) (int);
+ 
    /* True if the compiler should give an enum type only as many
       bytes as it takes to represent the range of possible values of
       that type.  */
Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.122
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.122 target-def.h
*** target-def.h	25 May 2005 11:52:11 -0000	1.122
--- target-def.h	27 May 2005 05:56:04 -0000
*************** #define TARGET_BUILD_BUILTIN_VA_LIST std
*** 379,384 ****
--- 379,385 ----
  
  #define TARGET_GET_PCH_VALIDITY default_get_pch_validity
  #define TARGET_PCH_VALID_P default_pch_valid_p
+ #define TARGET_CHECK_PCH_TARGET_FLAGS NULL
  
  #define TARGET_DEFAULT_SHORT_ENUMS hook_bool_void_false
  
*************** #define TARGET_INITIALIZER			\
*** 551,556 ****
--- 552,558 ----
    TARGET_GIMPLIFY_VA_ARG_EXPR,			\
    TARGET_GET_PCH_VALIDITY,			\
    TARGET_PCH_VALID_P,				\
+   TARGET_CHECK_PCH_TARGET_FLAGS,		\
    TARGET_DEFAULT_SHORT_ENUMS,			\
    TARGET_BUILTIN_SETJMP_FRAME_VALUE,		\
    TARGET_MD_ASM_CLOBBERS,			\
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.955
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.955 toplev.c
*** toplev.c	25 May 2005 03:58:58 -0000	1.955
--- toplev.c	27 May 2005 05:56:04 -0000
*************** default_pch_valid_p (const void *data_p,
*** 1487,1492 ****
--- 1487,1493 ----
    const char *data = (const char *)data_p;
    const char *flag_that_differs = NULL;
    size_t i;
+   int tf;
  
    /* -fpic and -fpie also usually make a PCH invalid.  */
    if (data[0] != flag_pic)
*************** default_pch_valid_p (const void *data_p,
*** 1496,1506 ****
    data += 2;
  
    /* Check target_flags.  */
!   if (memcmp (data, &target_flags, sizeof (target_flags)) != 0)
      {
-       int tf;
- 
-       memcpy (&tf, data, sizeof (target_flags));
  #ifdef TARGET_SWITCHES
        for (i = 0; i < ARRAY_SIZE (target_switches); i++)
  	{
--- 1497,1511 ----
    data += 2;
  
    /* Check target_flags.  */
!   memcpy (&tf, data, sizeof (target_flags));
!   if (targetm.check_pch_target_flags)
!     {
!       const char *r = targetm.check_pch_target_flags (tf);
!       if (r != NULL)
! 	return r;
!     }
!   else if (tf != target_flags)
      {
  #ifdef TARGET_SWITCHES
        for (i = 0; i < ARRAY_SIZE (target_switches); i++)
  	{
Index: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.328
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.328 sh.c
*** config/sh/sh.c	25 May 2005 04:17:17 -0000	1.328
--- config/sh/sh.c	27 May 2005 05:56:07 -0000
*************** static tree sh_handle_trap_exit_attribut
*** 228,233 ****
--- 228,234 ----
  static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *);
  static void sh_output_function_epilogue (FILE *, HOST_WIDE_INT);
  static void sh_insert_attributes (tree, tree *);
+ static const char *sh_check_pch_target_flags (int);
  static int sh_adjust_cost (rtx, rtx, rtx, int);
  static int sh_issue_rate (void);
  static int sh_dfa_new_cycle (FILE *, int, rtx, int, int, int *sort_p);
*************** #define TARGET_GIMPLIFY_VA_ARG_EXPR sh_g
*** 467,474 ****
  #undef TARGET_VECTOR_MODE_SUPPORTED_P
  #define TARGET_VECTOR_MODE_SUPPORTED_P sh_vector_mode_supported_p
  
! #undef TARGET_PCH_VALID_P
! #define TARGET_PCH_VALID_P sh_pch_valid_p
  
  #undef TARGET_DWARF_CALLING_CONVENTION
  #define TARGET_DWARF_CALLING_CONVENTION sh_dwarf_calling_convention
--- 468,475 ----
  #undef TARGET_VECTOR_MODE_SUPPORTED_P
  #define TARGET_VECTOR_MODE_SUPPORTED_P sh_vector_mode_supported_p
  
! #undef TARGET_CHECK_PCH_TARGET_FLAGS
! #define TARGET_CHECK_PCH_TARGET_FLAGS sh_check_pch_target_flags
  
  #undef TARGET_DWARF_CALLING_CONVENTION
  #define TARGET_DWARF_CALLING_CONVENTION sh_dwarf_calling_convention
*************** sh_cfun_interrupt_handler_p (void)
*** 7515,7550 ****
  	  != NULL_TREE);
  }
  
! /* Like default_pch_valid_p, but only check certain target_flags.  */
! const char *
! sh_pch_valid_p (const void *data_p, size_t len)
! {
! #ifdef TARGET_OPTIONS
!   /* ??? We have a copy of this in toplev.c, but it is static.  */
!   static const struct
!     {
!       const char *const prefix;
!       const char **const variable;
!       const char *const description;
!       const char *const value;
!     }
!   target_options[] = TARGET_OPTIONS;
! #endif
  
!   const char *data = (const char *)data_p;
!   const char *flag_that_differs = NULL;
!   size_t i;
!   int old_flags;
! 
!   /* -fpic and -fpie also usually make a PCH invalid.  */
!   if (data[0] != flag_pic)
!     return _("created and used with different settings of -fpic");
!   if (data[1] != flag_pie)
!     return _("created and used with different settings of -fpie");
!   data += 2;
! 
!   /* Check target_flags.  */
!   memcpy (&old_flags, data, sizeof (target_flags));
    if ((old_flags ^ target_flags) & (MASK_SH1 | MASK_SH2 | MASK_SH3
  				    | MASK_SH_E | MASK_HARD_SH4
  				    | MASK_FPU_SINGLE | MASK_SH4))
--- 7516,7526 ----
  	  != NULL_TREE);
  }
  
! /* Implement TARGET_CHECK_PCH_TARGET_FLAGS.  */
  
! static const char *
! sh_check_pch_target_flags (int old_flags)
! {
    if ((old_flags ^ target_flags) & (MASK_SH1 | MASK_SH2 | MASK_SH3
  				    | MASK_SH_E | MASK_HARD_SH4
  				    | MASK_FPU_SINGLE | MASK_SH4))
*************** sh_pch_valid_p (const void *data_p, size
*** 7553,7592 ****
      return _("created and used with different ABIs");
    if ((old_flags ^ target_flags) & MASK_LITTLE_ENDIAN)
      return _("created and used with different endianness");
- 
-   data += sizeof (target_flags);
-   len -= sizeof (target_flags);
- 
-   /* Check string options.  */
- #ifdef TARGET_OPTIONS
-   for (i = 0; i < ARRAY_SIZE (target_options); i++)
-     {
-       const char *str = *target_options[i].variable;
-       size_t l;
-       if (! str)
- 	str = "";
-       l = strlen (str) + 1;
-       if (len < l || memcmp (data, str, l) != 0)
- 	{
- 	  flag_that_differs = target_options[i].prefix;
- 	  goto make_message;
- 	}
-       data += l;
-       len -= l;
-     }
- #endif
- 
    return NULL;
- 
-  make_message:
-   {
-     char *r;
-     asprintf (&r, _("created and used with differing settings of '-m%s'"),
- 		  flag_that_differs);
-     if (r == NULL)
-       return _("out of memory");
-     return r;
-   }
  }
  
  /* Predicates used by the templates.  */
--- 7529,7535 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]