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]

Fix two bugs in varasm.c and related stuff


This patch of somewhat-related changes contains two bugfixes, a performance
improvement, and some cleanups.

One bug is the fact that output_constant_def did not force string constants
to be written if TREE_CST_RTL was set.  This caused undefined symbols when
bootstrapping GNAT on some machines.  I saw it on an EV4 Alpha (but not an
EV56) and it was reported on the GCC list by somebody else a while ago.

The second bug was in the handling of constants that are VIEW_CONVERT_EXPRs,
which I fixed in two ways: by properly passing the modifier down in expand_expr
and by properly stripping conversions in output_constant.

I also did some cleanups in areas where I looked at when working with
those bugs, including adding two more lang hooks.

The performance change is in tree.c:save_expr.  In GCC 2.8.1, it's an error
to make a SAVE_EXPR for a PLUS_EXPR of a CONST_INT and a SAVE_EXPR since the
handling of non-bit-aligned fields at variable positions depends on being able
to see the PLUS_EXPR in DECL_FIELD_BITPOS.  This isn't the case in GCC 3,
but it's nevertheless better to avoid the additional SAVE_EXPR, especially
since GCSE can find the multiple operations if indeed they occur.

Since variable_size now may not return a SAVE_EXPR, the test for it in
put_pending_size needs to be removed, but it's only called when there is
something that likely needs evaluation (and if it doesn't, the evaluation
won't do anything).

Tested on alphaev56-dec-osf4.0c.

Tue Nov 27 08:21:47 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>

	* Makefile.in (c-lang.o): Depends on langhooks-def.h.
	(expr.o, varasm.o): Depends on langhooks.h.
	* c-common.c (c_safe_from_p): Always declare.
	(c_expand_expr): Refine when declared.
	* c-lang.c (c-common.h): Now include.
	(LANG_HOOKS_SAFE_FROM_P): Define new hook.
	(c_init): Don't set lang_safe_from_expr.
	* expr.c (langhooks.h): Now include.
	(lang_safe_from_p): No longer define.
	(safe_from_p): Use lang hook.
	(expand_expr): Set IGNORE if VOID_TYPE result of VIEW_CONVERT_EXPR too.
	(expand_expr, case VIEW_CONVERT_EXPR): Pass ro_modifier down.
	* expr.h (lang_expand_constant, lang_safe_from_p): Delete.
	* langhooks-def.h (lhd_return_tree, lhd_safe_from_p): New decls.
	(LANG_HOOKS_EXPAND_CONSTANT, LANG_HOOKS_SAFE_FROM_P): New hooks.
	* langhooks.c (lhd_return_tree, lhd_safe_from_p): New functions.
	* langhooks.h (struct lang_hooks): New fields expand_constant
	and safe_from_p.
	* output.h (output_constant): Size arg is HOST_WIDE_INT.
	* stmt.c (expand_decl_init): No longer need to expand constant
	for CONST_DECL.
	* stor-layout.c (put_pending_size): Don't check for SAVE_EXPR.
	* toplev.c (lang_expand_constant): Delete var.
	* tree.c (save_expr): Don't put another SAVE_EXPR around simple
	operations on SAVE_EXPR.
	* varasm.c (langhooks.h): Now include.
	(compare_constant_1): Use lang_hooks, not lang_expand_constant.
	(record_constant_1, output_addressed_constants): Likewise.
	(initializer_constant_valid_p, output_constant): Likewise.
	(output_constant_def): Process no-defer of string constant.
	(output_addressed_constants, case ADDR_EXPR): Use handled_component_p.
	(output_constant): Strip more conversions.
	Track our size and pad for the rest.
	(array_size_for_constructor): Remove code for non-byte STRING_CST.
	(output_constructor): SIZE now HOST_WIDE_INT.
	* cp/Make-lang.in (cp-lang.o): Depends on c-common.h.
	* cp/cp-lang.c (c-common.h): Include.
	(LANG_HOOKS_EXPAND_CONSTANT, LANG_HOOKS_SAFE_FROM_P): New hooks.
	* cp/decl.c (cxx_init_decl_processing): Don't set lang_safe_from_p.
	* cp/expr.c (init_cplus_expand): Don't set lang_expand_constant.

*** Makefile.in	2001/11/26 23:44:46	1.788
--- Makefile.in	2001/11/27 12:26:15
*************** c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM
*** 1174,1178 ****
      $(GGC_H) c-lex.h toplev.h diagnostic.h output.h function.h $(VARRAY_H) \
      $(RTL_H) $(EXPR_H) tree-inline.h insn-config.h integrate.h langhooks.h \
!     langhooks-def.h
  c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) c-lex.h \
      debug.h $(C_TREE_H) \
--- 1174,1178 ----
      $(GGC_H) c-lex.h toplev.h diagnostic.h output.h function.h $(VARRAY_H) \
      $(RTL_H) $(EXPR_H) tree-inline.h insn-config.h integrate.h langhooks.h \
!     langhooks-def.h c-common.h
  c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) c-lex.h \
      debug.h $(C_TREE_H) \
*************** varasm.o : varasm.c $(CONFIG_H) $(SYSTEM
*** 1395,1399 ****
     function.h $(EXPR_H) hard-reg-set.h $(REGS_H) $(OBSTACK_H) \
     output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
!    $(HASHTAB_H) $(TARGET_H)
  function.o : function.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
     function.h $(EXPR_H) libfuncs.h $(REGS_H) hard-reg-set.h \
--- 1395,1399 ----
     function.h $(EXPR_H) hard-reg-set.h $(REGS_H) $(OBSTACK_H) \
     output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
!    $(HASHTAB_H) $(TARGET_H) langhooks.h
  function.o : function.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
     function.h $(EXPR_H) libfuncs.h $(REGS_H) hard-reg-set.h \
*************** expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) 
*** 1409,1413 ****
     $(REGS_H) $(EXPR_H) $(OPTABS_H) libfuncs.h insn-attr.h insn-config.h \
     $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
!    except.h reload.h $(GGC_H) intl.h $(TM_P_H)
  builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
     $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
--- 1409,1413 ----
     $(REGS_H) $(EXPR_H) $(OPTABS_H) libfuncs.h insn-attr.h insn-config.h \
     $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
!    except.h reload.h $(GGC_H) langhooks.h intl.h $(TM_P_H)
  builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
     $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
