From a00b100c9cb8756cfa1e1d72cfd0fd270679ae60 Mon Sep 17 00:00:00 2001 From: Ronald Oussoren Date: Sat, 25 Aug 2012 11:18:48 +0200 Subject: [PATCH] Fix issue 13370: Ensure that ctypes works on Mac OS X when Python is compiled using the clang compiler --- Misc/NEWS | 3 + Modules/_ctypes/libffi_osx/x86/darwin64.S | 6 +- Modules/_ctypes/libffi_osx/x86/x86-darwin.S | 4 + Modules/_ctypes/libffi_osx/x86/x86-ffi64.c | 118 +++++++++++++++++- .../_ctypes/libffi_osx/x86/x86-ffi_darwin.c | 4 +- 5 files changed, 128 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 5365d7e1d260fc..b97655bac63d05 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -95,6 +95,9 @@ Core and Builtins Library ------- +- Issue #13370: Ensure that ctypes works on Mac OS X when Python is + compiled using the clang compiler + - Issue #15544: Fix Decimal.__float__ to work with payload-carrying NaNs. - Issue #15199: Fix JavaScript's default MIME type to application/javascript. diff --git a/Modules/_ctypes/libffi_osx/x86/darwin64.S b/Modules/_ctypes/libffi_osx/x86/darwin64.S index eba451e9d2f11a..165d4693a49ab0 100644 --- a/Modules/_ctypes/libffi_osx/x86/darwin64.S +++ b/Modules/_ctypes/libffi_osx/x86/darwin64.S @@ -45,6 +45,7 @@ _ffi_call_unix64: LUW0: movq (%rsp), %r10 /* Load return address. */ + movq %rdi, %r12 /* Save a copy of the register area. */ leaq (%rdi, %rsi), %rax /* Find local stack base. */ movq %rdx, (%rax) /* Save flags. */ movq %rcx, 8(%rax) /* Save raddr. */ @@ -52,7 +53,8 @@ LUW0: movq %r10, 24(%rax) /* Relocate return address. */ movq %rax, %rbp /* Finalize local stack frame. */ LUW1: - movq %rdi, %r10 /* Save a copy of the register area. */ + /* movq %rdi, %r10 // Save a copy of the register area. */ + movq %r12, %r10 movq %r8, %r11 /* Save a copy of the target fn. */ movl %r9d, %eax /* Set number of SSE registers. */ @@ -255,7 +257,7 @@ Lld_void: ret .align 3 Lld_int8: - movzbl -24(%rsp), %eax + movzbl -24(%rsp), %eax ret .align 3 Lld_int16: diff --git a/Modules/_ctypes/libffi_osx/x86/x86-darwin.S b/Modules/_ctypes/libffi_osx/x86/x86-darwin.S index 6c85ea61d6249d..925a84131661e9 100644 --- a/Modules/_ctypes/libffi_osx/x86/x86-darwin.S +++ b/Modules/_ctypes/libffi_osx/x86/x86-darwin.S @@ -198,8 +198,12 @@ LCFI7: je Lcls_retldouble cmpl $FFI_TYPE_SINT64, %eax je Lcls_retllong + cmpl $FFI_TYPE_UINT8, %eax + je Lcls_retstruct1 cmpl $FFI_TYPE_SINT8, %eax je Lcls_retstruct1 + cmpl $FFI_TYPE_UINT16, %eax + je Lcls_retstruct2 cmpl $FFI_TYPE_SINT16, %eax je Lcls_retstruct2 cmpl $FFI_TYPE_STRUCT, %eax diff --git a/Modules/_ctypes/libffi_osx/x86/x86-ffi64.c b/Modules/_ctypes/libffi_osx/x86/x86-ffi64.c index d4a5cc14dee7c3..06feaf23da0b83 100644 --- a/Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +++ b/Modules/_ctypes/libffi_osx/x86/x86-ffi64.c @@ -152,12 +152,42 @@ classify_argument( case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: case FFI_TYPE_POINTER: +#if 0 if (byte_offset + type->size <= 4) classes[0] = X86_64_INTEGERSI_CLASS; else classes[0] = X86_64_INTEGER_CLASS; return 1; +#else + { + int size = byte_offset + type->size; + + if (size <= 4) + { + classes[0] = X86_64_INTEGERSI_CLASS; + return 1; + } + else if (size <= 8) + { + classes[0] = X86_64_INTEGER_CLASS; + return 1; + } + else if (size <= 12) + { + classes[0] = X86_64_INTEGER_CLASS; + classes[1] = X86_64_INTEGERSI_CLASS; + return 2; + } + else if (size <= 16) + { + classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; + return 2; + } + else + FFI_ASSERT (0); + } +#endif case FFI_TYPE_FLOAT: if (byte_offset == 0) @@ -213,6 +243,21 @@ classify_argument( byte_offset += (*ptr)->size; } + if (words > 2) + { + /* When size > 16 bytes, if the first one isn't + X86_64_SSE_CLASS or any other ones aren't + X86_64_SSEUP_CLASS, everything should be passed in + memory. */ + if (classes[0] != X86_64_SSE_CLASS) + return 0; + + for (i = 1; i < words; i++) + if (classes[i] != X86_64_SSEUP_CLASS) + return 0; + } + + /* Final merger cleanup. */ for (i = 0; i < words; i++) { @@ -224,13 +269,20 @@ classify_argument( /* The X86_64_SSEUP_CLASS should be always preceded by X86_64_SSE_CLASS. */ if (classes[i] == X86_64_SSEUP_CLASS - && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS)) + && classes[i - 1] != X86_64_SSE_CLASS + && classes[i - 1] != X86_64_SSEUP_CLASS) + { + FFI_ASSERT(i != 0); classes[i] = X86_64_SSE_CLASS; + } /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ if (classes[i] == X86_64_X87UP_CLASS - && (i == 0 || classes[i - 1] != X86_64_X87_CLASS)) + && classes[i - 1] != X86_64_X87_CLASS) + { + FFI_ASSERT(i != 0); classes[i] = X86_64_SSE_CLASS; + } } return words; @@ -369,6 +421,7 @@ ffi_prep_cif_machdep( cif->flags = flags; cif->bytes = bytes; + cif->bytes = ALIGN(bytes,8); return FFI_OK; } @@ -449,7 +502,61 @@ ffi_call( case X86_64_INTEGER_CLASS: case X86_64_INTEGERSI_CLASS: reg_args->gpr[gprcount] = 0; - memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); + switch (arg_types[i]->type) { + case FFI_TYPE_SINT8: + { + int8_t shortval = *(int8_t*)a; + int64_t actval = (int64_t)shortval; + reg_args->gpr[gprcount] = actval; + /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ + break; + } + + case FFI_TYPE_SINT16: + { + int16_t shortval = *(int16_t*)a; + int64_t actval = (int64_t)shortval; + memcpy (®_args->gpr[gprcount], &actval, 8); + break; + } + + case FFI_TYPE_SINT32: + { + int32_t shortval = *(int32_t*)a; + int64_t actval = (int64_t)shortval; + memcpy (®_args->gpr[gprcount], &actval, 8); + break; + } + + case FFI_TYPE_UINT8: + { + u_int8_t shortval = *(u_int8_t*)a; + u_int64_t actval = (u_int64_t)shortval; + /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ + reg_args->gpr[gprcount] = actval; + break; + } + + case FFI_TYPE_UINT16: + { + u_int16_t shortval = *(u_int16_t*)a; + u_int64_t actval = (u_int64_t)shortval; + memcpy (®_args->gpr[gprcount], &actval, 8); + break; + } + + case FFI_TYPE_UINT32: + { + u_int32_t shortval = *(u_int32_t*)a; + u_int64_t actval = (u_int64_t)shortval; + memcpy (®_args->gpr[gprcount], &actval, 8); + break; + } + + default: + //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); + reg_args->gpr[gprcount] = *(int64_t*)a; + } gprcount++; break; @@ -505,12 +612,15 @@ ffi_prep_closure( return FFI_OK; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmissing-prototypes" int ffi_closure_unix64_inner( ffi_closure* closure, void* rvalue, RegisterArgs* reg_args, char* argp) +#pragma clang diagnostic pop { ffi_cif* cif = closure->cif; void** avalue = alloca(cif->nargs * sizeof(void *)); @@ -621,4 +731,4 @@ ffi_closure_unix64_inner( return ret; } -#endif /* __x86_64__ */ \ No newline at end of file +#endif /* __x86_64__ */ diff --git a/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c b/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c index c9a306e51dcae5..706ea0f51206dc 100644 --- a/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +++ b/Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c @@ -35,6 +35,8 @@ /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments */ +void ffi_prep_args(char *stack, extended_cif *ecif); + void ffi_prep_args(char *stack, extended_cif *ecif) { register unsigned int i; @@ -433,4 +435,4 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue) } #endif -#endif // __i386__ \ No newline at end of file +#endif // __i386__