This is the mail archive of the gcc-bugs@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]

target/6912: x86_64 switch code generation problem with -fPIC


>Number:         6912
>Category:       target
>Synopsis:       x86_64 switch code generation problem with -fPIC
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 02 17:46:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Frank van der Linden
>Release:        3.2 20020602 (experimental)
>Organization:
>Environment:
System: NetBSD k2 1.5ZC NetBSD 1.5ZC (K2) #0: Wed May 1 02:01:29 CEST 2002 fvdl@k2:/work/trees/empee/sys/arch/i386/compile/K2 i386

host: i386-unknown-netbsdelf1.5ZC
build: i386-unknown-netbsdelf1.5ZC
target: x86_64--netbsd
configured with: /work/trees/toolchain/gcc/configure --target=x86_64--netbsd --disable-shared --with-gnu-ld --with-gas --enable-languages=c c++ --prefix=/work/fvdl/toolchain
>Description:
	gcc 3.1 and up generates bad code for switch jump tables when
	using the -fPIC flag. The problem is that the generated jump
	table contains 32-bit signed values for the relative offset to
	jump to. This is fine, for small mode. However, when they are
	loaded into a register for the computation of the jump destination,
	they are not sign-extended.

	This means that for negative offsets, the computed address will
	be wrong and way out of range (i.e. -10 will be added as
	0x00000000fffffff6).

	This bug may have gone unnoticed for a while, because mostly,
	the jump table resides in memory *before* the code it points
	to (.rodata comes before .text, or the jumptable resides in
	.text before the code), so the offsets will be positive.
	But, there are cases in which this is not the case (like in the
	NetBSD dynamic linker). And a compiler should not make assumptions
	about the order of sections anyway.

	small example program:


/*
 * Simple testcode to tickle a codegen bug with -fPIC and switch
 * statements on x86_64.
 *
 * The code inside the cases is irrelevant, it's just there as
 * filler to avoid stuff being optimised away.
 */

extern int a, b, c, d, e;

int
foo(void)
{
	switch (a) {
	case 1:
		a = b * c;
		a--;
		break;
	case 2:
		a = d * e;
		c = d / b;
		break;
	case 3:
		a = c / d;
		b = d * d;
		c--;
		break;
	case 4:
		a = d * d;
		b = c * c;
		break;
	case 5:
		c++;
		d++;
		c = b * b;
		break;
	}
	return 0;
}

======
	gcc 3.1 and up generates (with -O -fPIC)
======

        .file   "c.c"
        .text
        .align 2
.globl foo
        .type   foo,@function
foo:
.LFB1:
        pushq   %rbx
.LCFI0:
        movq    a@GOTPCREL(%rip), %rax
        cmpl    $5, (%rax)
        ja      .L2
        mov     (%rax), %eax
        leaq    .L8(%rip), %rdx
        mov     (%rdx,%rax,4), %eax		<==== no sign-extension
        addq    %rdx, %rax			<====
        jmp     *%rax
        .section        .rodata
        .align 4
        .align 4
.L8:
        .long   .L2-.L8
        .long   .L3-.L8
        .long   .L4-.L8
        .long   .L5-.L8
        .long   .L6-.L8
        .long   .L7-.L8
        .text
.L3:
[... rest of code deleted]
======
	An older gcc (gcc version 3.1 20010430 (experimental))
	generates (with -O -fPIC) correct code:
======
        .file   "c.c"
        .text
        .align 4
.globl foo
        .type   foo,@function
foo:
.LFB1:
        pushq   %rbx
.LCFI0:
        movq    a@GOTPCREL(%RIP), %rax
        movl    (%rax), %eax
        decl    %eax
        cmpl    $4, %eax
        ja      .L2
        mov     %eax, %eax
        leaq    .L8(%rip), %rdx
        movslq  (%rdx,%rax,4),%rax	<=== correct sign extension
        leaq    (%rax,%rdx), %rax
        jmp     *%rax
        .section        .rodata
        .align 16
        .align 4
.L8:
        .long .L3-.+4+(.-.L8)
        .long .L4-.+4+(.-.L8)
        .long .L5-.+4+(.-.L8)
        .long .L6-.+4+(.-.L8)
        .long .L7-.+4+(.-.L8)
        .text
        .align 4
.L3:
[... rest of output deleted]

>How-To-Repeat:
	Compile with a largish switch with -fPIC, and link the
	resulting program in such a way that the jumptable comes
	after the code it points to.
>Fix:
	Unknown to me, should be simple.
>Release-Note:
>Audit-Trail:
>Unformatted:


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