4221 on new codegen

Edward Z. Yang ezyang at MIT.EDU
Sat Jan 29 16:38:08 CET 2011


Test 4221 (under the ffi folder) segfaults with the new codegen turned on.

Before:

0xb7a68c78:     0x822fadc <stg_ap_v_info>
0xb7a68c74:     0xb7ab8f94
0xb7a68c70:     0xb7ab8fa4
0xb7a68c6c:     0x8134dc0 <stT_info>
0xb7a68c68:     0xb7ab8f94
0xb7a68c64:     0x822f9f4 <stg_marked_upd_frame_info>
0xb7a68c60:     0xb7ab8f48
0xb7a68c5c:     0xb7ab8f88
0xb7a68c58:     0x4063a000  # this is the counted float; this
0xb7a68c54:     0x0         # val is 157.0
0xb7a68c50:     0x804bbc0 <c1jG_info>

After:

0xb7a68c78:     0x822fadc <stg_ap_v_info>
0xb7a68c74:     0xb7ab8f94
0xb7a68c70:     0xb7ab8fa4
0xb7a68c6c:     0x8134dc0 <stT_info>
0xb7a68c68:     0xb7ab8f94
0xb7a68c64:     0x822f9f4 <stg_marked_upd_frame_info>
0xb7a68c60:     0xb7ab8f48
0xb7a68c5c:     0xb7ab8f88
0xb7a68c58:     0x4063a000
0xb7a68c54:     0x0

It then jumps c1jL_entry to which jumps to stg_gc_d1_info which segfaults on
return because 0xb7a68c54 is not a valid address.

The offending assembly:

(gdb) disas
Dump of assembler code for function c1jG_info:
   0x0804bbc0 <+0>:     fldl   0x4(%ebp)
   0x0804bbc3 <+3>:     fstp   %st(1)
   0x0804bbc5 <+5>:     fstl   0x4(%ebp)
   0x0804bbc8 <+8>:     add    $0x4,%ebp
=> 0x0804bbcb <+11>:    ffree  %st(0)
   0x0804bbcd <+13>:    ffree  %st(1)
   0x0804bbcf <+15>:    ffree  %st(2)
   0x0804bbd1 <+17>:    ffree  %st(3)
   0x0804bbd3 <+19>:    ffree  %st(4)
   0x0804bbd5 <+21>:    ffree  %st(5)
   0x0804bbd7 <+23>:    jmp    0x804bbdc <c1jL_entry>
   0x0804bbd9 <+25>:    lea    0x0(%esi),%esi

Optimized C--:

block_c1jG_entry()
        { [const 484;, const 32;]
        }
    c1jG:
        // emitReturn: Sequel: Assign
        _s1ev::F64 = F64[Sp + 4];
        ;
        F64[Sp + 4] = _s1ev::F64;
        Sp = Sp + 4;
        jump block_c1jL_entry ();
}

Regardless of whether or not it's right, this is pretty dumb code, so we
should fix the codegen not to do that.

I'm not sure what this code is /supposed/ to be doing, or what
generated it.  This bit might be correct and the FFI call leading
up to it may be wrong.  I have a prodigous amout of difficulty trying
to figure out if what's on the stack is right or not: maybe we could
have a chat about this.

Cheers,
Edward

Some possible useful raw data:

Raw C--:

 block_c1jh_entry()
         { [const 484;, const 32;]
         }
     c1jh:
         // emitReturn: Sequel: Assign
         _s1ev::F64 = F64[Sp + 4];
         _s1ev::F64 = _s1ev::F64;
         F64[Sp + 4] = _s1ev::F64;
         Sp = Sp + 4;
         jump block_c1jm_entry ();
 }

after manifest SP

