Skip to content

Instantly share code, notes, and snippets.

@osa1
Created May 27, 2016 10:28
Show Gist options
  • Select an option

  • Save osa1/6961501a76a4fd44538a1720b224b820 to your computer and use it in GitHub Desktop.

Select an option

Save osa1/6961501a76a4fd44538a1720b224b820 to your computer and use it in GitHub Desktop.
[section ""data" . $wsum_closure" {
$wsum_closure:
const $wsum_info;
},
$wsum_entry() // [R2]
{ info_tbl: [(cMo,
label: block_cMo_info
rep:StackRep []),
(cMv,
label: $wsum_info
rep:HeapRep static { Fun {arity: 1 fun_type: ArgSpec 5} }),
(cMD,
label: block_cMD_info
rep:StackRep [False]),
(cMI,
label: block_cMI_info
rep:StackRep [True])]
stack_info: arg_space: 8 updfr_space: Just 8
}
{offset
// make sure we have enough stack space
cMv:
if ((Sp + -16) < SpLim) goto cMw; else goto cMx;
// not enough stack space, run GC
cMw:
R2 = R2;
R1 = $wsum_closure;
call (stg_gc_fun)(R2, R1) args: 8, res: 0, upd: 8;
// have enough stack space
cMx:
I64[Sp - 8] = cMo; // cMo is pushed to the stack for cMp
R1 = R2; // what is R2? (probably the argument)
Sp = Sp - 8; // why is stack pointer not adjusted right after the push?
if (R1 & 7 != 0) goto cMo; else goto cMp;
// evaluate the argument, stack has cMo on top
cMp:
call (I64[R1])(R1) returns to cMo, args: 8, res: 8, upd: 8;
// the argument is evaluated at this point, so this must be a tag check
// the problem though, we pushed cMo to the stack even if (R1 & 7 != 0).
// isn't that a redundant operation? why not push cMo to the stack in
// cMp?
cMo:
if (R1 & 7 != 1) goto cMt; else goto cMs;
cMt: // it's a Cons
I64[Sp - 8] = cMD; // push cMD eagerly, just like how we pushed cMo
// eagerly
_sKX::P64 = P64[R1 + 14]; // tail, 14 instead of 16 because we know (R1 & 7 == 2)
R1 = P64[R1 + 6]; // head, 6 instead of 8 because we know (R1 & 7 == 2)
P64[Sp] = _sKX::P64; // push tail to the stack
Sp = Sp - 8; // first push overwrite cMo, so only after second push
// we decrement sp
if (R1 & 7 != 0) goto cMD; else goto cME; // check whether int is evaluated
// (of course it is! it has a bang in its definition!)
cME: // evaluate the !Int
call (I64[R1])(R1) returns to cMD, args: 8, res: 8, upd: 8;
cMD:
// at this point tail is on the stack, even if we didn't run cME!
I64[Sp] = cMI;
R2 = P64[Sp + 8]; // load tail to R2
I64[Sp + 8] = I64[R1 + 7]; // R1 has Int. because of pointer tagging,
// we know that the last bit should be 1,
// so we add 7 instead of 8 to get the
// first field
// recursively sum the tail
call $wsum_info(R2) returns to cMI, args: 8, res: 8, upd: 8;
cMI:
R1 = I64[Sp + 8] + R1; // sum return value + our int
Sp = Sp + 16; // restore stack, used two slots one for saving our
// int, one for
call (P64[Sp])(R1) args: 8, res: 0, upd: 8;
cMs: // it's a Nil
R1 = 0; // put return value to its reg
Sp = Sp + 8; // restore stack pointer
call (P64[Sp])(R1) args: 8, res: 0, upd: 8; // jump to the continuation
}
}]
$wsum =
\r srt:SRT:[] [w_sKU]
case w_sKU of _ {
Nil -> 0#;
Cons x_sKW xs_sKX ->
case x_sKW of _ {
I# x1_sKZ ->
case $wsum xs_sKX of ww_sL0 { __DEFAULT -> +# [x1_sKZ ww_sL0]; };
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment