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]

reliably telling whether a data object is in a RO, RW or ?? section


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

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