This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch Fix PR35013, PR27192
- From: Andrew Hutchinson <andrewhutchinson at cox dot net>
- To: Anatoly Sokolov <aesok at post dot ru>, gcc-patches at gcc dot gnu dot org, "Weddington, Eric" <eweddington at cso dot atmel dot com>
- Date: Sat, 16 Feb 2008 20:36:39 -0500
- Subject: Patch Fix PR35013, PR27192
- References: <47A3F532.4020805@cox.net> <47B73DCC.7090203@cox.net>
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);