On Fri, Mar 18, 2011 at 3:42 PM, Jakub Jelinek <ja...@redhat.com> wrote: > On Fri, Mar 18, 2011 at 03:32:45PM -0700, H.J. Lu wrote: >> On Fri, Mar 18, 2011 at 3:18 PM, Richard Henderson <r...@redhat.com> wrote: >> > On 03/18/2011 02:56 PM, H.J. Lu wrote: >> >> X86 backend uses Pmode for hardware pointer size. Changes >> >> it to 32bit for x32, which is really 64bit process, breaks many >> >> assumptions of x86 backend. push/pop/call is just the tip of >> >> the iceberg. >> > >> > Please enumerate "many assumptions". I can't think of any off >> > the top of my head. >> > >> >> I don't have a complete list. gen_push is one of them: >> >> static rtx >> gen_push (rtx arg) >> { >> struct machine_function *m = cfun->machine; >> >> if (m->fs.cfa_reg == stack_pointer_rtx) >> m->fs.cfa_offset += UNITS_PER_WORD; >> m->fs.sp_offset += UNITS_PER_WORD; >> >> return gen_rtx_SET (VOIDmode, >> gen_rtx_MEM (Pmode, >> gen_rtx_PRE_DEC (Pmode, >> stack_pointer_rtx)), >> arg); >> } >> >> You can only push/pup 64bit in hardware 64bit mode. > > That's still push/pop/call. And you can certainly use a Pmode (== SImode) > stack_pointer_rtx to describe it too, push/pop reference %rsp just > implicitly. For the MEM you would just use DImode for x32 in that case, > or for <= 32 bit pushes you could describe it as a SImode MEM with > PRE_MODIFY inside of it. >
Operations on stack and frame pointers, like push/pop, require stack and frame pointers in DImode. Even if I use word_mode in gen_push and gen_pop, I got [hjl@gnu-6 pmode-1]$ cat x.i extern void abort (void) __attribute__ ((__nothrow__)) __attribute__ ((__noreturn__)); typedef int DItype __attribute__ ((mode (DI))); typedef unsigned int UDItype __attribute__ ((mode (DI))); void foo (DItype a, DItype b) { const DItype w = (UDItype) a + (UDItype) b; if (w < a) abort (); } [hjl@gnu-6 pmode-1]$ make /export/build/gnu/gcc-x32/build-x86_64-linux/gcc/xgcc -B/export/build/gnu/gcc-x32/build-x86_64-linux/gcc/ -S -o x.s -mx32 x.i x.i: In function \u2018foo\u2019: x.i:10:1: error: unrecognizable insn: (insn/f 22 5 23 2 (set (mem:SI (pre_dec:DI (reg/f:SI 7 sp)) [0 S4 A8]) (reg/f:SI 6 bp)) x.i:6 -1 (nil)) x.i:10:1: internal compiler error: in insn_default_length, at config/i386/i386.md:600 Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. make: *** [x.s] Error 1 [hjl@gnu-6 pmode-1]$ -- H.J.