{offset
  c1j0:
      _s1el::I32 = I32[Sp + 4];   // CmmAssign
      I32[Sp - 4] = _s1el::I32;   // CmmStore
      _s1ei::I32 = I32[Sp + 0];   // CmmAssign
      if (Sp - 12 < SpLim) goto u1Am; else goto u1Ao;   // CmmCondBranch
  u1Am:
      Sp = Sp + 12;   // CmmAssign
      goto c1j7;   // CmmBranch
  c1j7:
      // outOfLine here
      R1 = call_fn_blob_rk2_closure;   // CmmAssign
      Sp = Sp - 12;   // CmmAssign
      call (stg_gc_fun)(...) returns to Nothing (12) (0) with update frame 12;   // CmmCall
  u1Ao:
      Sp = Sp + 12;   // CmmAssign
      goto c1j3;   // CmmBranch
  c1j3:
      // outOfLine should follow:
      if (_s1ei::I32 & 3 != 0) goto c1j9; else goto c1j8;   // CmmCondBranch
  c1j9:
      // emitReturn: Sequel: Assign
      _s1fO::I32 = _s1ei::I32;   // CmmAssign
      I32[Sp - 20] = _s1fO::I32;   // CmmStore
      goto u1Ai;   // CmmBranch
  u1Ai:
      Sp = Sp - 20;   // CmmAssign
      goto c1jc;   // CmmBranch
  c1j8:
      // emitCall: Sequel: Assign
      R1 = _s1ei::I32;   // CmmAssign
      I32[Sp - 20] = c1iw;   // CmmStore
      Sp = Sp - 20;   // CmmAssign
      call (I32[_s1ei::I32])(...) returns to Just c1iw (4) (4) with update frame 4;   // CmmCall
  c1iw:
      _s1fO::I32 = R1;   // CmmAssign
      I32[Sp + 0] = _s1fO::I32;   // CmmStore
      Sp = Sp + 4;   // CmmAssign
      goto u1Af;   // CmmBranch
  u1Af:
      Sp = Sp - 4;   // CmmAssign
      goto c1jc;   // CmmBranch
  c1jc:
      // outOfLine should follow:
      _s1fO::I32 = I32[Sp + 0];   // CmmAssign
      _s1ep::I32 = I32[_s1fO::I32 + 3];   // CmmAssign
      I32[Sp + 0] = _s1ep::I32;   // CmmStore
      _s1el::I32 = I32[Sp + 4];   // CmmAssign
      if (_s1el::I32 & 3 != 0) goto c1jf; else goto c1je;   // CmmCondBranch
  c1jf:
      // emitReturn: Sequel: Assign
      _s1el::I32 = I32[Sp + 4];   // CmmAssign
      _s1fP::I32 = _s1el::I32;   // CmmAssign
      I32[Sp - 4] = _s1fP::I32;   // CmmStore
      goto u1Aj;   // CmmBranch
  u1Aj:
      Sp = Sp - 4;   // CmmAssign
      goto c1jj;   // CmmBranch
  c1je:
      // emitCall: Sequel: Assign
      _s1el::I32 = I32[Sp + 4];   // CmmAssign
      R1 = _s1el::I32;   // CmmAssign
      I32[Sp - 4] = c1iG;   // CmmStore
      _s1el::I32 = I32[Sp + 4];   // CmmAssign
      Sp = Sp - 4;   // CmmAssign
      call (I32[_s1el::I32])(...) returns to Just c1iG (4) (4) with update frame 4;   // CmmCall
  c1iG:
      _s1fP::I32 = R1;   // CmmAssign
      I32[Sp + 0] = _s1fP::I32;   // CmmStore
      Sp = Sp + 4;   // CmmAssign
      goto u1Ag;   // CmmBranch
  u1Ag:
      Sp = Sp - 4;   // CmmAssign
      goto c1jj;   // CmmBranch
  c1jj:
      // outOfLine should follow:
      _s1fP::I32 = I32[Sp + 0];   // CmmAssign
      _s1eq::F64 = F64[_s1fP::I32 + 3];   // CmmAssign
      I32[Sp + 0] = c1jh;   // CmmStore
      _s1ep::I32 = I32[Sp + 4];   // CmmAssign
      foreign call "ccall" arg hints:  [PtrHint,]  result hints:  [] call_fn_blob(...) returns to c1jh args: ([_s1ep::I32,
                                                                                                               _s1eq::F64]) ress: ([_s1ev::F64]) with update frame 4;   // CmmForeignCall
  c1jh:
      // emitReturn: Sequel: Assign
      _s1ev::F64 = F64[Sp + 4];   // CmmAssign
      _s1ev::F64 = _s1ev::F64;   // CmmAssign
      F64[Sp + 4] = _s1ev::F64;   // CmmStore
      Sp = Sp + 4;   // CmmAssign
      goto u1Ak;   // CmmBranch
  u1Ak:
      goto c1jm;   // CmmBranch
  c1jm:
      Hp = Hp + 12;   // CmmAssign
      if (Hp > HpLim) goto c1jn; else goto c1jl;   // CmmCondBranch
  c1jn:
      HpAlloc = 12;   // CmmAssign
      // outOfLine here
      _s1ev::F64 = F64[Sp + 0];   // CmmAssign
      F64[Sp - 4] = _s1ev::F64;   // CmmStore
      I32[Sp + 4] = c1iT;   // CmmStore
      Sp = Sp - 4;   // CmmAssign
      call stg_gc_d1(...) returns to Just c1iT (12) (12) with update frame 4;   // CmmCall
  c1iT:
      _s1ev::F64 = F64[Sp + 0];   // CmmAssign
      F64[Sp + 4] = _s1ev::F64;   // CmmStore
      Sp = Sp + 12;   // CmmAssign
      goto u1Ah;   // CmmBranch
  u1Ah:
      Sp = Sp - 8;   // CmmAssign
      goto c1jm;   // CmmBranch
  c1jl:
      // outOfLine should follow:
      // allocDynClosure
      I32[Hp - 8] = GHC.Types.D#_con_info;   // CmmStore
      _s1ev::F64 = F64[Sp + 0];   // CmmAssign
      F64[Hp - 4] = _s1ev::F64;   // CmmStore
      _c1iZ::I32 = Hp - 8;   // CmmAssign
      // emitReturn: Sequel: Return
      R1 = _c1iZ::I32 + 1;   // CmmAssign
      Sp = Sp + 16;   // CmmAssign
      call (I32[Sp + 0])(...) returns to Nothing (4) (0) with update frame 4;   // CmmCall
}

