All credits for finding the root of the evil go to Andrew Hutchinson His original e-mail:
There is a bug! Backend (avr part) creates special "pm()" annotation by looking at RTL. This is done in avr.c by this function: static bool avr_assemble_integer (rtx x, unsigned int size, int aligned_p) { debug_rtx(x); /*ADDED TO DEBUG*/ fprintf(stderr,"size=%d align=%d\n\n",size,aligned_p); /*ADDED TO DEBUG*/ if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x)) || GET_CODE (x) == LABEL_REF)) { fputs ("\t.word\tpm(", asm_out_file); output_addr_const (asm_out_file, x); fputs (")\n", asm_out_file); return true; } return default_assemble_integer (x, size, aligned_p); } (I added 2 lines to debug it) You will see it looks symbol_ref or label_ref - otherwise it does not use pm. So I ran it with following testcase to see what argument get sent: //Dummy func int table[]= {1,2}; char ctable[]= {3,4}; void foo(void) {} //Table with address manipulation void (* const pFuncTable[]) (void) = { foo + 0, (foo + 1), foo +2 }; ....and we get the following: (const_int 1 [0x1]) size=2 align=1 (const_int 2 [0x2]) size=2 align=1 (const_int 3 [0x3]) size=1 align=1 (const_int 4 [0x4]) size=1 align=1 (symbol_ref:HI ("foo") [flags 0x3] <function_decl 0x7fdcf030 foo>) size=2 align=1 (const:HI (plus:HI (symbol_ref:HI ("foo") [flags 0x3] <function_decl 0x7fdcf030 foo>) (const_int 1 [0x1]))) size=2 align=1 (const:HI (plus:HI (symbol_ref:HI ("foo") [flags 0x3] <function_decl 0x7fdcf030 foo>) (const_int 2 [0x2]))) size=2 align=1 You will see last two cases are an expression with outer code as const:HI so it will not match, it does not add pm(). -- Summary: Incomplete check in RTL for "pm()" annotation Product: gcc Version: 4.2.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: wvangulik at xs4all dot nl GCC target triplet: avr-*-* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35013