def write_real_errno(self, save_err): """This occurs just before emit_raw_call(). """ mc = self.mc if handle_lasterror and (save_err & rffi.RFFI_READSAVED_LASTERROR): # must call SetLastError(). There are no registers to save # if we are on 32-bit in this case: no register contains # the arguments to the main function we want to call afterwards. # On win64, though, it's more messy. It could be better optimized # but for now we save (again) the registers containing arguments, # and restore them afterwards. from rpython.rlib.rwin32 import _SetLastError adr = llmemory.cast_ptr_to_adr(_SetLastError) SetLastError_addr = self.asm.cpu.cast_adr_to_int(adr) # if save_err & rffi.RFFI_ALT_ERRNO: lasterror = llerrno.get_alt_lasterror_offset(self.asm.cpu) else: lasterror = llerrno.get_rpy_lasterror_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi or r12, callee-saved if not WIN64: self.save_stack_position() # => edi, callee-saved mc.PUSH_m((tlofsreg.value, lasterror)) mc.CALL(imm(follow_jump(SetLastError_addr))) # restore the stack position without assuming a particular # calling convention of _SetLastError() self.mc.stack_frame_size_delta(-WORD) self.mc.MOV(esp, self.saved_stack_position_reg) else: self.win64_save_register_args() mc.MOV_rm(ecx.value, (tlofsreg.value, lasterror)) mc.CALL(imm(follow_jump(SetLastError_addr))) self.win64_restore_register_args() if save_err & rffi.RFFI_READSAVED_ERRNO: # Just before a call, read '*_errno' and write it into the # real 'errno'. Most registers are free here, including the # callee-saved ones, except 'ebx' and except the ones used to # pass the arguments on x86-64. if save_err & rffi.RFFI_ALT_ERRNO: rpy_errno = llerrno.get_alt_errno_offset(self.asm.cpu) else: rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu) p_errno = llerrno.get_p_errno_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi or r12, callee-saved if IS_X86_32: tmpreg = edx else: tmpreg = r10 # edx is used for 3rd argument mc.MOV_rm(tmpreg.value, (tlofsreg.value, p_errno)) mc.MOV32_rm(eax.value, (tlofsreg.value, rpy_errno)) mc.MOV32_mr((tmpreg.value, 0), eax.value) elif save_err & rffi.RFFI_ZERO_ERRNO_BEFORE: # Same, but write zero. p_errno = llerrno.get_p_errno_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi or r12, callee-saved mc.MOV_rm(eax.value, (tlofsreg.value, p_errno)) mc.MOV32_mi((eax.value, 0), 0)
def write_real_errno(self, save_err): """This occurs just before emit_raw_call(). """ mc = self.mc if handle_lasterror and (save_err & rffi.RFFI_READSAVED_LASTERROR): # must call SetLastError(). There are no registers to save # because we are on 32-bit in this case: no register contains # the arguments to the main function we want to call afterwards. from rpython.rlib.rwin32 import _SetLastError adr = llmemory.cast_ptr_to_adr(_SetLastError) SetLastError_addr = self.asm.cpu.cast_adr_to_int(adr) assert isinstance(self, CallBuilder32) # Windows 32-bit only # if save_err & rffi.RFFI_ALT_ERRNO: lasterror = llerrno.get_alt_lasterror_offset(self.asm.cpu) else: lasterror = llerrno.get_rpy_lasterror_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi, callee-saved self.save_stack_position() # => edi, callee-saved mc.PUSH_m((tlofsreg.value, lasterror)) mc.CALL(imm(follow_jump(SetLastError_addr))) # restore the stack position without assuming a particular # calling convention of _SetLastError() self.mc.stack_frame_size_delta(-WORD) self.mc.MOV(esp, self.saved_stack_position_reg) if save_err & rffi.RFFI_READSAVED_ERRNO: # Just before a call, read '*_errno' and write it into the # real 'errno'. Most registers are free here, including the # callee-saved ones, except 'ebx' and except the ones used to # pass the arguments on x86-64. if save_err & rffi.RFFI_ALT_ERRNO: rpy_errno = llerrno.get_alt_errno_offset(self.asm.cpu) else: rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu) p_errno = llerrno.get_p_errno_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi or r12, callee-saved if IS_X86_32: tmpreg = edx else: tmpreg = r11 # edx is used for 3rd argument mc.MOV_rm(tmpreg.value, (tlofsreg.value, p_errno)) mc.MOV32_rm(eax.value, (tlofsreg.value, rpy_errno)) mc.MOV32_mr((tmpreg.value, 0), eax.value) elif save_err & rffi.RFFI_ZERO_ERRNO_BEFORE: # Same, but write zero. p_errno = llerrno.get_p_errno_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi or r12, callee-saved mc.MOV_rm(eax.value, (tlofsreg.value, p_errno)) mc.MOV32_mi((eax.value, 0), 0)
def write_real_errno(self, save_err): """This occurs just before emit_raw_call(). """ mc = self.mc if handle_lasterror and (save_err & rffi.RFFI_READSAVED_LASTERROR): # must call SetLastError(). There are no registers to save # because we are on 32-bit in this case: no register contains # the arguments to the main function we want to call afterwards. from rpython.rlib.rwin32 import _SetLastError adr = llmemory.cast_ptr_to_adr(_SetLastError) SetLastError_addr = self.asm.cpu.cast_adr_to_int(adr) assert isinstance(self, CallBuilder32) # Windows 32-bit only # if save_err & rffi.RFFI_ALT_ERRNO: lasterror = llerrno.get_alt_lasterror_offset(self.asm.cpu) else: lasterror = llerrno.get_rpy_lasterror_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi, callee-saved self.save_stack_position() # => edi, callee-saved mc.PUSH_m((tlofsreg.value, lasterror)) mc.CALL(imm(follow_jump(SetLastError_addr))) # restore the stack position without assuming a particular # calling convention of _SetLastError() self.mc.MOV(esp, self.saved_stack_position_reg) if save_err & rffi.RFFI_READSAVED_ERRNO: # Just before a call, read '*_errno' and write it into the # real 'errno'. Most registers are free here, including the # callee-saved ones, except 'ebx' and except the ones used to # pass the arguments on x86-64. if save_err & rffi.RFFI_ALT_ERRNO: rpy_errno = llerrno.get_alt_errno_offset(self.asm.cpu) else: rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu) p_errno = llerrno.get_p_errno_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi or r12, callee-saved if IS_X86_32: tmpreg = edx else: tmpreg = r11 # edx is used for 3rd argument mc.MOV_rm(tmpreg.value, (tlofsreg.value, p_errno)) mc.MOV32_rm(eax.value, (tlofsreg.value, rpy_errno)) mc.MOV32_mr((tmpreg.value, 0), eax.value) elif save_err & rffi.RFFI_ZERO_ERRNO_BEFORE: # Same, but write zero. p_errno = llerrno.get_p_errno_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi or r12, callee-saved mc.MOV_rm(eax.value, (tlofsreg.value, p_errno)) mc.MOV32_mi((eax.value, 0), 0)
def read_real_errno(self, save_err): """This occurs after emit_raw_call() and after restore_stack_pointer(). """ mc = self.mc if save_err & rffi.RFFI_SAVE_ERRNO: # Just after a call, read the real 'errno' and save a copy of # it inside our thread-local '*_errno'. Most registers are # free here, including the callee-saved ones, except 'ebx'. # The tlofs register might have been loaded earlier and is # callee-saved, so it does not need to be reloaded. if save_err & rffi.RFFI_ALT_ERRNO: rpy_errno = llerrno.get_alt_errno_offset(self.asm.cpu) else: rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu) p_errno = llerrno.get_p_errno_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi or r12 (possibly reused) mc.MOV_rm(edi.value, (tlofsreg.value, p_errno)) mc.MOV32_rm(edi.value, (edi.value, 0)) mc.MOV32_mr((tlofsreg.value, rpy_errno), edi.value) if handle_lasterror and ( save_err & (rffi.RFFI_SAVE_LASTERROR | rffi.RFFI_SAVE_WSALASTERROR)): if save_err & rffi.RFFI_SAVE_LASTERROR: from rpython.rlib.rwin32 import _GetLastError adr = llmemory.cast_ptr_to_adr(_GetLastError) else: from rpython.rlib._rsocket_rffi import _WSAGetLastError adr = llmemory.cast_ptr_to_adr(_WSAGetLastError) GetLastError_addr = self.asm.cpu.cast_adr_to_int(adr) assert isinstance(self, CallBuilder32) # Windows 32-bit only # if save_err & rffi.RFFI_ALT_ERRNO: lasterror = llerrno.get_alt_lasterror_offset(self.asm.cpu) else: lasterror = llerrno.get_rpy_lasterror_offset(self.asm.cpu) self.save_result_value(save_edx=True) # save eax/edx/xmm0 self.result_value_saved_early = True mc.CALL(imm(follow_jump(GetLastError_addr))) # tlofsreg = self.get_tlofs_reg() # => esi (possibly reused) mc.MOV32_mr((tlofsreg.value, lasterror), eax.value)
def read_real_errno(self, save_err): """This occurs after emit_raw_call() and after restore_stack_pointer(). """ mc = self.mc if save_err & rffi.RFFI_SAVE_ERRNO: # Just after a call, read the real 'errno' and save a copy of # it inside our thread-local '*_errno'. Most registers are # free here, including the callee-saved ones, except 'ebx'. # The tlofs register might have been loaded earlier and is # callee-saved, so it does not need to be reloaded. if save_err & rffi.RFFI_ALT_ERRNO: rpy_errno = llerrno.get_alt_errno_offset(self.asm.cpu) else: rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu) p_errno = llerrno.get_p_errno_offset(self.asm.cpu) tlofsreg = self.get_tlofs_reg() # => esi or r12 (possibly reused) mc.MOV_rm(ecx.value, (tlofsreg.value, p_errno)) mc.MOV32_rm(ecx.value, (ecx.value, 0)) mc.MOV32_mr((tlofsreg.value, rpy_errno), ecx.value) if handle_lasterror and (save_err & (rffi.RFFI_SAVE_LASTERROR | rffi.RFFI_SAVE_WSALASTERROR)): if save_err & rffi.RFFI_SAVE_LASTERROR: from rpython.rlib.rwin32 import _GetLastError adr = llmemory.cast_ptr_to_adr(_GetLastError) else: from rpython.rlib._rsocket_rffi import _WSAGetLastError adr = llmemory.cast_ptr_to_adr(_WSAGetLastError) GetLastError_addr = self.asm.cpu.cast_adr_to_int(adr) assert isinstance(self, CallBuilder32) # Windows 32-bit only # if save_err & rffi.RFFI_ALT_ERRNO: lasterror = llerrno.get_alt_lasterror_offset(self.asm.cpu) else: lasterror = llerrno.get_rpy_lasterror_offset(self.asm.cpu) self.save_result_value(save_edx=True) # save eax/edx/xmm0 self.result_value_saved_early = True mc.CALL(imm(follow_jump(GetLastError_addr))) # tlofsreg = self.get_tlofs_reg() # => esi (possibly reused) mc.MOV32_mr((tlofsreg.value, lasterror), eax.value)