Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FIX: preserve callee-saved registers in callbacks
EBX, EDI, and ESI are callee-saved registers (for both, stdcall and cdecl), i.e. their content must be preserved across subroutine calls. For callbacks to work properly, they must adhere to the calling convention of the function they are called from. As Red/System's code generator uses callee-saved registers quite heavily, callbacks must save & restore those registers properly. Fixes issue #114.
- Loading branch information
89f2533
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Andreas, this addition should not be required as the IA32 emitter takes great care to use registers only locally for each emitted atomic action (especially to avoid registers saving as much as possible). Only EAX needs to be preserved, as it carries the last value from one atomic action to the next one.
89f2533
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took the wrong point of view, it is obvious now that your patch is required to protect caller's registers from changes operated by Red/System.
So ignore my previous comment.
89f2533
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A (cdecl/stdcall) C caller calling a Red callback can, per the calling convention, expect the values in EBX/ESI/EDI to be unchanged across the callback call. Red's IA32 emitter uses EBX/ESI heavily as scratch registers, so Red-generated code executed in the callback must take caution to preserve the values of EBX/ESI (and EDI) across the callback's lifetime.
Assume the following call hierarchy:
zmq_msg_close
), callszmq-free
), callsprint
)After 2. returns to 1., the values of EBX/ESI/EDI must be the same as they where when 1. first called into 2. However, the code generated by Red for 2. and especially 3. more often than not overwrites EBX/ESI/EDI. So the prolog/epilog generated for 1 must save/restore those registers.