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