*** c-common.h	2001/11/26 23:44:47	1.100
--- c-common.h	2001/11/27 12:26:16
*************** extern tree lookup_label			PARAMS ((tree
*** 803,814 ****
  extern void (*back_end_hook) PARAMS ((tree));
  
! #ifdef RTX_CODE
  
! extern struct rtx_def *c_expand_expr            PARAMS ((tree, rtx,
! 							 enum machine_mode,
! 							 enum expand_modifier));
  
  extern int c_safe_from_p                        PARAMS ((rtx, tree));
- #endif
  
  extern int c_unsafe_for_reeval			PARAMS ((tree));
--- 803,814 ----
  extern void (*back_end_hook) PARAMS ((tree));
  
! /* enum expand_modified is in expr.h, as is the macro below.  */
  
! #ifdef QUEUED_VAR
! extern rtx c_expand_expr            PARAMS ((tree, rtx, enum machine_mode,
! 					     enum expand_modifier));
! #endif
  
  extern int c_safe_from_p                        PARAMS ((rtx, tree));
  
  extern int c_unsafe_for_reeval			PARAMS ((tree));
*** c-lang.c	2001/11/26 23:44:48	1.69
--- c-lang.c	2001/11/27 12:26:16
*************** Software Foundation, 59 Temple Place - S
*** 35,38 ****
--- 35,39 ----
  #include "expr.h"
  #include "c-tree.h"
+ #include "c-common.h"
  #include "c-lex.h"
  #include "cpplib.h"
*************** static int c_cannot_inline_tree_fn PARAM
*** 65,68 ****
--- 66,71 ----
  #undef LANG_HOOKS_GET_ALIAS_SET
  #define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
+ #undef LANG_HOOKS_SAFE_FROM_P
+ #define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
  #undef LANG_HOOKS_PRINT_IDENTIFIER
  #define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
*************** c_init (filename)
*** 122,126 ****
    mark_lang_status = &mark_c_function_context;
    lang_expand_expr = &c_expand_expr;
-   lang_safe_from_p = &c_safe_from_p;
    diagnostic_format_decoder (global_dc) = &c_tree_printer;
    lang_expand_decl_stmt = &c_expand_decl_stmt;
--- 125,128 ----
*** expr.c	2001/11/26 22:29:46	1.385
--- expr.c	2001/11/27 12:26:25
*************** Software Foundation, 59 Temple Place - S
*** 43,46 ****
--- 43,47 ----
  #include "toplev.h"
  #include "ggc.h"
+ #include "langhooks.h"
  #include "intl.h"
  #include "tm_p.h"
*************** Software Foundation, 59 Temple Place - S
*** 73,85 ****
  #endif
  
- /* Hook called by safe_from_p for language-specific tree codes.  It is
-    up to the language front-end to install a hook if it has any such
-    codes that safe_from_p needs to know about.  Since same_from_p will
-    recursively explore the TREE_OPERANDs of an expression, this hook
-    should not reexamine those pieces.  This routine may recursively
-    call safe_from_p; it should always pass `0' as the TOP_P
-    parameter.  */
- int (*lang_safe_from_p) PARAMS ((rtx, tree));
- 
  /* If this is nonzero, we do not bother generating VOLATILE
     around volatile memory references, and we are willing to
--- 74,77 ----
*************** safe_from_p (x, exp, top_p)
*** 5855,5860 ****
        if ((unsigned int) TREE_CODE (exp)
  	  >= (unsigned int) LAST_AND_UNUSED_TREE_CODE
! 	  && lang_safe_from_p
! 	  && !(*lang_safe_from_p) (x, exp))
  	return 0;
      }
--- 5847,5851 ----
        if ((unsigned int) TREE_CODE (exp)
  	  >= (unsigned int) LAST_AND_UNUSED_TREE_CODE
! 	  && !(*lang_hooks.safe_from_p) (x, exp))
  	return 0;
      }
*************** expand_expr (exp, target, tmode, modifie
*** 6149,6153 ****
  	    || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
  		 || code == CONVERT_EXPR || code == REFERENCE_EXPR
! 		 || code == COND_EXPR)
  		&& TREE_CODE (type) == VOID_TYPE));
  
--- 6140,6144 ----
  	    || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
  		 || code == CONVERT_EXPR || code == REFERENCE_EXPR
! 		 || code == COND_EXPR || code == VIEW_CONVERT_EXPR)
  		&& TREE_CODE (type) == VOID_TYPE));
  
*************** expand_expr (exp, target, tmode, modifie
*** 7537,7541 ****
  
      case VIEW_CONVERT_EXPR:
!       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0);
  
        /* If the input and output modes are both the same, we are done.
--- 7528,7532 ----
  
      case VIEW_CONVERT_EXPR:
!       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, ro_modifier);
  
        /* If the input and output modes are both the same, we are done.
*** expr.h	2001/11/15 23:44:55	1.104
--- expr.h	2001/11/27 12:26:25
*************** extern rtx (*lang_expand_expr) PARAMS ((
*** 776,797 ****
  					enum expand_modifier modifier));
  
- #ifdef TREE_CODE
- /* Hook called by output_constant for language-specific tree codes.
-    It is up to the language front-end to install a hook if it has any
-    such codes that output_constant needs to know about.  Returns a
-    language-independent constant equivalent to its input.  */
- extern tree (*lang_expand_constant) PARAMS ((tree));
- 
  extern int safe_from_p PARAMS ((rtx, tree, int));
- 
- /* Hook called by safe_from_p for language-specific tree codes.  It is
-    up to the language front-end to install a hook if it has any such
-    codes that safe_from_p needs to know about.  Since same_from_p will
-    recursively explore the TREE_OPERANDs of an expression, this hook
-    should not reexamine those pieces.  This routine may recursively
-    call safe_from_p; it should always pass `0' as the TOP_P
-    parameter.  */
- extern int (*lang_safe_from_p) PARAMS ((rtx, tree));
- #endif
  
  /* Call this once to initialize the contents of the optabs
--- 776,780 ----
*** langhooks-def.h	2001/11/26 23:44:50	1.5
--- langhooks-def.h	2001/11/27 12:26:26
*************** extern void lhd_do_nothing PARAMS ((void
*** 41,44 ****
--- 41,46 ----
  extern int lhd_decode_option PARAMS ((int, char **));
  extern HOST_WIDE_INT lhd_get_alias_set PARAMS ((tree));
+ extern tree lhd_return_tree PARAMS ((tree));
+ extern int lhd_safe_from_p PARAMS ((rtx, tree));
  extern void lhd_clear_binding_stack PARAMS ((void));
  extern void lhd_print_tree_nothing PARAMS ((FILE *, tree, int));
*************** int lhd_tree_inlining_anon_aggr_type_p		
*** 68,71 ****
--- 70,75 ----
  #define LANG_HOOKS_POST_OPTIONS		lhd_do_nothing
  #define LANG_HOOKS_GET_ALIAS_SET	lhd_get_alias_set
+ #define LANG_HOOKS_EXPAND_CONSTANT	lhd_return_tree
+ #define LANG_HOOKS_SAFE_FROM_P		lhd_safe_from_p
  #define LANG_HOOKS_HONOR_READONLY	false
  #define LANG_HOOKS_PRINT_STATISTICS	lhd_do_nothing
*************** int lhd_tree_dump_type_quals			PARAMS ((
*** 127,130 ****
--- 131,136 ----
    LANG_HOOKS_CLEAR_BINDING_STACK, \
    LANG_HOOKS_GET_ALIAS_SET, \
+   LANG_HOOKS_EXPAND_CONSTANT, \
+   LANG_HOOKS_SAFE_FROM_P, \
    LANG_HOOKS_HONOR_READONLY, \
    LANG_HOOKS_PRINT_STATISTICS, \
*** langhooks.c	2001/11/22 02:32:52	1.9
--- langhooks.c	2001/11/27 12:26:27
*************** lhd_do_nothing ()
*** 39,42 ****
--- 39,51 ----
  }
  
+ /* Do nothing (return the tree node passed).  */
+ 
+ tree
+ lhd_return_tree (t)
+      tree t;
+ {
+   return t;
+ }
+ 
  /* Do nothing; the default hook to decode an option.  */
  
*************** lhd_print_tree_nothing (file, node, inde
*** 57,60 ****
--- 66,79 ----
       int indent ATTRIBUTE_UNUSED;
  {
+ }
+ 
+ /* Called from safe_from_p.  */
+ 
+ int
+ lhd_safe_from_p (x, exp)
+      rtx x;
+      tree exp;
+ {
+   return 1;
  }
  

*** langhooks.h	2001/11/26 23:44:50	1.12
--- langhooks.h	2001/11/27 12:26:27
*************** struct lang_hooks
*** 110,113 ****
--- 110,127 ----
    HOST_WIDE_INT (*get_alias_set) PARAMS ((tree));
  
+   /* Called with an expression that is to be processed as a constant.
+      Returns either the same expression or a language-independent
+      constant equivalent to its input.  */
+   tree (*expand_constant) PARAMS ((tree));
+ 
+   /* Hook called by safe_from_p for language-specific tree codes.  It is
+      up to the language front-end to install a hook if it has any such
+      codes that safe_from_p needs to know about.  Since same_from_p will
+      recursively explore the TREE_OPERANDs of an expression, this hook
+      should not reexamine those pieces.  This routine may recursively
+      call safe_from_p; it should always pass `0' as the TOP_P
+      parameter.  */
+   int (*safe_from_p) PARAMS ((rtx, tree));
+ 
    /* Nonzero if TYPE_READONLY and TREE_READONLY should always be honored.  */
    bool honor_readonly;
*** output.h	2001/11/14 13:51:09	1.88
--- output.h	2001/11/27 12:26:27
*************** extern tree initializer_constant_valid_p
*** 369,373 ****
  
     ALIGN is the alignment in bits that may be assumed for the data.  */
! extern void output_constant		PARAMS ((tree, int, unsigned));
  #endif
  
--- 369,374 ----
  
     ALIGN is the alignment in bits that may be assumed for the data.  */
! extern void output_constant		PARAMS ((tree, HOST_WIDE_INT,
! 						 unsigned int));
  #endif
  
*** stmt.c	2001/11/23 02:05:19	1.230
--- stmt.c	2001/11/27 12:26:32
*************** expand_decl_init (decl)
*** 4109,4127 ****
    int was_used = TREE_USED (decl);
  
!   /* If this is a CONST_DECL, we don't have to generate any code, but
!      if DECL_INITIAL is a constant, call expand_expr to force TREE_CST_RTL
!      to be set while in the obstack containing the constant.  If we don't
!      do this, we can lose if we have functions nested three deep and the middle
!      function makes a CONST_DECL whose DECL_INITIAL is a STRING_CST while
!      the innermost function is the first to expand that STRING_CST.  */
!   if (TREE_CODE (decl) == CONST_DECL)
!     {
!       if (DECL_INITIAL (decl) && TREE_CONSTANT (DECL_INITIAL (decl)))
! 	expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
! 		     EXPAND_INITIALIZER);
!       return;
!     }
! 
!   if (TREE_STATIC (decl))
      return;
  
--- 4109,4116 ----
    int was_used = TREE_USED (decl);
  
!   /* If this is a CONST_DECL, we don't have to generate any code.  Likewise
!      for static decls.  */
!   if (TREE_CODE (decl) == CONST_DECL
!       || TREE_STATIC (decl))
      return;
  
*** stor-layout.c	2001/10/24 21:47:23	1.110
--- stor-layout.c	2001/11/27 12:26:33
*************** put_pending_size (expr)
*** 115,120 ****
       tree expr;
  {
!   if (TREE_CODE (expr) == SAVE_EXPR)
!     pending_sizes = tree_cons (NULL_TREE, expr, pending_sizes);
  }
  
--- 115,119 ----
       tree expr;
  {
!   pending_sizes = tree_cons (NULL_TREE, expr, pending_sizes);
  }
  
*************** variable_size (size)
*** 141,145 ****
    /* If the language-processor is to take responsibility for variable-sized
       items (e.g., languages which have elaboration procedures like Ada),
!      just return SIZE unchanged.  Likewise for self-referential sizes.  */
    if (TREE_CONSTANT (size)
        || global_bindings_p () < 0 || contains_placeholder_p (size))
--- 140,145 ----
    /* If the language-processor is to take responsibility for variable-sized
       items (e.g., languages which have elaboration procedures like Ada),
!      just return SIZE unchanged.  Likewise for self-referential sizes and
!      constant sizes.  */
    if (TREE_CONSTANT (size)
        || global_bindings_p () < 0 || contains_placeholder_p (size))
*** toplev.c	2001/11/27 00:32:00	1.546
--- toplev.c	2001/11/27 12:26:37
*************** typedef rtx (*lang_expand_expr_t)
*** 396,401 ****
  lang_expand_expr_t lang_expand_expr = 0;
  
- tree (*lang_expand_constant) PARAMS ((tree)) = 0;
- 
  /* Pointer to function to finish handling an incomplete decl at the
     end of compilation.  */
--- 396,399 ----
*** tree.c	2001/11/09 23:30:25	1.219
--- tree.c	2001/11/27 12:26:40
*************** save_expr (expr)
*** 1550,1553 ****
--- 1550,1554 ----
  {
    tree t = fold (expr);
+   tree inner;
  
    /* We don't care about whether this can be used as an lvalue in this
*************** save_expr (expr)
*** 1556,1559 ****
--- 1557,1572 ----
      t = TREE_OPERAND (t, 0);
  
+ 
+   /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and
+      a constant, it will be more efficient to not make another SAVE_EXPR since
+      it will allow better simplification and GCSE will be able to merge the
+      computations if they actualy occur.  */
+   for (inner = t;
+        (TREE_CODE_CLASS (TREE_CODE (inner)) == '1'
+ 	|| (TREE_CODE_CLASS (TREE_CODE (inner)) == '2'
+ 	    && TREE_CONSTANT (TREE_OPERAND (inner, 1))));
+        inner = TREE_OPERAND (inner, 0))
+     ;
+ 
    /* If the tree evaluates to a constant, then we don't want to hide that
       fact (i.e. this allows further folding, and direct checks for constants).
*************** save_expr (expr)
*** 1561,1567 ****
       Since it is no problem to reevaluate literals, we just return the
       literal node.  */
! 
!   if (TREE_CONSTANT (t) || (TREE_READONLY (t) && ! TREE_SIDE_EFFECTS (t))
!       || TREE_CODE (t) == SAVE_EXPR || TREE_CODE (t) == ERROR_MARK)
      return t;
  
--- 1574,1580 ----
       Since it is no problem to reevaluate literals, we just return the
       literal node.  */
!   if (TREE_CONSTANT (inner)
!       || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
!       || TREE_CODE (inner) == SAVE_EXPR || TREE_CODE (inner) == ERROR_MARK)
      return t;
  
*** varasm.c	2001/11/23 11:21:07	1.229
--- varasm.c	2001/11/27 12:26:44
*************** Software Foundation, 59 Temple Place - S
*** 44,47 ****
--- 44,48 ----
  #include "c-pragma.h"
  #include "ggc.h"
+ #include "langhooks.h"
  #include "tm_p.h"
  #include "debug.h"
*************** static void output_after_function_consta
*** 169,173 ****
  static unsigned HOST_WIDE_INT array_size_for_constructor PARAMS ((tree));
  static unsigned min_align		PARAMS ((unsigned, unsigned));
! static void output_constructor		PARAMS ((tree, int, unsigned));
  #ifdef ASM_WEAKEN_LABEL
  static void remove_from_pending_weak_list	PARAMS ((const char *));
--- 170,175 ----
  static unsigned HOST_WIDE_INT array_size_for_constructor PARAMS ((tree));
  static unsigned min_align		PARAMS ((unsigned, unsigned));
! static void output_constructor		PARAMS ((tree, HOST_WIDE_INT,
! 						 unsigned int));
  #ifdef ASM_WEAKEN_LABEL
  static void remove_from_pending_weak_list	PARAMS ((const char *));
*************** struct constant_descriptor
*** 2478,2481 ****
--- 2480,2488 ----
  static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
  
+ /* We maintain a hash table of STRING_CST values.  Unless we are asked to force
+    out a string constant, we defer output of the constants until we know
+    they are actually used.  This will be if something takes its address or if
+    there is a usage of the string in the RTL of a function.  */
+ 
  #define STRHASH(x) ((hashval_t)((long)(x) >> 3))
  
*************** compare_constant_1 (exp, p)
*** 2900,2909 ****
  
      default:
!       if (lang_expand_constant)
!         {
!           exp = (*lang_expand_constant) (exp);
!           return compare_constant_1 (exp, p);
!         }
!       return 0;
      }
  
--- 2907,2918 ----
  
      default:
!       {
! 	tree new = (*lang_hooks.expand_constant) (exp);
! 
! 	if (new != exp)
!           return compare_constant_1 (new, p);
! 	else
! 	  return 0;
!       }
      }
  
*************** record_constant_1 (exp)
*** 3112,3121 ****
  
      default:
!       if (lang_expand_constant)
!         {
!           exp = (*lang_expand_constant) (exp);
            record_constant_1 (exp);
!         }
!       return;
      }
  
