A possible bug in g++ w/ -O option (SPARC)

Aki Niimura neko@my-Deja.com
Sun Dec 12 20:01:00 GMT 1999

Hi everyone,

I have been writing an application specific simulation
using C++ language. C++ allows me to write a simulation model
quite easily thanks to Object Oriented concept.

Anyway, my simulation program works fine under the following 
<Sparc / Solaris7>
 - w/o -O (no optimization)
<x86 / Solaris7>
 - w/o -O (no optimization)
 - w/  -O (optimization)

But it generates core dump under the following environment:
<Sparc / Solaris7>
 - w/  -O (optimization)

  % top <-- my simulation executable
  Segmentation Fault (core dumped)

I have been using g++ for this simulation for almost two years.
I think the version of g++ back then is 2.6.??.
And currently, I'm using g++ 2.95.2.

I have been waiting for somebody fixes this problem, but it 
seems not happening. So I tried to track down the problem by
myself. Unfortunately, I can't come up with a small sample 
program which reproduces the problem. But I think I understand
the problem.

My simulation uses longjmp and setjmp to implement $delay(n),
which controls the execution of the simulation.

   cout << "a" << endl;    // executed at T = T0
   $delay(2);              // implemented in macro
   cout << "b" << endl;    // executed at T = T0+2

The above code fragment is actually:

    static jmp_buf $env;
    static tick_t $till;
    static bool $magic;

	if($magic) longjmp($env, 1); 

    $cout << "a" << endl;     // executed at T = T0

//    $delay(2);
	if($time != $till) return; 
	$magic = false; 

    $cout << "b" << endl;     // executed at T = T0+2

What's happening when it is compiled with -O option is:

(1) Using gdb, I traced the program instruction by instruction

    sethi   %hi($magic.980), %o0
    ld  [%o0+%lo($magic.980)], %o0
    cmp %o0, 0
    be,a    .LL2411
    sethi   %hi($cout+84), %o0
    sethi   %hi($env.978), %o0
    or  %o0, %lo($env.978), %o0
    call    longjmp, 0            <<--- (a)
    mov 1, %o1
    or  %o0, %lo($cout+84), %o0
    sethi   %hi(.LLC21), %o1
    call    __ls__7ostreamPCc, 0
    or  %o1, %lo(.LLC21), %o1
    call    endl__FR7ostream, 0
    sethi   %hi($till.979), %l0   <<--- (b)
    sethi   %hi($time), %o0
    or  %o0, %lo($time), %o1
    ld  [%o0+%lo($time)], %o0
    call    .umul, 0
    ld  [%o1+4], %o1
    add %o0, 10, %o0
    st  %o0, [%l0+%lo($till.979)]
    sethi   %hi($magic.980), %o1
    mov 1, %o0
    st  %o0, [%o1+%lo($magic.980)]
    sethi   %hi($env.978), %o0
    call    setjmp, 0             <<--- (c)
    or  %o0, %lo($env.978), %o0
    sethi   %hi($time), %l1
    or  %l1, %lo($time), %l3
    ld  [%l1+%lo($time)], %o0
    call    .umul, 0
    ld  [%l3+4], %o1
    sethi   %hi($till.979), %l0
    mov %l0, %l2
    ld  [%l0+%lo($till.979)], %o1  <<<<<-- this is the location of SIGSEGV
    cmp %o0, %o1
    bne .LL2410
    sethi   %hi($magic.980), %l0
    st  %g0, [%l0+%lo($magic.980)]
    sethi   %hi($cout+84), %o0

(2) %l0 register value
When it generates SIGSEGV, the value of %l0 is 0x0 which is obviously
(3) %l0 is set at (b) but because of longjmp - setjmp branch, 
the program skips from (a) to (c) thus %l0 is not set correctly.

(4) g++ compiler does register allocation and check its validity.
However, g++ seems ignore the possible branch due to longjmp -

(5) I put an extra instruction which sets %l0 register and it works.

    sethi   %hi($till.979), %l0    <<--- extra instruction
    mov %l0, %l2
    ld  [%l0+%lo($till.979)], %o1  <<<<<-- this is the location of SIGSEGV
    cmp %o0, %o1

(6) I also put $env, $till, $magic into class member variables. 
And this case works.

    jmp_buf $env;   // no longer static
    tick_t $till;
    bool $magic;

    void exec();

I definitely want to use -O option because it brings significant
simulation speed up. I look forward to g++ future release with
this problem fixed.

Best regards,
Aki Niimura

--== Sent via Deja.com http://www.deja.com/ ==--
Share what you know. Learn what you don't.

More information about the Gcc-bugs mailing list