post dead assignment elimination

{offset
  c1j0:
      _s1el::I32 = I32[(old + 8)];   // CmmAssign
      I32[(slot<_s1el::I32> + 4)] = _s1el::I32;   // CmmStore
      _s1ei::I32 = I32[(old + 12)];   // CmmAssign
      if (Sp - <highSp> < SpLim) goto c1j7; else goto c1j3;   // CmmCondBranch
  c1j7:
      // outOfLine here
      R1 = call_fn_blob_rk2_closure;   // CmmAssign
      call (stg_gc_fun)(...) returns to Nothing (12) (0) with update frame 12;   // CmmCall
  c1j3:
      // outOfLine should follow:
      if (_s1ei::I32 & 3 != 0) goto c1j9; else goto c1j8;   // CmmCondBranch
  c1j9:
      // emitReturn: Sequel: Assign
      _s1fO::I32 = _s1ei::I32;   // CmmAssign
      I32[(slot<_s1fO::I32> + 4)] = _s1fO::I32;   // CmmStore
      goto u1Ai;   // CmmBranch
  u1Ai:
      goto c1jc;   // CmmBranch
  c1j8:
      // emitCall: Sequel: Assign
      R1 = _s1ei::I32;   // CmmAssign
      I32[(young<c1iw> + 4)] = c1iw;   // CmmStore
      call (I32[_s1ei::I32])(...) returns to Just c1iw (4) (4) with update frame 4;   // CmmCall
  c1iw:
      _s1fO::I32 = R1;   // CmmAssign
      I32[(slot<_s1fO::I32> + 4)] = _s1fO::I32;   // CmmStore
      goto u1Af;   // CmmBranch
  u1Af:
      goto c1jc;   // CmmBranch
  c1jc:
      // outOfLine should follow:
      _s1fO::I32 = I32[(slot<_s1fO::I32> + 4)];   // CmmAssign
      _s1ep::I32 = I32[_s1fO::I32 + 3];   // CmmAssign
      I32[(slot<_s1ep::I32> + 4)] = _s1ep::I32;   // CmmStore
      _s1el::I32 = I32[(slot<_s1el::I32> + 4)];   // CmmAssign
      if (_s1el::I32 & 3 != 0) goto c1jf; else goto c1je;   // CmmCondBranch
  c1jf:
      // emitReturn: Sequel: Assign
      _s1el::I32 = I32[(slot<_s1el::I32> + 4)];   // CmmAssign
      _s1fP::I32 = _s1el::I32;   // CmmAssign
      I32[(slot<_s1fP::I32> + 4)] = _s1fP::I32;   // CmmStore
      goto u1Aj;   // CmmBranch
  u1Aj:
      goto c1jj;   // CmmBranch
  c1je:
      // emitCall: Sequel: Assign
      _s1el::I32 = I32[(slot<_s1el::I32> + 4)];   // CmmAssign
      R1 = _s1el::I32;   // CmmAssign
      I32[(young<c1iG> + 4)] = c1iG;   // CmmStore
      _s1el::I32 = I32[(slot<_s1el::I32> + 4)];   // CmmAssign
      call (I32[_s1el::I32])(...) returns to Just c1iG (4) (4) with update frame 4;   // CmmCall
  c1iG:
      _s1fP::I32 = R1;   // CmmAssign
      I32[(slot<_s1fP::I32> + 4)] = _s1fP::I32;   // CmmStore
      goto u1Ag;   // CmmBranch
  u1Ag:
      goto c1jj;   // CmmBranch
  c1jj:
      // outOfLine should follow:
      _s1fP::I32 = I32[(slot<_s1fP::I32> + 4)];   // CmmAssign
      _s1eq::F64 = F64[_s1fP::I32 + 3];   // CmmAssign
      I32[(young<c1jh> + 4)] = c1jh;   // CmmStore
      _s1ep::I32 = I32[(slot<_s1ep::I32> + 4)];   // CmmAssign
      foreign call "ccall" arg hints:  [PtrHint,]  result hints:  [] call_fn_blob(...) returns to c1jh args: ([_s1ep::I32,
                                                                                                               _s1eq::F64]) ress: ([_s1ev::F64]) with update frame 4;   // CmmForeignCall
  c1jh:
      // emitReturn: Sequel: Assign
      _s1ev::F64 = F64[(slot<_s1ev::F64> + 8)];   // CmmAssign
      _s1ev::F64 = _s1ev::F64;   // CmmAssign
      F64[(slot<_s1ev::F64> + 8)] = _s1ev::F64;   // CmmStore
      goto u1Ak;   // CmmBranch
  u1Ak:
      goto c1jm;   // CmmBranch
  c1jm:
      Hp = Hp + 12;   // CmmAssign
      if (Hp > HpLim) goto c1jn; else goto c1jl;   // CmmCondBranch
  c1jn:
      HpAlloc = 12;   // CmmAssign
      // outOfLine here
      _s1ev::F64 = F64[(slot<_s1ev::F64> + 8)];   // CmmAssign
      F64[(young<c1iT> + 12)] = _s1ev::F64;   // CmmStore
      I32[(young<c1iT> + 4)] = c1iT;   // CmmStore
      call stg_gc_d1(...) returns to Just c1iT (12) (12) with update frame 4;   // CmmCall
  c1iT:
      _s1ev::F64 = F64[(young<c1iT> + 12)];   // CmmAssign
      F64[(slot<_s1ev::F64> + 8)] = _s1ev::F64;   // CmmStore
      goto u1Ah;   // CmmBranch
  u1Ah:
      goto c1jm;   // CmmBranch
  c1jl:
      // outOfLine should follow:
      // allocDynClosure
      I32[Hp - 8] = GHC.Types.D#_con_info;   // CmmStore
      _s1ev::F64 = F64[(slot<_s1ev::F64> + 8)];   // CmmAssign
      F64[Hp - 4] = _s1ev::F64;   // CmmStore
      _c1iZ::I32 = Hp - 8;   // CmmAssign
      // emitReturn: Sequel: Return
      R1 = _c1iZ::I32 + 1;   // CmmAssign
      call (I32[(old + 4)])(...) returns to Nothing (4) (0) with update frame 4;   // CmmCall
}



More information about the Glasgow-haskell-users mailing list