[GHC] #12433: GHCi produces incorrect results when evaluating with compiled code

GHC ghc-devs at haskell.org
Tue Jul 26 00:20:28 UTC 2016


#12433: GHCi produces incorrect results when evaluating with compiled code
-------------------------------------+-------------------------------------
        Reporter:  diatchki          |                Owner:
            Type:  bug               |               Status:  new
        Priority:  highest           |            Milestone:
       Component:  Compiler          |              Version:  8.0.1
      Resolution:                    |             Keywords:  ghci, dynamic
                                     |  linking, compiled code
Operating System:  Linux             |         Architecture:  x86_64
 Type of failure:  Incorrect result  |  (amd64)
  at runtime                         |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by rwbarton):

 The problem is in PIC code generation for jump tables (CmmSwitch). Here is
 the problematic part of `haskellLex62`:
 {{{
            call $wcclass_r2lE_info(R2) returns to c2s5, args: 8, res: 8,
 upd: 8;
        c2s5:
            _s2mn::I64 = I64[Sp + 8];
            _s2mo::I64 = R1;
            if (%MO_S_Ge_W64(R1, 12)) goto c2sB; else goto u2t1;
        u2t1:
            if (%MO_S_Lt_W64(_s2mo::I64, 0)) goto c2sB; else goto u2t2;
        u2t2:
            switch [0 .. 11] _s2mo::I64 {
                case 0, 1, 2, 3, 4 : goto u2t7;
                case 10 : goto c2sT;
                case 11 : goto c2sV;
                default: goto c2sB;
            }
        c2sV:
            Hp = Hp + 48;
            if (Hp > HpLim) goto c2sY; else goto c2sX;
        c2sY:
            HpAlloc = 48;
            R1 = _s2mo::I64;
            call stg_gc_unbx_r1(R1) returns to c2s5, args: 8, res: 8, upd:
 8;
        c2sX:
            I64[Hp - 40] = sat_s2mp_info;
            P64[Hp - 24] = P64[Sp + 24];
            I64[Hp - 16] = :_con_info;
            P64[Hp - 8] = GHC.Tuple.()_closure+1;
            P64[Hp] = Hp - 40;
            R1 = Hp - 14;
            Sp = Sp + 32;
            call (P64[Sp])(R1) args: 8, res: 0, upd: 8;
 }}}
 Observe that `c2s5` is the continuation for the call to `$wcclass_r2lE`,
 but it can also be returned to from the garbage collector after a failed
 heap check. The variable `_s2mo` is initialized at `c2s5` and then still
 live in the failed heap check block `c2sY`.

 However, the assembly generated for the switch looks like
 {{{
 _c2s5:
         movq 8(%rbp),%rax
         movq %rbx,%rcx     ; %rcx is _s2mo, set to R1 = %rbx
         cmpq $18,%rbx
         jge _c2sB
 _u2t1:
         testq %rcx,%rcx
         jl _c2sB
 _u2t2:
         leaq _n2tK(%rip),%rbx
         movslq (%rbx,%rcx,8),%rcx
         addq %rcx,%rbx
         jmp *%rbx
 ;; then a big jump table named _n2tK; in the case of 11, it jumps to _c2sV
 _c2sY:
         movq $48,904(%r13)
         movq %rcx,%rbx
         jmp *stg_gc_unbx_r1 at gotpcrel(%rip)
 _c2sV:
         addq $48,%r12
         cmpq 856(%r13),%r12
         ja _c2sY
 }}}
 In the failed heap check code at `_c2sY`, ghc thinks that `_s2mo` is still
 in `%rcx`. But actually it was clobbered by the jump table calculation at
 `_u2t2`.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12433#comment:3>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list