This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Reinstate old usage of TREE_STATIC on ADDR_EXPR
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 24 May 2008 15:33:11 +0200
- Subject: [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;