--- 3121,3131 ----
  
      default:
!       {
! 	tree new = (*lang_hooks.expand_constant) (exp);
! 
! 	if (new != exp)
            record_constant_1 (exp);
! 	return;
!       }
      }
  
*************** output_constant_def (exp, defer)
*** 3284,3288 ****
    rtx rtl;
  
!   if (TREE_CODE (exp) != INTEGER_CST && TREE_CST_RTL (exp))
      return TREE_CST_RTL (exp);
  
--- 3294,3301 ----
    rtx rtl;
  
!   /* We can't just use the saved RTL if this is a defererred string constant
!      and we are not to defer anymode.  */
!   if (TREE_CODE (exp) != INTEGER_CST && TREE_CST_RTL (exp)
!       && (defer || !STRING_POOL_ADDRESS_P (XEXP (TREE_CST_RTL (exp), 0))))
      return TREE_CST_RTL (exp);
  
*************** output_addressed_constants (exp)
*** 4193,4219 ****
  {
    int reloc = 0;
  
    /* Give the front-end a chance to convert VALUE to something that
       looks more like a constant to the back-end.  */
!   if (lang_expand_constant)
!     exp = (*lang_expand_constant) (exp);
  
    switch (TREE_CODE (exp))
      {
      case ADDR_EXPR:
!       {
! 	tree constant = TREE_OPERAND (exp, 0);
  
- 	while (TREE_CODE (constant) == COMPONENT_REF)
- 	  {
- 	    constant = TREE_OPERAND (constant, 0);
- 	  }
- 
- 	if (TREE_CODE_CLASS (TREE_CODE (constant)) == 'c'
- 	    || TREE_CODE (constant) == CONSTRUCTOR)
- 	  /* No need to do anything here
- 	     for addresses of variables or functions.  */
- 	  output_constant_def (constant, 0);
-       }
        reloc = 1;
        break;
--- 4206,4229 ----
  {
    int reloc = 0;
+   tree tem;
  
    /* Give the front-end a chance to convert VALUE to something that
       looks more like a constant to the back-end.  */
!   exp = (*lang_hooks.expand_constant) (exp);
  
    switch (TREE_CODE (exp))
      {
      case ADDR_EXPR:
!       /* Go inside any operations that get_inner_reference can handle and see
! 	 if what's inside is a constant: no need to do anything here for
! 	 addresses of variables or functions.  */
!       for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
! 	   tem = TREE_OPERAND (tem, 0))
! 	;
! 
!       if (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c'
! 	    || TREE_CODE (tem) == CONSTRUCTOR)
! 	  output_constant_def (tem, 0);
  
        reloc = 1;
        break;
*************** output_addressed_constants (exp)
*** 4232,4241 ****
  
      case CONSTRUCTOR:
!       {
! 	tree link;
! 	for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
! 	  if (TREE_VALUE (link) != 0)
! 	    reloc |= output_addressed_constants (TREE_VALUE (link));
!       }
        break;
  
--- 4242,4249 ----
  
      case CONSTRUCTOR:
!       for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
! 	if (TREE_VALUE (tem) != 0)
! 	    reloc |= output_addressed_constants (TREE_VALUE (tem));
! 
        break;
  
*************** initializer_constant_valid_p (value, end
*** 4263,4268 ****
    /* Give the front-end a chance to convert VALUE to something that
       looks more like a constant to the back-end.  */
!   if (lang_expand_constant)
!     value = (*lang_expand_constant) (value);
  
    switch (TREE_CODE (value))
--- 4271,4275 ----
    /* Give the front-end a chance to convert VALUE to something that
       looks more like a constant to the back-end.  */
!   value = (*lang_hooks.expand_constant) (value);
  
    switch (TREE_CODE (value))
*************** void
*** 4439,4474 ****
  output_constant (exp, size, align)
       tree exp;
!      int size;
       unsigned int align;
  {
!   enum tree_code code = TREE_CODE (TREE_TYPE (exp));
  
    /* Some front-ends use constants other than the standard language-indepdent
       varieties, but which may still be output directly.  Give the front-end a
       chance to convert EXP to a language-independent representation.  */
!   if (lang_expand_constant)
!     {
!       exp = (*lang_expand_constant) (exp);
!       code = TREE_CODE (TREE_TYPE (exp));
!     }
  
    if (size == 0 || flag_syntax_only)
      return;
  
!   /* Eliminate the NON_LVALUE_EXPR_EXPR that makes a cast not be an lvalue.
!      That way we get the constant (we hope) inside it.  Also, strip off any
!      NOP_EXPR that converts between two record, union, array, or set types
!      or a CONVERT_EXPR that converts to a union TYPE.  */
!   while ((TREE_CODE (exp) == NOP_EXPR
! 	  && (TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0))
! 	      || AGGREGATE_TYPE_P (TREE_TYPE (exp))))
! 	 || (TREE_CODE (exp) == CONVERT_EXPR && code == UNION_TYPE)
  	 || TREE_CODE (exp) == NON_LVALUE_EXPR
  	 || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
!     {
!       exp = TREE_OPERAND (exp, 0);
!       code = TREE_CODE (TREE_TYPE (exp));
!     }
  
    /* Allow a constructor with no elements for any data type.
       This means to fill the space with zeros.  */
--- 4446,4473 ----
  output_constant (exp, size, align)
       tree exp;
!      HOST_WIDE_INT size;
       unsigned int align;
  {
!   enum tree_code code;
!   HOST_WIDE_INT thissize;
  
    /* Some front-ends use constants other than the standard language-indepdent
       varieties, but which may still be output directly.  Give the front-end a
       chance to convert EXP to a language-independent representation.  */
!   exp = (*lang_hooks.expand_constant) (exp);
  
    if (size == 0 || flag_syntax_only)
      return;
  
!   /* Eliminate any conversions since we'll be outputting the underlying
!      constant.  */
!   while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
  	 || TREE_CODE (exp) == NON_LVALUE_EXPR
  	 || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
!     exp = TREE_OPERAND (exp, 0);
  
+   code = TREE_CODE (TREE_TYPE (exp));
+   thissize = int_size_in_bytes (TREE_TYPE (exp));
+ 
    /* Allow a constructor with no elements for any data type.
       This means to fill the space with zeros.  */
*************** output_constant (exp, size, align)
*** 4491,4494 ****
--- 4490,4495 ----
      }
  
+   /* Now output the underlying data.  If we've handling the padding, return.
+      Otherwise, break and ensure THISSIZE is the size written.  */
    switch (code)
      {
*************** output_constant (exp, size, align)
*** 4499,4512 ****
      case POINTER_TYPE:
      case REFERENCE_TYPE:
-       /* ??? What about       (int)((float)(int)&foo + 4)    */
-       while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
- 	     || TREE_CODE (exp) == NON_LVALUE_EXPR)
- 	exp = TREE_OPERAND (exp, 0);
- 
        if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
  					   EXPAND_INITIALIZER),
  			      size, align, 0))
  	error ("initializer for integer value is too complicated");
-       size = 0;
        break;
  
--- 4500,4507 ----
*************** output_constant (exp, size, align)
*** 4518,4529 ****
  		     mode_for_size (size * BITS_PER_UNIT, MODE_FLOAT, 0),
  		     align);
