Next: IR2 Conversion, Previous: Full Calls, Up: Calling Convention [Contents]
The unknown-values return convention consists of two parts. The first
part is that of returning a single value. The second is that of
returning a different number of values. We also changed the convention
in 0.9.10, so we should describe both the old and new versions. The
three interesting VOPs here are return-single
, return
,
and return-multiple
.
For a single-value return, we load the return value in the first
argument-passing register (A0
, or EDI
), reload the old
frame pointer, burn the stack frame, and return. The old convention
was to increment the return address by two before returning, typically
via a JMP
, which was guaranteed to screw up branch- prediction
hardware. The new convention is to return with the carry flag clear.
For a multiple-value return, we pass the first three values in the
argument-passing registers, and the remainder on the stack. ECX
contains the total number of values as a fixnum, EBX
points to
where the callee frame was, EBP
has been restored to point to
the caller frame, and the first of the values on the stack (the fourth
overall) is at [EBP-16]
. The old convention was just to jump to
the return address at this point. The newer one has us setting the
carry flag first.
The code at the call site for accepting some number of unknown- values
is fairly well boilerplated. If we are expecting zero or one values,
then we need to reset the stack pointer if we are in a multiple-value
return. In the old convention we just encoded a MOV ESP, EBX
instruction, which neatly fit in the two byte gap that was skipped by
a single-value return. In the new convention we have to explicitly
check the carry flag with a conditional jump around the MOV ESP,
EBX
instruction. When expecting more than one value, we need to
arrange to set up default values when a single-value return happens,
so we encode a jump around a stub of code which fakes up the register
use convention of a multiple-value return. Again, in the old
convention this was a two-byte unconditional jump, and in the new
convention this is a conditional jump based on the carry flag.
Next: IR2 Conversion, Previous: Full Calls, Up: Calling Convention [Contents]