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]

[PATCH] Reinstate old usage of TREE_STATIC on ADDR_EXPR


Hi,

In the GCC 3.x days, TREE_STATIC on ADDR_EXPR of a FUNCTION_DECL meant "do not 
build a trampoline even if the function is nested":

    case ADDR_EXPR:
      if (modifier == EXPAND_STACK_PARM)
	target = 0;
      /* Are we taking the address of a nested function?  */
      if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL
	  && decl_function_context (TREE_OPERAND (exp, 0)) != 0
	  && ! DECL_NO_STATIC_CHAIN (TREE_OPERAND (exp, 0))
	  && ! TREE_STATIC (exp))
	{
	  op0 = trampoline_address (TREE_OPERAND (exp, 0));
	  op0 = force_operand (op0, target);
	}

This usage was incompletely documented in tree.h:

   static_flag:

       TREE_STATIC in
           VAR_DECL, FUNCTION_DECL, CONSTRUCTOR, ADDR_EXPR

/* In a VAR_DECL, nonzero means allocate static storage.
   In a FUNCTION_DECL, nonzero if function has been defined.
   In a CONSTRUCTOR, nonzero means allocate static storage.

   ??? This is also used in lots of other nodes in unclear ways which
   should be cleaned up some day.  */
#define TREE_STATIC(NODE) ((NODE)->base.static_flag)

that's probably why it didn't survive the transition to the 4.x series.  But 
we need it for 'Address in Ada.

Tested on i586-suse-linux, OK for mainline?


2008-05-24  Eric Botcazou  <ebotcazou@adacore.com>

	* tree.h (TREE_STATIC): Fully document usage on ADDR_EXPR.
	* tree-nested.c (convert_tramp_reference) <ADDR_EXPR>: Do not
	build a trampoline if we don't want one.
	* varasm.c (initializer_constant_valid_p) <ADDR_EXPR>: Do not
	return zero for nested functions if we don't want a trampoline.


2008-05-24  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/trampoline1.adb: New test.
	* gnat.dg/trampoline2.adb: Likewise.


-- 
Eric Botcazou
Index: tree.h
===================================================================
--- tree.h	(revision 135795)
+++ tree.h	(working copy)
@@ -1170,6 +1170,7 @@ extern void omp_clause_range_check_faile
 /* In a VAR_DECL, nonzero means allocate static storage.
    In a FUNCTION_DECL, nonzero if function has been defined.
    In a CONSTRUCTOR, nonzero means allocate static storage.
+   In a ADDR_EXPR, nonzero means do not use a trampoline.
 
    ??? This is also used in lots of other nodes in unclear ways which
    should be cleaned up some day.  */
Index: tree-nested.c
===================================================================
--- tree-nested.c	(revision 135795)
+++ tree-nested.c	(working copy)
@@ -1645,6 +1645,10 @@ convert_tramp_reference (tree *tp, int *
       if (DECL_NO_STATIC_CHAIN (decl))
 	break;
 
+      /* If we don't want a trampoline, then don't build one.  */
+      if (TREE_STATIC (t))
+	break;
+
       /* Lookup the immediate parent of the callee, as that's where
 	 we need to insert the trampoline.  */
       for (i = info; i->context != target_context; i = i->outer)
Index: varasm.c
===================================================================
--- varasm.c	(revision 135795)
+++ varasm.c	(working copy)
@@ -4099,25 +4099,29 @@ initializer_constant_valid_p (tree value
 
     case ADDR_EXPR:
     case FDESC_EXPR:
-      value = staticp (TREE_OPERAND (value, 0));
-      if (value)
-	{
-	  /* "&(*a).f" is like unto pointer arithmetic.  If "a" turns out to
-	     be a constant, this is old-skool offsetof-like nonsense.  */
-	  if (TREE_CODE (value) == INDIRECT_REF
-	      && TREE_CONSTANT (TREE_OPERAND (value, 0)))
-	    return null_pointer_node;
-	  /* Taking the address of a nested function involves a trampoline.  */
-	  if (TREE_CODE (value) == FUNCTION_DECL
-	      && decl_function_context (value)
-	      && !DECL_NO_STATIC_CHAIN (value))
-	    return NULL_TREE;
-	  /* "&{...}" requires a temporary to hold the constructed
-	     object.  */
-	  if (TREE_CODE (value) == CONSTRUCTOR)
-	    return NULL_TREE;
-	}
-      return value;
+      {
+	tree op0 = staticp (TREE_OPERAND (value, 0));
+	if (op0)
+	  {
+	    /* "&(*a).f" is like unto pointer arithmetic.  If "a" turns out
+	       to be a constant, this is old-skool offsetof-like nonsense.  */
+	    if (TREE_CODE (op0) == INDIRECT_REF
+		&& TREE_CONSTANT (TREE_OPERAND (op0, 0)))
+	      return null_pointer_node;
+	    /* Taking the address of a nested function involves a trampoline,
+	       unless we don't need or want one.  */
+	    if (TREE_CODE (op0) == FUNCTION_DECL
+		&& decl_function_context (op0)
+		&& !DECL_NO_STATIC_CHAIN (op0)
+		&& !TREE_STATIC (value))
+	      return NULL_TREE;
+	    /* "&{...}" requires a temporary to hold the constructed
+	       object.  */
+	    if (TREE_CODE (op0) == CONSTRUCTOR)
+	      return NULL_TREE;
+	  }
+	return op0;
+      }
 
     case VIEW_CONVERT_EXPR:
     case NON_LVALUE_EXPR:
-- { dg-do compile }
-- { dg-options "-gnatws" }

with System; use System;

procedure Trampoline1 is

  A : Integer;

  function F (I : Integer) return Integer is
  begin
    return A + I;
  end F;

  CA : System.Address := F'Code_Address;

begin
  if CA = System.Null_Address then
    raise Program_Error;
  end if;
end;

-- { dg-final { scan-assembler-not "GNU-stack.*x" } }
-- { dg-do run }
-- { dg-options "-gnatws" }

with System; use System;

procedure Trampoline2 is

  A : Integer;

  type FuncPtr is access function (I : Integer) return Integer;

  function F (I : Integer) return Integer is
  begin
    return A + I;
  end F;

  P : FuncPtr := F'Access;
  CA : System.Address := F'Code_Address;
  I : Integer;

begin
  if CA = System.Null_Address then
    raise Program_Error;
  end if;

  I := P(0);
end;

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