-       size = 0;
        break;
  
      case COMPLEX_TYPE:
!       output_constant (TREE_REALPART (exp), size / 2, align);
!       output_constant (TREE_IMAGPART (exp), size / 2,
! 		       min_align (align, BITS_PER_UNIT * (size / 2)));
!       size -= (size / 2) * 2;
        break;
  
--- 4513,4522 ----
  		     mode_for_size (size * BITS_PER_UNIT, MODE_FLOAT, 0),
  		     align);
        break;
  
      case COMPLEX_TYPE:
!       output_constant (TREE_REALPART (exp), thissize / 2, align);
!       output_constant (TREE_IMAGPART (exp), thissize / 2,
! 		       min_align (align, BITS_PER_UNIT * (thissize / 2)));
        break;
  
*************** output_constant (exp, size, align)
*** 4536,4549 ****
        else if (TREE_CODE (exp) == STRING_CST)
  	{
! 	  int excess = 0;
! 
! 	  if (size > TREE_STRING_LENGTH (exp))
! 	    {
! 	      excess = size - TREE_STRING_LENGTH (exp);
! 	      size = TREE_STRING_LENGTH (exp);
! 	    }
! 
! 	  assemble_string (TREE_STRING_POINTER (exp), size);
! 	  size = excess;
  	}
        else
