I've been working with a fork of C-evo for a while now.
Its been very stable for at least a year.
However, recently a game locked up in a (wide) cpu loop.
The broken code is in the shared library, built with FPC 3.2.2,
its nothing to do with Lazarus, except that Lazarus code calls the library.

I compiled a debug version to investigate and the problem went away.
It seemed likely that the issue was optimisations, and sure enough, O1 is fine 
but O2 broken.
Trying the optimisations individually I found that PEEPHOLE + REGVAR alone 
caused the problem.
The code actually works fine at O4, providing either PEEPHOLE or REGVAR is 
disabled.

This is with x64 on Debian Linux, but the problem is also on Arch Linux, so 
nothing specific with the Debian build.
Other options like Ct, Ci, Co, CR, Cr make no difference.
I tried FPC versions back to 3.0.4, and the issue is still there, so its not a 
recent regression.

Its unlikely that I can reproduce this problem with a small program,
but compiling the offending code to assembler, the problem seems rather obvious.

Its in a method function,

[500]  function TBarbarina.DoAttack(uix, AttackLoc: integer): boolean;

It seems that parameter AttackLoc is corrupted halfway through the routine, 
just after being used in an assignment,

[587]      TestLoc := AttackLoc;

If the parameter AttackLoc is used immediately after this statement, for 
example in a Writeln, its OK.
But if not, its corrupted when used later.

The problem looks like the register allocator,
as at line 587 the assembler comment says that AttackLoc is now in r13d,
but r13d has not been initialised. AttackLoc was in 83288(%rsp) up to this 
point.

Here is an extract of the assembler showing statements where AttackLoc is used
(to around the point where the problem occurs)

.....

# Var uix located in register eax
    movl    %edx,%eax
    movq    %rax,83288(%rsp)
# Var AttackLoc located in register eax
# [503] var

.....

# [514] IsBombardment := AttackLoc = maNextCity;
    movl    83288(%rsp),%eax
    cmpl    $-1,%eax

.....

# [531] if (TestTime >= $800) or (AttackLoc = maNextCity) and (TestTime > $800 
- 100) then
    cmpl    $2048,%edx
    jge    .Lj281
    movl    83288(%rsp),%eax
    cmpl    $-1,%eax
    jne    .Lj284
    cmpl    $1948,%edx
    jg    .Lj281
.Lj284:

.....

# [548] AttackLoc := NextLoc;
    movl    %ebx,%eax
    movq    %rax,83288(%rsp)
.Lj298:
.Lj294:
# [550] if (NextLoc = AttackLoc) and ((MyModel[mix].Domain <> dSea) or
    movl    83288(%rsp),%eax
    cmpl    %ebx,%eax
    jne    .Lj301
    movq    83272(%rsp),%rax
    movq    48(%rax),%rcx
    movq    83280(%rsp),%rax
    movzwl    14(%rax),%edx
    imulq    $68,%rdx,%rax
    cmpb    $1,17(%rcx,%rax)
    jne    .Lj302

.....

# [587] TestLoc := AttackLoc;
    movl    83288(%rsp),%eax
# Var AttackLoc located in register r13d        ****************** !!!!
    movl    %eax,24(%rsp)

.....

# [605] until (NextLoc = AttackLoc) or (MoveResult and rExecuted = 0) or
    cmpl    %r12d,%r13d
    je    .Lj332
    movl    %ebx,%eax
    andl    $1073741824,%eax
    je    .Lj332

.....

# [607] Result := (NextLoc = AttackLoc) and (MoveResult and rExecuted <> 0);
    cmpl    %r12d,%r13d
    jne    .Lj338
    movl    %ebx,%eax
    andl    $1073741824,%eax
    je    .Lj338
    movb    $1,83240(%rsp)
    jmp    .Lj340
.Lj338:
    movb    $0,83240(%rsp)

.....


There are four source files, around 250k, to compile this library. I can supply 
them if anyone wants to investigate.
Is this sufficient for a bug report?  Does anyone know of any existing bugs 
like this? Maybe already fixed?

I'll attach the source and assembler for this routine in a follow up mail.


Cheers,
Peter






_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to