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 Fix PR35013, PR27192


The attached patch fixes

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35013
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27192

Both of these problems occur because the avr backend fails to recognize function pointer expressions - such as foo + 2

As a result, these references are treated as byte addresses by assembler, rather word addresses using the pm() directive. The patch changes the operand check to one that finds the function reference buried in the expression. (This is similar to code used on the SPARC-gcc)

This patch has been tested using gcc version 4.3.0 20080121 (experimental) with HEAD versions of the AVR files. No regressions occurred running gcc.c-torture/execute testsuite with simulator and the PR test cases generate the correct code.

Please comit.

2008-02-16 Andy Hutchinson <hutchinsonandy@aim.com>

PR avr/35013 avr/27192

* avr.h (text_segment_operand): New function to check program memory address.

* avr.c (text_segment_operand): New function to check program memory address.
(print_operand_address, avr_assemble_integer): Add new check.






Index: avr-protos.h
===================================================================
--- avr-protos.h	(revision 132369)
+++ avr-protos.h	(working copy)
@@ -111,6 +111,7 @@
 extern int _reg_unused_after (rtx insn, rtx reg);
 extern int avr_jump_mode (rtx x, rtx insn);
 extern int byte_immediate_operand (rtx op, enum machine_mode mode);
+extern int text_segment_operand (rtx op, enum machine_mode mode);
 extern int test_hard_reg_class (enum reg_class class, rtx x);
 extern int jump_over_one_insn_p (rtx insn, rtx dest);
 
Index: avr.c
===================================================================
--- avr.c	(revision 132366)
+++ avr.c	(working copy)
@@ -1116,8 +1116,7 @@
 
     default:
       if (CONSTANT_ADDRESS_P (addr)
-	  && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
-	      || GET_CODE (addr) == LABEL_REF))
+	  && text_segment_operand (addr, VOIDmode))
 	{
 	  fprintf (file, "pm(");
 	  output_addr_const (file,addr);
@@ -1428,6 +1427,26 @@
           && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
 }
 
+/* Return true if OP is a program memory reference.*/
+int 
+text_segment_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  switch (GET_CODE (op))
+    {
+    case LABEL_REF :
+      return true;
+    case SYMBOL_REF :
+      return SYMBOL_REF_FUNCTION_P (op);
+    case PLUS :
+      /* Assume canonical format of symbol + constant.
+	 Fall through.  */
+    case CONST :
+      return text_segment_operand (XEXP (op, 0), VOIDmode);
+    default :
+      return false;
+    }
+}
+
 /* Output all insn addresses and their sizes into the assembly language
    output file.  This is helpful for debugging whether the length attributes
    in the md file are correct.
@@ -4465,8 +4484,7 @@
 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
 {
   if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
-      && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
-	  || GET_CODE (x) == LABEL_REF))
+      && text_segment_operand (x, VOIDmode) )
     {
       fputs ("\t.word\tpm(", asm_out_file);
       output_addr_const (asm_out_file, x);

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