--- 4529,4534 ----
        else if (TREE_CODE (exp) == STRING_CST)
  	{
! 	  thissize = MIN (TREE_STRING_LENGTH (exp), size);
! 	  assemble_string (TREE_STRING_POINTER (exp), thissize);
  	}
        else
*************** output_constant (exp, size, align)
*** 4563,4573 ****
  	assemble_integer (expand_expr (exp, NULL_RTX,
  				       VOIDmode, EXPAND_INITIALIZER),
! 			  size, align, 1);
        else if (TREE_CODE (exp) == CONSTRUCTOR)
  	{
! 	  unsigned char *buffer = (unsigned char *) alloca (size);
! 	  if (get_set_constructor_bytes (exp, buffer, size))
  	    abort ();
! 	  assemble_string ((char *) buffer, size);
  	}
        else
--- 4548,4558 ----
  	assemble_integer (expand_expr (exp, NULL_RTX,
  				       VOIDmode, EXPAND_INITIALIZER),
! 			 thissize, align, 1);
        else if (TREE_CODE (exp) == CONSTRUCTOR)
  	{
! 	  unsigned char *buffer = (unsigned char *) alloca (thissize);
! 	  if (get_set_constructor_bytes (exp, buffer, thissize))
  	    abort ();
! 	  assemble_string ((char *) buffer, thissize);
  	}
        else
