This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
reliably telling whether a data object is in a RO, RW or ?? section
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 29 Sep 2003 19:19:33 -0300
- Subject: reliably telling whether a data object is in a RO, RW or ?? section
- Organization: GCC Team, Red Hat
decl_readonly_section() can tell whether an object is going to be
placed in a read-only section or not, as long as you can provide it
with the right value for its `reloc' argument. AFAICT, the only
function that knows how to compute reloc is private to varasm.c, and
it always emits the variable definition as a side effect.
I happen to need to be able to tell whether a label or symbol was
assigned to a read-only or read-write data section, in order to
generate more efficient code. I ended up hacking
output_addressed_constants() such that it can be used to compute reloc
without writing anything out, and arranging for
categorize_decl_for_section() to accept a negative reloc as an
indication that it should attempt to compute reloc with
output_addressed_constants(), inverting all bits in reloc if it can't
compute it.
The reason for inverting the bits is that I need a way to turn
decl_readonly_section() into a tri-state function: when it returns
true, we're sure the data is in a read-only section, but when it
returns false, I don't know whether it's in a read-write section or we
just don't know where it is. I can optimize the read-write case as
well, but it won't work if the symbol turns out to be in a read-only
section. So I call decl_readonly_section() twice, passing it ~0 and
~3, and so I can get the answer I need.
I'm not entirely happy with this solution, but it works.
Alternatively, I've considered instead adding an alternate entry point
similar to decl_readonly_section() that doesn't take a reloc value,
and that returns a tri-state value, but I wasn't even sure whether my
change to output_addressed_constants() would be acceptable, so I
thought I'd ask first.
Bootstrapped on i686-pc-linux-gnu, tested with the target I'm working
on. Ok to install? Comments?
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* varasm.c (output_addressed_constants): Add boolean argument to
control whether to actually output the constant or just compute
reloc. Adjust all callers.
(categorize_decl_for_section): If reloc is negative, compute it
from above.
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/uberbaum/gcc/varasm.c,v
retrieving revision 1.388
diff -u -p -r1.388 varasm.c
--- gcc/varasm.c 29 Sep 2003 21:29:11 -0000 1.388
+++ gcc/varasm.c 29 Sep 2003 21:59:41 -0000
@@ -154,7 +154,7 @@ static struct pool_constant *find_pool_c
static void mark_constant_pool (void);
static void mark_constants (rtx);
static int mark_constant (rtx *current_rtx, void *data);
-static int output_addressed_constants (tree);
+static int output_addressed_constants (tree, bool output);
static unsigned HOST_WIDE_INT array_size_for_constructor (tree);
static unsigned min_align (unsigned, unsigned);
static void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int);
@@ -1459,7 +1459,7 @@ assemble_variable (tree decl, int top_le
if (DECL_INITIAL (decl) == error_mark_node)
reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
else if (DECL_INITIAL (decl))
- reloc = output_addressed_constants (DECL_INITIAL (decl));
+ reloc = output_addressed_constants (DECL_INITIAL (decl), TRUE);
resolve_unique_section (decl, reloc, flag_data_sections);
/* Handle uninitialized definitions. */
@@ -2501,7 +2501,7 @@ output_constant_def_contents (rtx symbol
/* Make sure any other constants whose addresses appear in EXP
are assigned label numbers. */
- int reloc = output_addressed_constants (exp);
+ int reloc = output_addressed_constants (exp, TRUE);
/* Align the location counter as required by EXP's data type. */
int align = TYPE_ALIGN (TREE_TYPE (exp));
@@ -3334,7 +3334,7 @@ mark_constant (rtx *current_rtx, void *d
Indicate whether an ADDR_EXPR has been encountered. */
static int
-output_addressed_constants (tree exp)
+output_addressed_constants (tree exp, bool output)
{
int reloc = 0, reloc2;
tree tem;
@@ -3354,8 +3354,9 @@ output_addressed_constants (tree exp)
tem = TREE_OPERAND (tem, 0))
;
- if (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c'
- || TREE_CODE (tem) == CONSTRUCTOR)
+ if (output
+ && (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c'
+ || TREE_CODE (tem) == CONSTRUCTOR))
output_constant_def (tem, 0);
if (TREE_PUBLIC (tem))
@@ -3365,13 +3366,13 @@ output_addressed_constants (tree exp)
break;
case PLUS_EXPR:
- reloc = output_addressed_constants (TREE_OPERAND (exp, 0));
- reloc |= output_addressed_constants (TREE_OPERAND (exp, 1));
+ reloc = output_addressed_constants (TREE_OPERAND (exp, 0), output);
+ reloc |= output_addressed_constants (TREE_OPERAND (exp, 1), output);
break;
case MINUS_EXPR:
- reloc = output_addressed_constants (TREE_OPERAND (exp, 0));
- reloc2 = output_addressed_constants (TREE_OPERAND (exp, 1));
+ reloc = output_addressed_constants (TREE_OPERAND (exp, 0), output);
+ reloc2 = output_addressed_constants (TREE_OPERAND (exp, 1), output);
/* The difference of two local labels is computable at link time. */
if (reloc == 1 && reloc2 == 1)
reloc = 0;
@@ -3382,13 +3383,13 @@ output_addressed_constants (tree exp)
case NOP_EXPR:
case CONVERT_EXPR:
case NON_LVALUE_EXPR:
- reloc = output_addressed_constants (TREE_OPERAND (exp, 0));
+ reloc = output_addressed_constants (TREE_OPERAND (exp, 0), output);
break;
case CONSTRUCTOR:
for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
if (TREE_VALUE (tem) != 0)
- reloc |= output_addressed_constants (TREE_VALUE (tem));
+ reloc |= output_addressed_constants (TREE_VALUE (tem), output);
break;
@@ -4710,6 +4711,24 @@ static enum section_category
categorize_decl_for_section (tree decl, int reloc, int shlib)
{
enum section_category ret;
+
+ if (reloc < 0)
+ {
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == STRING_CST)
+ reloc = 0;
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_INITIAL (decl) == error_mark_node)
+ reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
+ else if (TREE_CODE (decl) == VAR_DECL
+ && DECL_INITIAL (decl))
+ reloc = output_addressed_constants (DECL_INITIAL (decl), FALSE);
+ else if (TREE_CODE (decl) == CONSTRUCTOR)
+ reloc = output_addressed_constants (decl, FALSE);
+ else
+ /* Invert all bits. */
+ reloc = ~reloc;
+ }
if (TREE_CODE (decl) == FUNCTION_DECL)
return SECCAT_TEXT;
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist Professional serial bug killer