def write_real_errno(self, save_err): if save_err & rffi.RFFI_READSAVED_ERRNO: # Just before a call, read '*_errno' and write it into the # real 'errno'. The x0-x7 registers contain arguments to the # future call; # the x8-x10 registers contain various stuff. XXX what? # We still have x11 and up. 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) self.mc.LDR_ri(r.x11.value, r.sp.value, self.asm.saved_threadlocal_addr + self.current_sp) self.mc.LDR_ri(r.ip0.value, r.x11.value, p_errno) self.mc.LDR_ri(r.x11.value, r.x11.value, rpy_errno) self.mc.STR_ri(r.x11.value, r.ip0.value, 0) elif save_err & rffi.RFFI_ZERO_ERRNO_BEFORE: # Same, but write zero. p_errno = llerrno.get_p_errno_offset(self.asm.cpu) self.mc.LDR_ri(r.x11.value, r.sp.value, self.asm.saved_threadlocal_addr + self.current_sp) self.mc.LDR_ri(r.ip0.value, r.x11.value, p_errno) self.mc.MOVZ_r_u16(r.x11.value, 0, 0) self.mc.STR_ri(r.x11.value, r.ip0.value, 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 # 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 write_real_errno(self, save_err): if save_err & rffi.RFFI_READSAVED_ERRNO: # Just before a call, read 'rpy_errno' and write it into the # real 'errno'. The r0-r3 registers contain arguments to the # future call; the r5-r7 registers contain various stuff. # We still have r8-r12. rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu) p_errno = llerrno.get_p_errno_offset(self.asm.cpu) self.mc.LDR_ri(r.r9.value, r.sp.value, self.asm.saved_threadlocal_addr + self.current_sp) self.mc.LDR_ri(r.ip.value, r.r9.value, p_errno) self.mc.LDR_ri(r.r9.value, r.r9.value, rpy_errno) self.mc.STR_ri(r.r9.value, r.ip.value) elif save_err & rffi.RFFI_ZERO_ERRNO_BEFORE: # Same, but write zero. p_errno = llerrno.get_p_errno_offset(self.asm.cpu) self.mc.LDR_ri(r.r9.value, r.sp.value, self.asm.saved_threadlocal_addr + self.current_sp) self.mc.LDR_ri(r.ip.value, r.r9.value, p_errno) self.mc.MOV_ri(r.r9.value, 0) self.mc.STR_ri(r.r9.value, r.ip.value)
def write_real_errno(self, save_err): # r11 is saved in call_releasegil_addr_and_move_real_arguments, # thus can be used freely here! if save_err & rffi.RFFI_READSAVED_ERRNO: # Just before a call, read '*_errno' and write it into the # real 'errno'. 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) self.mc.LG(r.r11, l.addr(THREADLOCAL_ADDR_OFFSET, r.SP)) self.mc.LGF(r.SCRATCH2, l.addr(rpy_errno, r.r11)) self.mc.LG(r.r11, l.addr(p_errno, r.r11)) self.mc.STY(r.SCRATCH2, l.addr(0,r.r11)) elif save_err & rffi.RFFI_ZERO_ERRNO_BEFORE: # Same, but write zero. p_errno = llerrno.get_p_errno_offset(self.asm.cpu) self.mc.LG(r.r11, l.addr(THREADLOCAL_ADDR_OFFSET, r.SP)) self.mc.LG(r.r11, l.addr(p_errno, r.r11)) self.mc.LGHI(r.SCRATCH, l.imm(0)) self.mc.STY(r.SCRATCH, l.addr(0,r.r11))
def write_real_errno(self, save_err): # r11 is saved in call_releasegil_addr_and_move_real_arguments, # thus can be used freely here! if save_err & rffi.RFFI_READSAVED_ERRNO: # Just before a call, read '*_errno' and write it into the # real 'errno'. 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) self.mc.LG(r.r11, l.addr(THREADLOCAL_ADDR_OFFSET, r.SP)) self.mc.LGF(r.SCRATCH2, l.addr(rpy_errno, r.r11)) self.mc.LG(r.r11, l.addr(p_errno, r.r11)) self.mc.STY(r.SCRATCH2, l.addr(0, r.r11)) elif save_err & rffi.RFFI_ZERO_ERRNO_BEFORE: # Same, but write zero. p_errno = llerrno.get_p_errno_offset(self.asm.cpu) self.mc.LG(r.r11, l.addr(THREADLOCAL_ADDR_OFFSET, r.SP)) self.mc.LG(r.r11, l.addr(p_errno, r.r11)) self.mc.LGHI(r.SCRATCH, l.imm(0)) self.mc.STY(r.SCRATCH, l.addr(0, r.r11))
def read_real_errno(self, save_err): 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 'rpy_errno'. Registers r8-r12 # are unused here, and registers r2-r3 never contain anything # after the call. rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu) p_errno = llerrno.get_p_errno_offset(self.asm.cpu) self.mc.LDR_ri(r.r3.value, r.sp.value, self.asm.saved_threadlocal_addr) self.mc.LDR_ri(r.ip.value, r.r3.value, p_errno) self.mc.LDR_ri(r.ip.value, r.ip.value, 0) self.mc.STR_ri(r.ip.value, r.r3.value, rpy_errno)
def read_real_errno(self, save_err): 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'. Registers r4-r10 # never contain anything after the call. 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) self.mc.ld(r.r9.value, r.SP.value, THREADLOCAL_ADDR_OFFSET) self.mc.ld(r.r10.value, r.r9.value, p_errno) self.mc.lwz(r.r10.value, r.r10.value, 0) self.mc.stw(r.r10.value, r.r9.value, rpy_errno)
def write_real_errno(self, save_err): if save_err & rffi.RFFI_READSAVED_ERRNO: # Just before a call, read '*_errno' and write it into the # real 'errno'. A lot of registers are free here, notably # r11 and r0. 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) self.mc.ld(r.r11.value, r.SP.value, THREADLOCAL_ADDR_OFFSET + self.subtracted_to_sp) self.mc.lwz(r.r0.value, r.r11.value, rpy_errno) self.mc.ld(r.r11.value, r.r11.value, p_errno) self.mc.stw(r.r0.value, r.r11.value, 0) elif save_err & rffi.RFFI_ZERO_ERRNO_BEFORE: # Same, but write zero. p_errno = llerrno.get_p_errno_offset(self.asm.cpu) self.mc.ld(r.r11.value, r.SP.value, THREADLOCAL_ADDR_OFFSET + self.subtracted_to_sp) self.mc.ld(r.r11.value, r.r11.value, p_errno) self.mc.li(r.r0.value, 0) self.mc.stw(r.r0.value, r.r11.value, 0)
def read_real_errno(self, save_err): 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'. Registers r3-r6 # never contain anything after the call. 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) self.mc.LG(r.r3, l.addr(THREADLOCAL_ADDR_OFFSET, r.SP)) self.mc.LG(r.r4, l.addr(p_errno, r.r3)) self.mc.LGF(r.r4, l.addr(0, r.r4)) self.mc.STY(r.r4, l.addr(rpy_errno, r.r3))
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)