*************** output_constant (exp, size, align)
*** 4576,4582 ****
  
      default:
!       break; /* ??? */
      }
  
    if (size > 0)
      assemble_zeros (size);
--- 4561,4568 ----
  
      default:
!       abort ();
      }
  
+   size -= thissize;
    if (size > 0)
      assemble_zeros (size);
*************** array_size_for_constructor (val)
*** 4594,4604 ****
    tree max_index, i;
  
    if (TREE_CODE (val) == STRING_CST)
!     {
!       HOST_WIDE_INT len = TREE_STRING_LENGTH(val);
!       HOST_WIDE_INT esz = int_size_in_bytes (TREE_TYPE (TREE_TYPE (val)));
!       HOST_WIDE_INT tsz = len * esz;
!       return tsz;
!     }
    max_index = NULL_TREE;
    for (i = CONSTRUCTOR_ELTS (val); i ; i = TREE_CHAIN (i))
--- 4580,4589 ----
    tree max_index, i;
  
+   /* This code used to attempt to handle string constants that are not
+      arrays of single-bytes, but nothing else does, so there's no point in
+      doing it here.  */
    if (TREE_CODE (val) == STRING_CST)
!     return TREE_STRING_LENGTH (val);
! 
    max_index = NULL_TREE;
    for (i = CONSTRUCTOR_ELTS (val); i ; i = TREE_CHAIN (i))
