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]

expanding addrs for initializers


Re-visiting this.  If we have source like this:

extern void func();

long long fptr = (long long)&func;

and pointers are smaller than "long long" (example: i386 or m32c), the
compiler will first convert the pointer to an int, then convert the
int to a long long.  This results in output like this:

	.long	func
	.long	0

Which isn't useful if the address happens to be bigger than int
(example: reset vectors on m32c), and is just plain wrong on big
endian machines.

I've figured out a few changes that let this work in a useful way, but
some of the assumptions may not be globally valid, so I'm asking for
confirmation here.

First off, in initializer_constant_valid_p, we don't assume there's
only one conversion.  If we see a NOP_EXPR or CONVERT_EXPR, we peel of
however many there are.  We only really care about the inner and outer
types at this point, as no more compile-time conversions happen after
this point (true?).

Second, in output_constant, we add an assumption that constants which
are the address of some DECL can be extended by the assembler in a
meaningful way.  Certainly, gcc isn't doing a good job of extending
them, and if such an extension isn't possible, it's already too late
for gcc to do it at compile time, might as well let the assembler or
linker emit the diagnostic (gcc's current diagnostic is misleading).

Lastly, m32c knows how to widen pointers in the assembler.  (ok, I
happen to know this assumption is valid ;)

Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.525
diff -p -U3 -r1.525 varasm.c
--- varasm.c	17 Aug 2005 19:25:12 -0000	1.525
+++ varasm.c	19 Aug 2005 03:34:58 -0000
@@ -3652,9 +3652,13 @@ initializer_constant_valid_p (tree value
 	tree src_type;
 	tree dest_type;
 
-	src = TREE_OPERAND (value, 0);
-	src_type = TREE_TYPE (src);
 	dest_type = TREE_TYPE (value);
+	src = value;
+	do {
+	  src = TREE_OPERAND (src, 0);
+	} while (TREE_CODE (src) == CONVERT_EXPR
+		 || TREE_CODE (src) == NOP_EXPR);
+	src_type = TREE_TYPE (src);
 
 	/* Allow conversions between pointer types, floating-point
 	   types, and offset types.  */
@@ -3857,6 +3861,13 @@ output_constant (tree exp, unsigned HOST
   code = TREE_CODE (TREE_TYPE (exp));
   thissize = int_size_in_bytes (TREE_TYPE (exp));
 
+  /* Assume addresses of decls can be extended to larger types by the
+     assembler/linker, or at least, that they'll fail otherwise.  */
+  if (TREE_CODE (exp) == ADDR_EXPR
+      && DECL_P (TREE_OPERAND (exp, 0))
+      && thissize < size)
+    thissize = size;
+
   /* Allow a constructor with no elements for any data type.
      This means to fill the space with zeros.  */
   if (TREE_CODE (exp) == CONSTRUCTOR
Index: config/m32c/m32c.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m32c/m32c.c,v
retrieving revision 1.3
diff -p -U3 -r1.3 m32c.c
--- config/m32c/m32c.c	16 Aug 2005 00:31:39 -0000	1.3
+++ config/m32c/m32c.c	19 Aug 2005 03:34:59 -0000
@@ -1972,6 +1972,15 @@ m32c_asm_integer (rtx x, unsigned int si
       output_addr_const (asm_out_file, x);
       fputc ('\n', asm_out_file);
       return true;
+    case 4:
+      if (GET_CODE (x) == SYMBOL_REF)
+	{
+	  fprintf (asm_out_file, "\t.long\t");
+	  output_addr_const (asm_out_file, x);
+	  fputc ('\n', asm_out_file);
+	  return true;
+	}
+      break;
     }
   return default_assemble_integer (x, size, aligned_p);
 }


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