C++ PATCH for function-at-a-time mode

Mark Mitchell markATcodesourcery.com
Fri Sep 17 18:24:00 GMT 1999


We are now function-at-a-time in C++.  Well, almost.  There are still
a few places where we do semantic processing while generating RTL, and
static initialization functions are still not in function-at-a-time
mode.  These warts will go soon.

Although I can bootstrap, and make check without regressions, I expect
that I have just introduced some bugs.  Some may go away "by
themselves" as the last bits of function-at-a-time stuff get cleaned
up.  Obviously, I'll deal with any regressions ASAP.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com


1999-09-17  Mark Mitchell  <mark@codesourcery.com>

        Turn on function-at-a-time processing.  
	* cp-tree.h (doing_semantic_analysis_p): New macro.
	(SF_DEFAULT): Define to zero, not SF_EXPAND.
	(start_handler_parms): Change prototype.
	(expand_start_catch_block): Likewise.
	(expand_end_catch_block): Likewise.
	(expand_start_eh_spec): Likewise.
	(expand_end_eh_spec): Declare.
	(finish_handler_parms): Change prototype.
	(begin_catch_block): Declare.
	(finish_handler): Change prototype.
	(do_pushlevel): Declare.
	(do_poplevel): Likewise.  
	* decl.c (pushlevel): Don't create
	binding levels when not doing semantic analysis.
	(poplevel): Don't pop them.
	(pushdecl): Assert that we are never called when not doing
	semantic analysis.
	(pushdecl_top_level): Use push_to_top_level.
	(make_label_decl): Don't fiddle with obstacks.  Make RTL For the
	label when expanding.
	(cp_finish_decl): Only inject for-scope variables when doing
	semantic analysis.  Add comments.
	(start_handler_parms): Return the handler parm.
	(start_function): Reorganize.  Don't clear DECL_INITIAL if it is
	already set.  Reinitialize from saved function data if available.
	Don't pushlevel when not doing semantic analysis.
	(store_parm_decls): Only generate RTL when expanding.  Only
	pushdecl when doing semantic analysis.  Set
	current_eh_spec_try_block if appropriate.
	(finish_function): Simplify.  Use do_pushlevel and do_poplevel.
	Combine common code.  Don't poplevel when not doing semantic
	analysis.
	(push_cp_function_context): Don't expand functions without an
	explicit call to expand_body.
	(mark_lang_function): Make eh_spec_try_block and
	x_scope_stmt_stack.  
	* except.c (expand_end_eh_spec): Don't
	declare.
	(process_start_catch_block): Likewise.
	(push_eh_cleanup): Use finish_decl_cleanup.
	(initialize_handler_parm): New function.
	(expand_start_catch_block): Use it.
	(expand_end_catch_block): Use tree-generation functions, not
	RTL-generation functions.
	(expand_start_eh_spec): Likewise.
	(expand_end_eh_spec): Likewise.
	(expand_exception_blocks): Simplify.
	(start_anon_func): Use do_pushlevel.
	(end_anon_func): Use do_poplvel.  Call expand_body for the
	function.  
	* expr.c (do_case): Don't call define_case_label.  
	* init.c (create_temporary_var): Set DECL_CONTEXT for local
	variables.  
	* method.c (emit_thunk): Call expand_body for the
	thunk.
	(sythesize_method): Likewise.  
	* parse.y (handler_args): Give it ttype.
	(eat_saved_input): Call expand_body.
	(base_init): Use do_pushlevel.
	(pending_inline): Call expand_body.
	(handler): Adjust calls to finish_handler_parms and
	finish_handler.
	(handler_args): Don't call expand_start_catch_block.  Return the
	catch parameter.  * pt.c (tsubst_expr): Adjust HANDLER handling.
	* parse.c: Regenerated.
	* rtti.c (synthesize_tinfo_fn): Call finish_function.  
	* semantics.c (do_pushlevel): Give it external linkage.  Build
	SCOPE_STMTs.
	(do_poplevel): Likewise.
	(finish_case_label): Call define_case_label when doing semantic
	analysis.
	(finish_goto_stmt): Create RTL for labels.
	(finish_function_try_block): Set in_function_try_handler
	unconditionally.
	(finish_function_handler_sequence): Unset it.
	(finish_handler_parms): Use expand_start_catch_block even when
	building a statement-tree.
	(begin_catch_block): New function.
	(finish_handler): Move a little RTL-generation logic here.
	(finish_decl_cleanup): Allow cleanups for empty declarations.
	(finish_named_return_value): Don't pushdecl when not doing
	semantic analysis.
	(expand_stmt): Don't do semantic analysis for variable
	declarations.  Handle START_CATCH_STMT.  Call expand_label
	directly for a LABEL_STMT.  Tweak handling of GOTO_STMT.  Adjust
	HANDLERs.  Handle SCOPE_STMT, CTOR_INITIALIZER, and RETURN_INIT.
	(expand_body): Let expand_stmt handle CTOR_INITIALIZER,
	RETURN_INIT and function try blocks.

Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.307
diff -c -p -r1.307 cp-tree.h
*** cp-tree.h	1999/09/17 23:14:46	1.307
--- cp-tree.h	1999/09/17 23:33:19
*************** struct language_function
*** 623,628 ****
--- 623,631 ----
    tree x_current_class_ref;
    tree x_last_tree;
    tree x_last_expr_type;
+   tree x_eh_spec_try_block;
+   tree x_scope_stmt_stack;
+   tree x_in_charge_parm;
  
    struct rtx_def *x_last_dtor_insn;
    struct rtx_def *x_last_parm_cleanup_insn;
*************** struct language_function
*** 694,699 ****
--- 697,716 ----
     the last expression statement.  */
  
  #define last_expr_type cp_function_chain->x_last_expr_type
+ 
+ /* The TRY_BLOCK for the exception-specifiers for the current
+    function, if any.  */
+ 
+ #define current_eh_spec_try_block cp_function_chain->x_eh_spec_try_block
+ 
+ /* The stack of SCOPE_STMTs for the current function.  */
+ 
+ #define current_scope_stmt_stack cp_function_chain->x_scope_stmt_stack
+ 
+ /* The `__in_chrg' parameter for the current function.  Only used for
+    destructors.  */
+ 
+ #define current_in_charge_parm cp_function_chain->x_in_charge_parm
  
  /* Set to 0 at beginning of a function definition, set to 1 if
     a return statement that specifies a return value is seen.  */
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.457
diff -c -p -r1.457 decl.c
*** decl.c	1999/09/17 23:14:47	1.457
--- decl.c	1999/09/17 23:33:28
*************** start_function (declspecs, declarator, a
*** 13001,13006 ****
--- 13001,13009 ----
  	    = build_indirect_ref (t, NULL_PTR);
  	  cp_function_chain->x_current_class_ptr = t;
  	  
+ 	  if (DECL_DESTRUCTOR_P (decl1))
+ 	    current_in_charge_parm = TREE_CHAIN (t);
+ 
  	  resume_momentary (i);
  	  if (! hack_decl_function_context (decl1))
  	    end_temporary_allocation ();
*************** finish_function (lineno, flags)
*** 13374,13380 ****
  	  tree binfo = TYPE_BINFO (current_class_type);
  	  tree cond = integer_one_node;
  	  tree exprstmt;
- 	  tree in_charge_node = lookup_name (in_charge_identifier, 0);
  	  tree virtual_size;
  	  int ok_to_optimize_dtor = 0;
  	  int empty_dtor = get_last_insn () == last_dtor_insn;
--- 13377,13382 ----
*************** finish_function (lineno, flags)
*** 13424,13430 ****
  	    exprstmt = build_delete (current_class_type, current_class_ref, integer_zero_node,
  				     LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
  	  else
! 	    exprstmt = build_delete (current_class_type, current_class_ref, in_charge_node,
  				     LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
  
  	  /* If we did not assign to this, then `this' is non-zero at
--- 13426,13434 ----
  	    exprstmt = build_delete (current_class_type, current_class_ref, integer_zero_node,
  				     LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
  	  else
! 	    exprstmt = build_delete (current_class_type,
! 				     current_class_ref, 
! 				     current_in_charge_parm,
  				     LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
  
  	  /* If we did not assign to this, then `this' is non-zero at
*************** finish_function (lineno, flags)
*** 13451,13457 ****
  		{
  		  tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
  		  expand_start_cond (build (BIT_AND_EXPR, integer_type_node,
! 					    in_charge_node, integer_two_node), 0);
  		  while (vbases)
  		    {
  		      if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
--- 13455,13462 ----
  		{
  		  tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
  		  expand_start_cond (build (BIT_AND_EXPR, integer_type_node,
! 					    current_in_charge_parm, 
! 					    integer_two_node), 0);
  		  while (vbases)
  		    {
  		      if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
*************** finish_function (lineno, flags)
*** 13499,13505 ****
  	  if (exprstmt)
  	    {
  	      cond = build (BIT_AND_EXPR, integer_type_node,
! 			    in_charge_node, integer_one_node);
  	      expand_start_cond (cond, 0);
  	      expand_expr_stmt (exprstmt);
  	      expand_end_cond ();
--- 13504,13510 ----
  	  if (exprstmt)
  	    {
  	      cond = build (BIT_AND_EXPR, integer_type_node,
! 			    current_in_charge_parm, integer_one_node);
  	      expand_start_cond (cond, 0);
  	      expand_expr_stmt (exprstmt);
  	      expand_end_cond ();
Index: search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.122
diff -c -p -r1.122 search.c
*** search.c	1999/09/09 06:16:40	1.122
--- search.c	1999/09/17 23:33:30
*************** expand_indirect_vtbls_init (binfo, true_
*** 2784,2790 ****
  
        if (fixup_insns)
  	{
! 	  tree in_charge_node = lookup_name (in_charge_identifier, 0);
  	  if (! in_charge_node)
  	    {
  	      warning ("recoverable internal compiler error, nobody's in charge!");
--- 2784,2790 ----
  
        if (fixup_insns)
  	{
! 	  tree in_charge_node = current_in_charge_parm;
  	  if (! in_charge_node)
  	    {
  	      warning ("recoverable internal compiler error, nobody's in charge!");


More information about the Gcc-patches mailing list