*************** static void
*** 4633,4637 ****
  output_constructor (exp, size, align)
       tree exp;
!      int size;
       unsigned int align;
  {
--- 4618,4622 ----
  output_constructor (exp, size, align)
       tree exp;
!      HOST_WIDE_INT size;
       unsigned int align;
  {
*** cp/Make-lang.in	2001/11/22 02:32:54	1.99
--- cp/Make-lang.in	2001/11/27 12:26:51
*************** cp/lex.o: cp/lex.c $(CXX_TREE_H) cp/pars
*** 244,248 ****
    toplev.h output.h mbchar.h $(GGC_H) input.h diagnostic.h cp/operators.def \
    $(TM_P_H)
! cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) toplev.h langhooks.h langhooks-def.h
  cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \
    output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \
--- 244,249 ----
    toplev.h output.h mbchar.h $(GGC_H) input.h diagnostic.h cp/operators.def \
    $(TM_P_H)
! cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) toplev.h langhooks.h langhooks-def.h \
!   c-common.h
  cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \
    output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \
*** cp/cp-lang.c	2001/11/22 02:32:54	1.7
--- cp/cp-lang.c	2001/11/27 12:26:51
*************** Boston, MA 02111-1307, USA.  */
*** 24,27 ****
--- 24,28 ----
  #include "tree.h"
  #include "cp-tree.h"
+ #include "c-common.h"
  #include "toplev.h"
  #include "langhooks.h"
*************** static HOST_WIDE_INT cxx_get_alias_set P
*** 46,49 ****
--- 47,54 ----
  #undef LANG_HOOKS_GET_ALIAS_SET
  #define LANG_HOOKS_GET_ALIAS_SET cxx_get_alias_set
+ #undef LANG_HOOKS_EXPAND_CONSTANT
+ #define LANG_HOOKS_EXPAND_CONSTANT cplus_expand_constant
+ #undef LANG_HOOKS_SAFE_FROM_P
+ #define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
  #undef LANG_HOOKS_PRINT_STATISTICS
  #define LANG_HOOKS_PRINT_STATISTICS cxx_print_statistics
*** cp/decl.c	2001/11/22 02:32:55	1.828
--- cp/decl.c	2001/11/27 12:27:06
*************** cxx_init_decl_processing ()
*** 6408,6412 ****
    free_lang_status = &pop_cp_function_context;
    mark_lang_status = &mark_cp_function_context;
-   lang_safe_from_p = &c_safe_from_p;
    lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
  
--- 6408,6411 ----
*** cp/expr.c	2001/07/25 09:00:35	1.61
--- cp/expr.c	2001/11/27 12:27:06
*************** init_cplus_expand ()
*** 136,140 ****
  {
    lang_expand_expr = cplus_expand_expr;
-   lang_expand_constant = cplus_expand_constant;
  }
  
--- 136,139 ----


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