From 56a9d7e3daff45f5fef206ea42398b4a0505fb47 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Tue, 15 Mar 2011 12:20:02 -0400 Subject: #11554: reactivate test_email_codecs, and make it pass. The fix is to charset.py, which was not doing the encoding to the correct output character set when doing a body_encode for either the shift-jis or euc-jp charsets. There's also a fix for handling a bytes input in encoders.py. Patch by Michael Henry, comment changes by me. --- Lib/email/charset.py | 9 ++++++-- Lib/email/encoders.py | 9 +++++--- Lib/email/test/test_email.py | 4 ++-- Lib/email/test/test_email_codecs.py | 46 +++++++++++++++++++++++++------------ Lib/test/test_email.py | 2 ++ Misc/ACKS | 1 + Misc/NEWS | 5 ++++ 7 files changed, 54 insertions(+), 22 deletions(-) diff --git a/Lib/email/charset.py b/Lib/email/charset.py index 24d5545..f22be2c 100644 --- a/Lib/email/charset.py +++ b/Lib/email/charset.py @@ -263,7 +263,7 @@ class Charset: Returns "quoted-printable" if self.body_encoding is QP. Returns "base64" if self.body_encoding is BASE64. - Returns "7bit" otherwise. + Returns conversion function otherwise. """ assert self.body_encoding != SHORTEST if self.body_encoding == QP: @@ -381,7 +381,10 @@ class Charset: """Body-encode a string by converting it first to bytes. The type of encoding (base64 or quoted-printable) will be based on - self.body_encoding. + self.body_encoding. If body_encoding is None, we assume the + output charset is a 7bit encoding, so re-encoding the decoded + string using the ascii codec produces the correct string version + of the content. """ # 7bit/8bit encodings return the string unchanged (module conversions) if self.body_encoding is BASE64: @@ -391,4 +394,6 @@ class Charset: elif self.body_encoding is QP: return email.quoprimime.body_encode(string) else: + if isinstance(string, str): + string = string.encode(self.output_charset).decode('ascii') return string diff --git a/Lib/email/encoders.py b/Lib/email/encoders.py index 0ea441d..c66f4cc 100644 --- a/Lib/email/encoders.py +++ b/Lib/email/encoders.py @@ -54,10 +54,13 @@ def encode_7or8bit(msg): # There's no payload. For backwards compatibility we use 7bit msg['Content-Transfer-Encoding'] = '7bit' return - # We play a trick to make this go fast. If encoding to ASCII succeeds, we - # know the data must be 7bit, otherwise treat it as 8bit. + # We play a trick to make this go fast. If encoding/decode to ASCII + # succeeds, we know the data must be 7bit, otherwise treat it as 8bit. try: - orig.encode('ascii') + if isinstance(orig, str): + orig.encode('ascii') + else: + orig.decode('ascii') except UnicodeError: # iso-2022-* is non-ASCII but still 7-bit charset = msg.get_charset() diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py index f8bdaa2..a6ea1d1 100644 --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -3365,9 +3365,9 @@ class TestCharset(unittest.TestCase): # built-in encodings where the header encoding is QP but the body # encoding is not. from email import charset as CharsetModule - CharsetModule.add_charset('fake', CharsetModule.QP, None) + CharsetModule.add_charset('fake', CharsetModule.QP, None, 'utf-8') c = Charset('fake') - eq('hello w\xf6rld', c.body_encode('hello w\xf6rld')) + eq('hello world', c.body_encode('hello world')) def test_unicode_charset_name(self): charset = Charset('us-ascii') diff --git a/Lib/email/test/test_email_codecs.py b/Lib/email/test/test_email_codecs.py index acc19c3..ca85f57 100644 --- a/Lib/email/test/test_email_codecs.py +++ b/Lib/email/test/test_email_codecs.py @@ -13,7 +13,7 @@ from email.message import Message # We're compatible with Python 2.3, but it doesn't have the built-in Asian # codecs, so we have to skip all these tests. try: - str('foo', 'euc-jp') + str(b'foo', 'euc-jp') except LookupError: raise unittest.SkipTest @@ -22,11 +22,14 @@ except LookupError: class TestEmailAsianCodecs(TestEmailBase): def test_japanese_codecs(self): eq = self.ndiffAssertEqual - j = Charset("euc-jp") - g = Charset("iso-8859-1") + jcode = "euc-jp" + gcode = "iso-8859-1" + j = Charset(jcode) + g = Charset(gcode) h = Header("Hello World!") - jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' - ghello = 'Gr\xfc\xdf Gott!' + jhello = str(b'\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc' + b'\xa5\xeb\xa5\xc9\xa1\xaa', jcode) + ghello = str(b'Gr\xfc\xdf Gott!', gcode) h.append(jhello, j) h.append(ghello, g) # BAW: This used to -- and maybe should -- fold the two iso-8859-1 @@ -36,13 +39,17 @@ class TestEmailAsianCodecs(TestEmailBase): # encoded word. eq(h.encode(), """\ Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?= - =?iso-8859-1?q?Gr=FC=DF?= =?iso-8859-1?q?_Gott!?=""") + =?iso-8859-1?q?Gr=FC=DF_Gott!?=""") eq(decode_header(h.encode()), - [('Hello World!', None), - ('\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'), - ('Gr\xfc\xdf Gott!', 'iso-8859-1')]) - int = 'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9' - h = Header(int, j, header_name="Subject") + [(b'Hello World!', None), + (b'\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'), + (b'Gr\xfc\xdf Gott!', gcode)]) + subject_bytes = (b'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5' + b'\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2' + b'\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3' + b'\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9') + subject = str(subject_bytes, jcode) + h = Header(subject, j, header_name="Subject") # test a very long header enc = h.encode() # TK: splitting point may differ by codec design and/or Header encoding @@ -50,15 +57,24 @@ Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?= =?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?= =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""") # TK: full decode comparison - eq(h.__unicode__().encode('euc-jp'), int) + eq(str(h).encode(jcode), subject_bytes) + + def test_payload_encoding_utf8(self): + jhello = str(b'\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc' + b'\xa5\xeb\xa5\xc9\xa1\xaa', 'euc-jp') + msg = Message() + msg.set_payload(jhello, 'utf-8') + ustr = msg.get_payload(decode=True).decode(msg.get_content_charset()) + self.assertEqual(jhello, ustr) def test_payload_encoding(self): - jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa' jcode = 'euc-jp' + jhello = str(b'\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc' + b'\xa5\xeb\xa5\xc9\xa1\xaa', jcode) msg = Message() msg.set_payload(jhello, jcode) - ustr = str(msg.get_payload(), msg.get_content_charset()) - self.assertEqual(jhello, ustr.encode(jcode)) + ustr = msg.get_payload(decode=True).decode(msg.get_content_charset()) + self.assertEqual(jhello, ustr) diff --git a/Lib/test/test_email.py b/Lib/test/test_email.py index f0a18e7..5eebba5 100644 --- a/Lib/test/test_email.py +++ b/Lib/test/test_email.py @@ -3,10 +3,12 @@ # The specific tests now live in Lib/email/test from email.test.test_email import suite +from email.test.test_email_codecs import suite as codecs_suite from test import support def test_main(): support.run_unittest(suite()) + support.run_unittest(codecs_suite()) if __name__ == '__main__': test_main() diff --git a/Misc/ACKS b/Misc/ACKS index a1197ad..8938267 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -371,6 +371,7 @@ Kevan Heydon Jason Hildebrand Richie Hindle Konrad Hinsen +Michael Henry David Hobley Tim Hochberg Joerg-Cyril Hoehle diff --git a/Misc/NEWS b/Misc/NEWS index a201895..adc719b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,9 @@ Core and Builtins Library ------- +- Issue #11554: Fixed support for Japanese codecs; previously the body output + encoding was not done if euc-jp or shift-jis was specified as the charset. + - Issue #11500: Fixed a bug in the os x proxy bypass code for fully qualified IP addresses in the proxy exception list. @@ -99,6 +102,8 @@ Tools/Demos Tests ----- +- Issue #11554: Reactivated test_email_codecs. + - Issue #11490: test_subprocess:test_leaking_fds_on_error no longer gives a false positive if the last directory in the path is inaccessible. -- cgit v0.12 From 106f8e3ea48e247d6f4354890994f0b16fdcc8c4 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Tue, 15 Mar 2011 12:48:41 -0400 Subject: Remove obsolete comment. --- Lib/email/message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/email/message.py b/Lib/email/message.py index b821bfd..28835d0 100644 --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -242,7 +242,7 @@ class Message: raise TypeError('Expected list, got %s' % type(self._payload)) payload = self._payload cte = self.get('content-transfer-encoding', '').lower() - # payload can be bytes here, (I wonder if that is actually a bug?) + # payload may be bytes here. if isinstance(payload, str): if _has_surrogates(payload): bpayload = payload.encode('ascii', 'surrogateescape') -- cgit v0.12 From 8beaa6c2eca32351a6bc3204f4350176fd972fd6 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Tue, 15 Mar 2011 19:10:51 +0200 Subject: Revert typo fixes in _cytpes/libffi* --- Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c | 660 ++--- .../_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c | 2782 ++++++++++---------- 2 files changed, 1721 insertions(+), 1721 deletions(-) diff --git a/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c b/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c index 66c6a3b..501035d 100644 --- a/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c +++ b/Modules/_ctypes/libffi/src/powerpc/ffi_darwin.c @@ -59,24 +59,24 @@ enum { ASM_NEEDS_REGISTERS = 4 }; The stack layout we want looks like this: - | Return address from ffi_call_DARWIN | higher addresses + | Return address from ffi_call_DARWIN | higher addresses |--------------------------------------------| - | Previous backchain pointer 4 | stack pointer here - |--------------------------------------------|<+ <<< on entry to - | Saved r28-r31 4*4 | | ffi_call_DARWIN + | Previous backchain pointer 4 | stack pointer here + |--------------------------------------------|<+ <<< on entry to + | Saved r28-r31 4*4 | | ffi_call_DARWIN |--------------------------------------------| | | Parameters (at least 8*4=32) | | |--------------------------------------------| | | Space for GPR2 4 | | - |--------------------------------------------| | stack | - | Reserved 2*4 | | grows | - |--------------------------------------------| | down V - | Space for callee's LR 4 | | - |--------------------------------------------| | lower addresses + |--------------------------------------------| | stack | + | Reserved 2*4 | | grows | + |--------------------------------------------| | down V + | Space for callee's LR 4 | | + |--------------------------------------------| | lower addresses | Saved CR 4 | | |--------------------------------------------| | stack pointer here - | Current backchain pointer 4 |-/ during - |--------------------------------------------| <<< ffi_call_DARWIN + | Current backchain pointer 4 |-/ during + |--------------------------------------------| <<< ffi_call_DARWIN */ @@ -123,106 +123,106 @@ void ffi_prep_args(extended_cif *ecif, unsigned *const stack) i--, ptr++, p_argv++) { switch ((*ptr)->type) - { - /* If a floating-point parameter appears before all of the general- - purpose registers are filled, the corresponding GPRs that match - the size of the floating-point parameter are skipped. */ - case FFI_TYPE_FLOAT: - double_tmp = *(float *)*p_argv; - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - *(double *)next_arg = double_tmp; - else - *fpr_base++ = double_tmp; - next_arg++; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; - - case FFI_TYPE_DOUBLE: - double_tmp = *(double *)*p_argv; - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - *(double *)next_arg = double_tmp; - else - *fpr_base++ = double_tmp; - next_arg += 2; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; + { + /* If a floating-point parameter appears before all of the general- + purpose registers are filled, the corresponding GPRs that match + the size of the floating-point parameter are skipped. */ + case FFI_TYPE_FLOAT: + double_tmp = *(float *)*p_argv; + if (fparg_count >= NUM_FPR_ARG_REGISTERS) + *(double *)next_arg = double_tmp; + else + *fpr_base++ = double_tmp; + next_arg++; + fparg_count++; + FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); + break; + + case FFI_TYPE_DOUBLE: + double_tmp = *(double *)*p_argv; + if (fparg_count >= NUM_FPR_ARG_REGISTERS) + *(double *)next_arg = double_tmp; + else + *fpr_base++ = double_tmp; + next_arg += 2; + fparg_count++; + FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); + break; #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - double_tmp = ((double *)*p_argv)[0]; - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - *(double *)next_arg = double_tmp; - else - *fpr_base++ = double_tmp; - next_arg += 2; - fparg_count++; - double_tmp = ((double *)*p_argv)[1]; - if (fparg_count >= NUM_FPR_ARG_REGISTERS) - *(double *)next_arg = double_tmp; - else - *fpr_base++ = double_tmp; - next_arg += 2; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; + case FFI_TYPE_LONGDOUBLE: + double_tmp = ((double *)*p_argv)[0]; + if (fparg_count >= NUM_FPR_ARG_REGISTERS) + *(double *)next_arg = double_tmp; + else + *fpr_base++ = double_tmp; + next_arg += 2; + fparg_count++; + double_tmp = ((double *)*p_argv)[1]; + if (fparg_count >= NUM_FPR_ARG_REGISTERS) + *(double *)next_arg = double_tmp; + else + *fpr_base++ = double_tmp; + next_arg += 2; + fparg_count++; + FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); + break; #endif - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - *(long long *)next_arg = *(long long *)*p_argv; - next_arg+=2; - break; - case FFI_TYPE_UINT8: - gprvalue = *(unsigned char *)*p_argv; - goto putgpr; - case FFI_TYPE_SINT8: - gprvalue = *(signed char *)*p_argv; - goto putgpr; - case FFI_TYPE_UINT16: - gprvalue = *(unsigned short *)*p_argv; - goto putgpr; - case FFI_TYPE_SINT16: - gprvalue = *(signed short *)*p_argv; - goto putgpr; - - case FFI_TYPE_STRUCT: - dest_cpy = (char *) next_arg; - - /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, - SI 4 bytes) are aligned as if they were those modes. - Structures with 3 byte in size are padded upwards. */ - size_al = (*ptr)->size; - /* If the first member of the struct is a double, then align - the struct to double-word. - Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ - if ((*ptr)->elements[0]->type == 3) - size_al = ALIGN((*ptr)->size, 8); - if (size_al < 3 && ecif->cif->abi == FFI_DARWIN) - dest_cpy += 4 - size_al; - - memcpy((char *)dest_cpy, (char *)*p_argv, size_al); - next_arg += (size_al + 3) / 4; - break; - - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - gprvalue = *(unsigned *)*p_argv; - putgpr: - *next_arg++ = gprvalue; - break; - default: - break; - } + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + *(long long *)next_arg = *(long long *)*p_argv; + next_arg+=2; + break; + case FFI_TYPE_UINT8: + gprvalue = *(unsigned char *)*p_argv; + goto putgpr; + case FFI_TYPE_SINT8: + gprvalue = *(signed char *)*p_argv; + goto putgpr; + case FFI_TYPE_UINT16: + gprvalue = *(unsigned short *)*p_argv; + goto putgpr; + case FFI_TYPE_SINT16: + gprvalue = *(signed short *)*p_argv; + goto putgpr; + + case FFI_TYPE_STRUCT: + dest_cpy = (char *) next_arg; + + /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, + SI 4 bytes) are aligned as if they were those modes. + Structures with 3 byte in size are padded upwards. */ + size_al = (*ptr)->size; + /* If the first member of the struct is a double, then align + the struct to double-word. + Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ + if ((*ptr)->elements[0]->type == 3) + size_al = ALIGN((*ptr)->size, 8); + if (size_al < 3 && ecif->cif->abi == FFI_DARWIN) + dest_cpy += 4 - size_al; + + memcpy((char *)dest_cpy, (char *)*p_argv, size_al); + next_arg += (size_al + 3) / 4; + break; + + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_POINTER: + gprvalue = *(unsigned *)*p_argv; + putgpr: + *next_arg++ = gprvalue; + break; + default: + break; + } } /* Check that we didn't overrun the stack... */ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); //FFI_ASSERT((unsigned *)fpr_base - // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); + // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); } @@ -246,15 +246,15 @@ darwin_adjust_aggregate_sizes (ffi_type *s) p = s->elements[i]; darwin_adjust_aggregate_sizes (p); if (i == 0 - && (p->type == FFI_TYPE_UINT64 - || p->type == FFI_TYPE_SINT64 - || p->type == FFI_TYPE_DOUBLE - || p->alignment == 8)) - align = 8; + && (p->type == FFI_TYPE_UINT64 + || p->type == FFI_TYPE_SINT64 + || p->type == FFI_TYPE_DOUBLE + || p->alignment == 8)) + align = 8; else if (p->alignment == 16 || p->alignment < 4) - align = p->alignment; + align = p->alignment; else - align = 4; + align = 4; s->size = ALIGN(s->size, align) + p->size; } @@ -287,7 +287,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { darwin_adjust_aggregate_sizes (cif->rtype); for (i = 0; i < cif->nargs; i++) - darwin_adjust_aggregate_sizes (cif->arg_types[i]); + darwin_adjust_aggregate_sizes (cif->arg_types[i]); } /* Space for the frame pointer, callee's LR, CR, etc, and for @@ -348,58 +348,58 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) { switch ((*ptr)->type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - fparg_count++; - /* If this FP arg is going on the stack, it must be - 8-byte-aligned. */ - if (fparg_count > NUM_FPR_ARG_REGISTERS - && intarg_count%2 != 0) - intarg_count++; - break; + { + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + fparg_count++; + /* If this FP arg is going on the stack, it must be + 8-byte-aligned. */ + if (fparg_count > NUM_FPR_ARG_REGISTERS + && intarg_count%2 != 0) + intarg_count++; + break; #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - fparg_count += 2; - /* If this FP arg is going on the stack, it must be - 8-byte-aligned. */ - if (fparg_count > NUM_FPR_ARG_REGISTERS - && intarg_count%2 != 0) - intarg_count++; - intarg_count +=2; - break; + case FFI_TYPE_LONGDOUBLE: + fparg_count += 2; + /* If this FP arg is going on the stack, it must be + 8-byte-aligned. */ + if (fparg_count > NUM_FPR_ARG_REGISTERS + && intarg_count%2 != 0) + intarg_count++; + intarg_count +=2; + break; #endif - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - /* 'long long' arguments are passed as two words, but - either both words must fit in registers or both go - on the stack. If they go on the stack, they must - be 8-byte-aligned. */ - if (intarg_count == NUM_GPR_ARG_REGISTERS-1 - || (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0)) - intarg_count++; - intarg_count += 2; - break; - - case FFI_TYPE_STRUCT: - size_al = (*ptr)->size; - /* If the first member of the struct is a double, then align - the struct to double-word. - Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ - if ((*ptr)->elements[0]->type == 3) - size_al = ALIGN((*ptr)->size, 8); - intarg_count += (size_al + 3) / 4; - break; - - default: - /* Everything else is passed as a 4-byte word in a GPR, either - the object itself or a pointer to it. */ - intarg_count++; - break; - } + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + /* 'long long' arguments are passed as two words, but + either both words must fit in registers or both go + on the stack. If they go on the stack, they must + be 8-byte-aligned. */ + if (intarg_count == NUM_GPR_ARG_REGISTERS-1 + || (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0)) + intarg_count++; + intarg_count += 2; + break; + + case FFI_TYPE_STRUCT: + size_al = (*ptr)->size; + /* If the first member of the struct is a double, then align + the struct to double-word. + Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ + if ((*ptr)->elements[0]->type == 3) + size_al = ALIGN((*ptr)->size, 8); + intarg_count += (size_al + 3) / 4; + break; + + default: + /* Everything else is passed as a 4-byte word in a GPR, either + the object itself or a pointer to it. */ + intarg_count++; + break; + } } if (fparg_count != 0) @@ -425,9 +425,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) } extern void ffi_call_AIX(extended_cif *, unsigned, unsigned, unsigned *, - void (*fn)(void), void (*fn2)(void)); + void (*fn)(void), void (*fn2)(void)); extern void ffi_call_DARWIN(extended_cif *, unsigned, unsigned, unsigned *, - void (*fn)(void), void (*fn2)(void)); + void (*fn)(void), void (*fn2)(void)); void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { @@ -451,11 +451,11 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { case FFI_AIX: ffi_call_AIX(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn, - ffi_prep_args); + ffi_prep_args); break; case FFI_DARWIN: ffi_call_DARWIN(&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn, - ffi_prep_args); + ffi_prep_args); break; default: FFI_ASSERT(0); @@ -478,61 +478,61 @@ typedef struct aix_fd_struct { and aix_clsoure.S SP previous -> +---------------------------------------+ <--- child frame - | back chain to caller 4 | - +---------------------------------------+ 4 - | saved CR 4 | - +---------------------------------------+ 8 - | saved LR 4 | - +---------------------------------------+ 12 - | reserved for compilers 4 | - +---------------------------------------+ 16 - | reserved for binders 4 | - +---------------------------------------+ 20 - | saved TOC pointer 4 | - +---------------------------------------+ 24 - | always reserved 8*4=32 (previous GPRs)| - | according to the linkage convention | - | from AIX | - +---------------------------------------+ 56 - | our FPR area 13*8=104 | - | f1 | - | . | - | f13 | - +---------------------------------------+ 160 - | result area 8 | - +---------------------------------------+ 168 - | alignment to the next multiple of 16 | + | back chain to caller 4 | + +---------------------------------------+ 4 + | saved CR 4 | + +---------------------------------------+ 8 + | saved LR 4 | + +---------------------------------------+ 12 + | reserved for compilers 4 | + +---------------------------------------+ 16 + | reserved for binders 4 | + +---------------------------------------+ 20 + | saved TOC pointer 4 | + +---------------------------------------+ 24 + | always reserved 8*4=32 (previous GPRs)| + | according to the linkage convention | + | from AIX | + +---------------------------------------+ 56 + | our FPR area 13*8=104 | + | f1 | + | . | + | f13 | + +---------------------------------------+ 160 + | result area 8 | + +---------------------------------------+ 168 + | alignement to the next multiple of 16 | SP current --> +---------------------------------------+ 176 <- parent frame - | back chain to caller 4 | - +---------------------------------------+ 180 - | saved CR 4 | - +---------------------------------------+ 184 - | saved LR 4 | - +---------------------------------------+ 188 - | reserved for compilers 4 | - +---------------------------------------+ 192 - | reserved for binders 4 | - +---------------------------------------+ 196 - | saved TOC pointer 4 | - +---------------------------------------+ 200 - | always reserved 8*4=32 we store our | - | GPRs here | - | r3 | - | . | - | r10 | - +---------------------------------------+ 232 - | overflow part | - +---------------------------------------+ xxx - | ???? | - +---------------------------------------+ xxx + | back chain to caller 4 | + +---------------------------------------+ 180 + | saved CR 4 | + +---------------------------------------+ 184 + | saved LR 4 | + +---------------------------------------+ 188 + | reserved for compilers 4 | + +---------------------------------------+ 192 + | reserved for binders 4 | + +---------------------------------------+ 196 + | saved TOC pointer 4 | + +---------------------------------------+ 200 + | always reserved 8*4=32 we store our | + | GPRs here | + | r3 | + | . | + | r10 | + +---------------------------------------+ 232 + | overflow part | + +---------------------------------------+ xxx + | ???? | + +---------------------------------------+ xxx */ ffi_status ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, + void *codeloc) { unsigned int *tramp; struct ffi_aix_trampoline_struct *tramp_aix; @@ -592,12 +592,12 @@ flush_icache(char *addr) { #ifndef _AIX __asm__ volatile ( - "dcbf 0,%0\n" - "\tsync\n" - "\ticbi 0,%0\n" - "\tsync\n" - "\tisync" - : : "r"(addr) : "memory"); + "dcbf 0,%0\n" + "\tsync\n" + "\ticbi 0,%0\n" + "\tsync\n" + "\tisync" + : : "r"(addr) : "memory"); #endif } @@ -618,7 +618,7 @@ typedef union } ffi_dblfl; int ffi_closure_helper_DARWIN (ffi_closure*, void*, - unsigned long*, ffi_dblfl*); + unsigned long*, ffi_dblfl*); /* Basically the trampoline invokes ffi_closure_ASM, and on entry, r11 holds the address of the closure. @@ -628,7 +628,7 @@ int ffi_closure_helper_DARWIN (ffi_closure*, void*, following helper function to do most of the work. */ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, - unsigned long * pgr, ffi_dblfl * pfr) + unsigned long * pgr, ffi_dblfl * pfr) { /* rvalue is the pointer to space for return value in closure assembly pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM @@ -675,121 +675,121 @@ int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue, while (i < avn) { switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = (char *) pgr + 3; - ng++; - pgr++; - break; - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = (char *) pgr + 2; - ng++; - pgr++; - break; - - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - case FFI_TYPE_POINTER: - avalue[i] = pgr; - ng++; - pgr++; - break; - - case FFI_TYPE_STRUCT: - /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, - SI 4 bytes) are aligned as if they were those modes. */ - size_al = arg_types[i]->size; - /* If the first member of the struct is a double, then align - the struct to double-word. - Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ - if (arg_types[i]->elements[0]->type == 3) - size_al = ALIGN(arg_types[i]->size, 8); - if (size_al < 3 && cif->abi == FFI_DARWIN) - avalue[i] = (void*) pgr + 4 - size_al; - else - avalue[i] = (void*) pgr; - ng += (size_al + 3) / 4; - pgr += (size_al + 3) / 4; - break; - - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - /* Long long ints are passed in two gpr's. */ - avalue[i] = pgr; - ng += 2; - pgr += 2; - break; - - case FFI_TYPE_FLOAT: - /* A float value consumes a GPR. - There are 13 64bit floating point registers. */ - if (nf < NUM_FPR_ARG_REGISTERS) - { - temp = pfr->d; - pfr->f = (float)temp; - avalue[i] = pfr; - pfr++; - } - else - { - avalue[i] = pgr; - } - nf++; - ng++; - pgr++; - break; - - case FFI_TYPE_DOUBLE: - /* A double value consumes two GPRs. - There are 13 64bit floating point registers. */ - if (nf < NUM_FPR_ARG_REGISTERS) - { - avalue[i] = pfr; - pfr++; - } - else - { - avalue[i] = pgr; - } - nf++; - ng += 2; - pgr += 2; - break; + { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + avalue[i] = (char *) pgr + 3; + ng++; + pgr++; + break; + + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + avalue[i] = (char *) pgr + 2; + ng++; + pgr++; + break; + + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_POINTER: + avalue[i] = pgr; + ng++; + pgr++; + break; + + case FFI_TYPE_STRUCT: + /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, + SI 4 bytes) are aligned as if they were those modes. */ + size_al = arg_types[i]->size; + /* If the first member of the struct is a double, then align + the struct to double-word. + Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */ + if (arg_types[i]->elements[0]->type == 3) + size_al = ALIGN(arg_types[i]->size, 8); + if (size_al < 3 && cif->abi == FFI_DARWIN) + avalue[i] = (void*) pgr + 4 - size_al; + else + avalue[i] = (void*) pgr; + ng += (size_al + 3) / 4; + pgr += (size_al + 3) / 4; + break; + + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + /* Long long ints are passed in two gpr's. */ + avalue[i] = pgr; + ng += 2; + pgr += 2; + break; + + case FFI_TYPE_FLOAT: + /* A float value consumes a GPR. + There are 13 64bit floating point registers. */ + if (nf < NUM_FPR_ARG_REGISTERS) + { + temp = pfr->d; + pfr->f = (float)temp; + avalue[i] = pfr; + pfr++; + } + else + { + avalue[i] = pgr; + } + nf++; + ng++; + pgr++; + break; + + case FFI_TYPE_DOUBLE: + /* A double value consumes two GPRs. + There are 13 64bit floating point registers. */ + if (nf < NUM_FPR_ARG_REGISTERS) + { + avalue[i] = pfr; + pfr++; + } + else + { + avalue[i] = pgr; + } + nf++; + ng += 2; + pgr += 2; + break; #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - /* A long double value consumes four GPRs and two FPRs. - There are 13 64bit floating point registers. */ - if (nf < NUM_FPR_ARG_REGISTERS - 1) - { - avalue[i] = pfr; - pfr += 2; - } - /* Here we have the situation where one part of the long double - is stored in fpr13 and the other part is already on the stack. - We use a union to pass the long double to avalue[i]. */ - else if (nf == NUM_FPR_ARG_REGISTERS - 1) - { - memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits)); - memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits)); - avalue[i] = &temp_ld.ld; - } - else - { - avalue[i] = pgr; - } - nf += 2; - ng += 4; - pgr += 4; - break; + case FFI_TYPE_LONGDOUBLE: + /* A long double value consumes four GPRs and two FPRs. + There are 13 64bit floating point registers. */ + if (nf < NUM_FPR_ARG_REGISTERS - 1) + { + avalue[i] = pfr; + pfr += 2; + } + /* Here we have the situation where one part of the long double + is stored in fpr13 and the other part is already on the stack. + We use a union to pass the long double to avalue[i]. */ + else if (nf == NUM_FPR_ARG_REGISTERS - 1) + { + memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits)); + memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits)); + avalue[i] = &temp_ld.ld; + } + else + { + avalue[i] = pgr; + } + nf += 2; + ng += 4; + pgr += 4; + break; #endif - default: - FFI_ASSERT(0); - } + default: + FFI_ASSERT(0); + } i++; } diff --git a/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c b/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c index e00f153..8953d5f 100644 --- a/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +++ b/Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c @@ -39,7 +39,7 @@ #if 0 #if defined(POWERPC_DARWIN) -#include // for sys_icache_invalidate() +#include // for sys_icache_invalidate() #endif #else @@ -55,8 +55,8 @@ extern void ffi_closure_ASM(void); // The layout of a function descriptor. A C function pointer really // points to one of these. typedef struct aix_fd_struct { - void* code_pointer; - void* toc; + void* code_pointer; + void* toc; } aix_fd; /* ffi_prep_args is called by the assembly routine once stack space @@ -64,241 +64,241 @@ typedef struct aix_fd_struct { The stack layout we want looks like this: - | Return address from ffi_call_DARWIN | higher addresses + | Return address from ffi_call_DARWIN | higher addresses |--------------------------------------------| - | Previous backchain pointer 4/8 | stack pointer here + | Previous backchain pointer 4/8 | stack pointer here |--------------------------------------------|-\ <<< on entry to - | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN + | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN |--------------------------------------------| | | Parameters (at least 8*(4/8)=32/64) | | (176) +112 - +288 |--------------------------------------------| | | Space for GPR2 4/8 | | - |--------------------------------------------| | stack | - | Reserved (4/8)*2 | | grows | - |--------------------------------------------| | down V + |--------------------------------------------| | stack | + | Reserved (4/8)*2 | | grows | + |--------------------------------------------| | down V | Space for callee's LR 4/8 | | - |--------------------------------------------| | lower addresses + |--------------------------------------------| | lower addresses | Saved CR 4/8 | | |--------------------------------------------| | stack pointer here | Current backchain pointer 4/8 | | during |--------------------------------------------|-/ <<< ffi_call_DARWIN - Note: ppc64 CR is saved in the low word of a long on the stack. + Note: ppc64 CR is saved in the low word of a long on the stack. */ /*@-exportheader@*/ void ffi_prep_args( - extended_cif* inEcif, - unsigned *const stack) + extended_cif* inEcif, + unsigned *const stack) /*@=exportheader@*/ { - /* Copy the ecif to a local var so we can trample the arg. - BC note: test this with GP later for possible problems... */ - volatile extended_cif* ecif = inEcif; + /* Copy the ecif to a local var so we can trample the arg. + BC note: test this with GP later for possible problems... */ + volatile extended_cif* ecif = inEcif; - const unsigned bytes = ecif->cif->bytes; - const unsigned flags = ecif->cif->flags; + const unsigned bytes = ecif->cif->bytes; + const unsigned flags = ecif->cif->flags; - /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode - and 8 in 64-bit mode. */ - unsigned long *const longStack = (unsigned long *const)stack; + /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode + and 8 in 64-bit mode. */ + unsigned long *const longStack = (unsigned long *const)stack; - /* 'stacktop' points at the previous backchain pointer. */ + /* 'stacktop' points at the previous backchain pointer. */ #if defined(__ppc64__) - // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area, - // saved registers, and an extra FPR. - unsigned long *const stacktop = - (unsigned long *)(unsigned long)((char*)longStack + bytes + 96); + // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area, + // saved registers, and an extra FPR. + unsigned long *const stacktop = + (unsigned long *)(unsigned long)((char*)longStack + bytes + 96); #elif defined(__ppc__) - unsigned long *const stacktop = longStack + (bytes / sizeof(long)); + unsigned long *const stacktop = longStack + (bytes / sizeof(long)); #else #error undefined architecture #endif - /* 'fpr_base' points at the space for fpr1, and grows upwards as - we use FPR registers. */ - double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) - - NUM_FPR_ARG_REGISTERS; + /* 'fpr_base' points at the space for fpr1, and grows upwards as + we use FPR registers. */ + double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) - + NUM_FPR_ARG_REGISTERS; #if defined(__ppc64__) - // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base - // down a couple pegs. - fpr_base -= 2; + // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base + // down a couple pegs. + fpr_base -= 2; #endif - unsigned int fparg_count = 0; + unsigned int fparg_count = 0; - /* 'next_arg' grows up as we put parameters in it. */ - unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */ + /* 'next_arg' grows up as we put parameters in it. */ + unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */ - int i; - double double_tmp; - void** p_argv = ecif->avalue; - unsigned long gprvalue; - ffi_type** ptr = ecif->cif->arg_types; + int i; + double double_tmp; + void** p_argv = ecif->avalue; + unsigned long gprvalue; + ffi_type** ptr = ecif->cif->arg_types; - /* Check that everything starts aligned properly. */ - FFI_ASSERT(stack == SF_ROUND(stack)); - FFI_ASSERT(stacktop == SF_ROUND(stacktop)); - FFI_ASSERT(bytes == SF_ROUND(bytes)); + /* Check that everything starts aligned properly. */ + FFI_ASSERT(stack == SF_ROUND(stack)); + FFI_ASSERT(stacktop == SF_ROUND(stacktop)); + FFI_ASSERT(bytes == SF_ROUND(bytes)); - /* Deal with return values that are actually pass-by-reference. - Rule: - Return values are referenced by r3, so r4 is the first parameter. */ + /* Deal with return values that are actually pass-by-reference. + Rule: + Return values are referenced by r3, so r4 is the first parameter. */ - if (flags & FLAG_RETVAL_REFERENCE) - *next_arg++ = (unsigned long)(char*)ecif->rvalue; + if (flags & FLAG_RETVAL_REFERENCE) + *next_arg++ = (unsigned long)(char*)ecif->rvalue; - /* Now for the arguments. */ - for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) + /* Now for the arguments. */ + for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) { - switch ((*ptr)->type) - { - /* If a floating-point parameter appears before all of the general- - purpose registers are filled, the corresponding GPRs that match - the size of the floating-point parameter are shadowed for the - benefit of vararg and pre-ANSI functions. */ - case FFI_TYPE_FLOAT: - double_tmp = *(float*)*p_argv; + switch ((*ptr)->type) + { + /* If a floating-point parameter appears before all of the general- + purpose registers are filled, the corresponding GPRs that match + the size of the floating-point parameter are shadowed for the + benefit of vararg and pre-ANSI functions. */ + case FFI_TYPE_FLOAT: + double_tmp = *(float*)*p_argv; - if (fparg_count < NUM_FPR_ARG_REGISTERS) - *fpr_base++ = double_tmp; + if (fparg_count < NUM_FPR_ARG_REGISTERS) + *fpr_base++ = double_tmp; - *(double*)next_arg = double_tmp; + *(double*)next_arg = double_tmp; - next_arg++; - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); + next_arg++; + fparg_count++; + FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; + break; - case FFI_TYPE_DOUBLE: - double_tmp = *(double*)*p_argv; + case FFI_TYPE_DOUBLE: + double_tmp = *(double*)*p_argv; - if (fparg_count < NUM_FPR_ARG_REGISTERS) - *fpr_base++ = double_tmp; + if (fparg_count < NUM_FPR_ARG_REGISTERS) + *fpr_base++ = double_tmp; - *(double*)next_arg = double_tmp; + *(double*)next_arg = double_tmp; - next_arg += MODE_CHOICE(2,1); - fparg_count++; - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); + next_arg += MODE_CHOICE(2,1); + fparg_count++; + FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; + break; #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: + case FFI_TYPE_LONGDOUBLE: #if defined(__ppc64__) - if (fparg_count < NUM_FPR_ARG_REGISTERS) - *(long double*)fpr_base = *(long double*)*p_argv; + if (fparg_count < NUM_FPR_ARG_REGISTERS) + *(long double*)fpr_base = *(long double*)*p_argv; #elif defined(__ppc__) - if (fparg_count < NUM_FPR_ARG_REGISTERS - 1) - *(long double*)fpr_base = *(long double*)*p_argv; - else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1) - *(double*)fpr_base = *(double*)*p_argv; + if (fparg_count < NUM_FPR_ARG_REGISTERS - 1) + *(long double*)fpr_base = *(long double*)*p_argv; + else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1) + *(double*)fpr_base = *(double*)*p_argv; #else #error undefined architecture #endif - *(long double*)next_arg = *(long double*)*p_argv; - fparg_count += 2; - fpr_base += 2; - next_arg += MODE_CHOICE(4,2); - FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); + *(long double*)next_arg = *(long double*)*p_argv; + fparg_count += 2; + fpr_base += 2; + next_arg += MODE_CHOICE(4,2); + FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); - break; -#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + break; +#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: #if defined(__ppc64__) - gprvalue = *(long long*)*p_argv; - goto putgpr; + gprvalue = *(long long*)*p_argv; + goto putgpr; #elif defined(__ppc__) - *(long long*)next_arg = *(long long*)*p_argv; - next_arg += 2; - break; + *(long long*)next_arg = *(long long*)*p_argv; + next_arg += 2; + break; #else #error undefined architecture #endif - case FFI_TYPE_POINTER: - gprvalue = *(unsigned long*)*p_argv; - goto putgpr; + case FFI_TYPE_POINTER: + gprvalue = *(unsigned long*)*p_argv; + goto putgpr; - case FFI_TYPE_UINT8: - gprvalue = *(unsigned char*)*p_argv; - goto putgpr; + case FFI_TYPE_UINT8: + gprvalue = *(unsigned char*)*p_argv; + goto putgpr; - case FFI_TYPE_SINT8: - gprvalue = *(signed char*)*p_argv; - goto putgpr; + case FFI_TYPE_SINT8: + gprvalue = *(signed char*)*p_argv; + goto putgpr; - case FFI_TYPE_UINT16: - gprvalue = *(unsigned short*)*p_argv; - goto putgpr; + case FFI_TYPE_UINT16: + gprvalue = *(unsigned short*)*p_argv; + goto putgpr; - case FFI_TYPE_SINT16: - gprvalue = *(signed short*)*p_argv; - goto putgpr; + case FFI_TYPE_SINT16: + gprvalue = *(signed short*)*p_argv; + goto putgpr; - case FFI_TYPE_STRUCT: - { + case FFI_TYPE_STRUCT: + { #if defined(__ppc64__) - unsigned int gprSize = 0; - unsigned int fprSize = 0; + unsigned int gprSize = 0; + unsigned int fprSize = 0; - ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count, - (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize); - next_arg += gprSize / sizeof(long); - fpr_base += fprSize / sizeof(double); + ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count, + (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize); + next_arg += gprSize / sizeof(long); + fpr_base += fprSize / sizeof(double); #elif defined(__ppc__) - char* dest_cpy = (char*)next_arg; - - /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, - SI 4 bytes) are aligned as if they were those modes. - Structures with 3 byte in size are padded upwards. */ - unsigned size_al = (*ptr)->size; - - /* If the first member of the struct is a double, then align - the struct to double-word. */ - if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN((*ptr)->size, 8); - - if (ecif->cif->abi == FFI_DARWIN) - { - if (size_al < 3) - dest_cpy += 4 - size_al; - } - - memcpy((char*)dest_cpy, (char*)*p_argv, size_al); - next_arg += (size_al + 3) / 4; + char* dest_cpy = (char*)next_arg; + + /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, + SI 4 bytes) are aligned as if they were those modes. + Structures with 3 byte in size are padded upwards. */ + unsigned size_al = (*ptr)->size; + + /* If the first member of the struct is a double, then align + the struct to double-word. */ + if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) + size_al = ALIGN((*ptr)->size, 8); + + if (ecif->cif->abi == FFI_DARWIN) + { + if (size_al < 3) + dest_cpy += 4 - size_al; + } + + memcpy((char*)dest_cpy, (char*)*p_argv, size_al); + next_arg += (size_al + 3) / 4; #else #error undefined architecture #endif - break; - } + break; + } - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - gprvalue = *(unsigned*)*p_argv; + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + gprvalue = *(unsigned*)*p_argv; putgpr: - *next_arg++ = gprvalue; - break; + *next_arg++ = gprvalue; + break; - default: - break; - } - } + default: + break; + } + } /* Check that we didn't overrun the stack... */ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); //FFI_ASSERT((unsigned *)fpr_base - // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); + // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); } @@ -306,320 +306,320 @@ putgpr: bool ffi64_struct_contains_fp( - const ffi_type* inType) + const ffi_type* inType) { - bool containsFP = false; - unsigned int i; - - for (i = 0; inType->elements[i] != NULL && !containsFP; i++) - { - if (inType->elements[i]->type == FFI_TYPE_FLOAT || - inType->elements[i]->type == FFI_TYPE_DOUBLE || - inType->elements[i]->type == FFI_TYPE_LONGDOUBLE) - containsFP = true; - else if (inType->elements[i]->type == FFI_TYPE_STRUCT) - containsFP = ffi64_struct_contains_fp(inType->elements[i]); - } - - return containsFP; + bool containsFP = false; + unsigned int i; + + for (i = 0; inType->elements[i] != NULL && !containsFP; i++) + { + if (inType->elements[i]->type == FFI_TYPE_FLOAT || + inType->elements[i]->type == FFI_TYPE_DOUBLE || + inType->elements[i]->type == FFI_TYPE_LONGDOUBLE) + containsFP = true; + else if (inType->elements[i]->type == FFI_TYPE_STRUCT) + containsFP = ffi64_struct_contains_fp(inType->elements[i]); + } + + return containsFP; } -#endif // defined(__ppc64__) +#endif // defined(__ppc64__) /* Perform machine dependent cif processing. */ ffi_status ffi_prep_cif_machdep( - ffi_cif* cif) + ffi_cif* cif) { - /* All this is for the DARWIN ABI. */ - int i; - ffi_type** ptr; - int intarg_count = 0; - int fparg_count = 0; - unsigned int flags = 0; - unsigned int size_al = 0; - - /* All the machine-independent calculation of cif->bytes will be wrong. - Redo the calculation for DARWIN. */ - - /* Space for the frame pointer, callee's LR, CR, etc, and for - the asm's temp regs. */ - unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); - - /* Return value handling. The rules are as follows: - - 32-bit (or less) integer values are returned in gpr3; - - Structures of size <= 4 bytes also returned in gpr3; - - 64-bit integer values and structures between 5 and 8 bytes are - returned in gpr3 and gpr4; - - Single/double FP values are returned in fpr1; - - Long double FP (if not equivalent to double) values are returned in - fpr1 and fpr2; - - Larger structures values are allocated space and a pointer is passed - as the first argument. */ - switch (cif->rtype->type) - { + /* All this is for the DARWIN ABI. */ + int i; + ffi_type** ptr; + int intarg_count = 0; + int fparg_count = 0; + unsigned int flags = 0; + unsigned int size_al = 0; + + /* All the machine-independent calculation of cif->bytes will be wrong. + Redo the calculation for DARWIN. */ + + /* Space for the frame pointer, callee's LR, CR, etc, and for + the asm's temp regs. */ + unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); + + /* Return value handling. The rules are as follows: + - 32-bit (or less) integer values are returned in gpr3; + - Structures of size <= 4 bytes also returned in gpr3; + - 64-bit integer values and structures between 5 and 8 bytes are + returned in gpr3 and gpr4; + - Single/double FP values are returned in fpr1; + - Long double FP (if not equivalent to double) values are returned in + fpr1 and fpr2; + - Larger structures values are allocated space and a pointer is passed + as the first argument. */ + switch (cif->rtype->type) + { #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - flags |= FLAG_RETURNS_128BITS; - flags |= FLAG_RETURNS_FP; - break; -#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - - case FFI_TYPE_DOUBLE: - flags |= FLAG_RETURNS_64BITS; - /* Fall through. */ - case FFI_TYPE_FLOAT: - flags |= FLAG_RETURNS_FP; - break; + case FFI_TYPE_LONGDOUBLE: + flags |= FLAG_RETURNS_128BITS; + flags |= FLAG_RETURNS_FP; + break; +#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + + case FFI_TYPE_DOUBLE: + flags |= FLAG_RETURNS_64BITS; + /* Fall through. */ + case FFI_TYPE_FLOAT: + flags |= FLAG_RETURNS_FP; + break; #if defined(__ppc64__) - case FFI_TYPE_POINTER: + case FFI_TYPE_POINTER: #endif - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - flags |= FLAG_RETURNS_64BITS; - break; + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + flags |= FLAG_RETURNS_64BITS; + break; - case FFI_TYPE_STRUCT: - { + case FFI_TYPE_STRUCT: + { #if defined(__ppc64__) - if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) - { - flags |= FLAG_RETVAL_REFERENCE; - flags |= FLAG_RETURNS_NOTHING; - intarg_count++; - } - else - { - flags |= FLAG_RETURNS_STRUCT; + if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) + { + flags |= FLAG_RETVAL_REFERENCE; + flags |= FLAG_RETURNS_NOTHING; + intarg_count++; + } + else + { + flags |= FLAG_RETURNS_STRUCT; - if (ffi64_struct_contains_fp(cif->rtype)) - flags |= FLAG_STRUCT_CONTAINS_FP; - } + if (ffi64_struct_contains_fp(cif->rtype)) + flags |= FLAG_STRUCT_CONTAINS_FP; + } #elif defined(__ppc__) - flags |= FLAG_RETVAL_REFERENCE; - flags |= FLAG_RETURNS_NOTHING; - intarg_count++; + flags |= FLAG_RETVAL_REFERENCE; + flags |= FLAG_RETURNS_NOTHING; + intarg_count++; #else #error undefined architecture #endif - break; - } - - case FFI_TYPE_VOID: - flags |= FLAG_RETURNS_NOTHING; - break; - - default: - /* Returns 32-bit integer, or similar. Nothing to do here. */ - break; - } - - /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the - first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest - goes on the stack. Structures are passed as a pointer to a copy of - the structure. Stuff on the stack needs to keep proper alignment. */ - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - switch ((*ptr)->type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - fparg_count++; - /* If this FP arg is going on the stack, it must be - 8-byte-aligned. */ - if (fparg_count > NUM_FPR_ARG_REGISTERS - && intarg_count % 2 != 0) - intarg_count++; - break; + break; + } + + case FFI_TYPE_VOID: + flags |= FLAG_RETURNS_NOTHING; + break; + + default: + /* Returns 32-bit integer, or similar. Nothing to do here. */ + break; + } + + /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the + first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest + goes on the stack. Structures are passed as a pointer to a copy of + the structure. Stuff on the stack needs to keep proper alignment. */ + for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) + { + switch ((*ptr)->type) + { + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + fparg_count++; + /* If this FP arg is going on the stack, it must be + 8-byte-aligned. */ + if (fparg_count > NUM_FPR_ARG_REGISTERS + && intarg_count % 2 != 0) + intarg_count++; + break; #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: - fparg_count += 2; - /* If this FP arg is going on the stack, it must be - 8-byte-aligned. */ + case FFI_TYPE_LONGDOUBLE: + fparg_count += 2; + /* If this FP arg is going on the stack, it must be + 8-byte-aligned. */ - if ( + if ( #if defined(__ppc64__) - fparg_count > NUM_FPR_ARG_REGISTERS + 1 + fparg_count > NUM_FPR_ARG_REGISTERS + 1 #elif defined(__ppc__) - fparg_count > NUM_FPR_ARG_REGISTERS + fparg_count > NUM_FPR_ARG_REGISTERS #else #error undefined architecture #endif - && intarg_count % 2 != 0) - intarg_count++; - - intarg_count += 2; - break; -#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - /* 'long long' arguments are passed as two words, but - either both words must fit in registers or both go - on the stack. If they go on the stack, they must - be 8-byte-aligned. */ - if (intarg_count == NUM_GPR_ARG_REGISTERS - 1 - || (intarg_count >= NUM_GPR_ARG_REGISTERS - && intarg_count % 2 != 0)) - intarg_count++; - - intarg_count += MODE_CHOICE(2,1); - - break; - - case FFI_TYPE_STRUCT: - size_al = (*ptr)->size; - /* If the first member of the struct is a double, then align - the struct to double-word. */ - if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN((*ptr)->size, 8); + && intarg_count % 2 != 0) + intarg_count++; + + intarg_count += 2; + break; +#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + /* 'long long' arguments are passed as two words, but + either both words must fit in registers or both go + on the stack. If they go on the stack, they must + be 8-byte-aligned. */ + if (intarg_count == NUM_GPR_ARG_REGISTERS - 1 + || (intarg_count >= NUM_GPR_ARG_REGISTERS + && intarg_count % 2 != 0)) + intarg_count++; + + intarg_count += MODE_CHOICE(2,1); + + break; + + case FFI_TYPE_STRUCT: + size_al = (*ptr)->size; + /* If the first member of the struct is a double, then align + the struct to double-word. */ + if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) + size_al = ALIGN((*ptr)->size, 8); #if defined(__ppc64__) - // Look for FP struct members. - unsigned int j; - - for (j = 0; (*ptr)->elements[j] != NULL; j++) - { - if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT || - (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE) - { - fparg_count++; - - if (fparg_count > NUM_FPR_ARG_REGISTERS) - intarg_count++; - } - else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE) - { - fparg_count += 2; - - if (fparg_count > NUM_FPR_ARG_REGISTERS + 1) - intarg_count += 2; - } - else - intarg_count++; - } + // Look for FP struct members. + unsigned int j; + + for (j = 0; (*ptr)->elements[j] != NULL; j++) + { + if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT || + (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE) + { + fparg_count++; + + if (fparg_count > NUM_FPR_ARG_REGISTERS) + intarg_count++; + } + else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE) + { + fparg_count += 2; + + if (fparg_count > NUM_FPR_ARG_REGISTERS + 1) + intarg_count += 2; + } + else + intarg_count++; + } #elif defined(__ppc__) - intarg_count += (size_al + 3) / 4; + intarg_count += (size_al + 3) / 4; #else #error undefined architecture #endif - break; + break; - default: - /* Everything else is passed as a 4/8-byte word in a GPR, either - the object itself or a pointer to it. */ - intarg_count++; - break; - } - } + default: + /* Everything else is passed as a 4/8-byte word in a GPR, either + the object itself or a pointer to it. */ + intarg_count++; + break; + } + } - /* Space for the FPR registers, if needed. */ - if (fparg_count != 0) - { - flags |= FLAG_FP_ARGUMENTS; + /* Space for the FPR registers, if needed. */ + if (fparg_count != 0) + { + flags |= FLAG_FP_ARGUMENTS; #if defined(__ppc64__) - bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double); + bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double); #elif defined(__ppc__) - bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); + bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); #else #error undefined architecture #endif - } + } - /* Stack space. */ + /* Stack space. */ #if defined(__ppc64__) - if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) - bytes += (intarg_count + fparg_count) * sizeof(long); + if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) + bytes += (intarg_count + fparg_count) * sizeof(long); #elif defined(__ppc__) - if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) - bytes += (intarg_count + 2 * fparg_count) * sizeof(long); + if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) + bytes += (intarg_count + 2 * fparg_count) * sizeof(long); #else #error undefined architecture #endif - else - bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); + else + bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); - /* The stack space allocated needs to be a multiple of 16/32 bytes. */ - bytes = SF_ROUND(bytes); + /* The stack space allocated needs to be a multiple of 16/32 bytes. */ + bytes = SF_ROUND(bytes); - cif->flags = flags; - cif->bytes = bytes; + cif->flags = flags; + cif->bytes = bytes; - return FFI_OK; + return FFI_OK; } /*@-declundef@*/ /*@-exportheader@*/ extern void ffi_call_AIX( -/*@out@*/ extended_cif*, - unsigned, - unsigned, -/*@out@*/ unsigned*, - void (*fn)(void), - void (*fn2)(extended_cif*, unsigned *const)); +/*@out@*/ extended_cif*, + unsigned, + unsigned, +/*@out@*/ unsigned*, + void (*fn)(void), + void (*fn2)(extended_cif*, unsigned *const)); extern void ffi_call_DARWIN( -/*@out@*/ extended_cif*, - unsigned long, - unsigned, -/*@out@*/ unsigned*, - void (*fn)(void), - void (*fn2)(extended_cif*, unsigned *const)); +/*@out@*/ extended_cif*, + unsigned long, + unsigned, +/*@out@*/ unsigned*, + void (*fn)(void), + void (*fn2)(extended_cif*, unsigned *const)); /*@=declundef@*/ /*@=exportheader@*/ void ffi_call( -/*@dependent@*/ ffi_cif* cif, - void (*fn)(void), -/*@out@*/ void* rvalue, -/*@dependent@*/ void** avalue) +/*@dependent@*/ ffi_cif* cif, + void (*fn)(void), +/*@out@*/ void* rvalue, +/*@dependent@*/ void** avalue) { - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return - value address then we need to make one. */ - if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - /*@-sysunrecog@*/ - ecif.rvalue = alloca(cif->rtype->size); - /*@=sysunrecog@*/ - } - else - ecif.rvalue = rvalue; - - switch (cif->abi) - { - case FFI_AIX: - /*@-usedef@*/ - ffi_call_AIX(&ecif, -cif->bytes, - cif->flags, ecif.rvalue, fn, ffi_prep_args); - /*@=usedef@*/ - break; - - case FFI_DARWIN: - /*@-usedef@*/ - ffi_call_DARWIN(&ecif, -(long)cif->bytes, - cif->flags, ecif.rvalue, fn, ffi_prep_args); - /*@=usedef@*/ - break; - - default: - FFI_ASSERT(0); - break; + extended_cif ecif; + + ecif.cif = cif; + ecif.avalue = avalue; + + /* If the return value is a struct and we don't have a return + value address then we need to make one. */ + if ((rvalue == NULL) && + (cif->rtype->type == FFI_TYPE_STRUCT)) + { + /*@-sysunrecog@*/ + ecif.rvalue = alloca(cif->rtype->size); + /*@=sysunrecog@*/ + } + else + ecif.rvalue = rvalue; + + switch (cif->abi) + { + case FFI_AIX: + /*@-usedef@*/ + ffi_call_AIX(&ecif, -cif->bytes, + cif->flags, ecif.rvalue, fn, ffi_prep_args); + /*@=usedef@*/ + break; + + case FFI_DARWIN: + /*@-usedef@*/ + ffi_call_DARWIN(&ecif, -(long)cif->bytes, + cif->flags, ecif.rvalue, fn, ffi_prep_args); + /*@=usedef@*/ + break; + + default: + FFI_ASSERT(0); + break; } } @@ -627,53 +627,53 @@ ffi_call( and aix_clsoure.S SP previous -> +---------------------------------------+ <--- child frame - | back chain to caller 4 | - +---------------------------------------+ 4 - | saved CR 4 | - +---------------------------------------+ 8 - | saved LR 4 | - +---------------------------------------+ 12 - | reserved for compilers 4 | - +---------------------------------------+ 16 - | reserved for binders 4 | - +---------------------------------------+ 20 - | saved TOC pointer 4 | - +---------------------------------------+ 24 - | always reserved 8*4=32 (previous GPRs)| - | according to the linkage convention | - | from AIX | - +---------------------------------------+ 56 - | our FPR area 13*8=104 | - | f1 | - | . | - | f13 | - +---------------------------------------+ 160 - | result area 8 | - +---------------------------------------+ 168 - | alignment to the next multiple of 16 | + | back chain to caller 4 | + +---------------------------------------+ 4 + | saved CR 4 | + +---------------------------------------+ 8 + | saved LR 4 | + +---------------------------------------+ 12 + | reserved for compilers 4 | + +---------------------------------------+ 16 + | reserved for binders 4 | + +---------------------------------------+ 20 + | saved TOC pointer 4 | + +---------------------------------------+ 24 + | always reserved 8*4=32 (previous GPRs)| + | according to the linkage convention | + | from AIX | + +---------------------------------------+ 56 + | our FPR area 13*8=104 | + | f1 | + | . | + | f13 | + +---------------------------------------+ 160 + | result area 8 | + +---------------------------------------+ 168 + | alignement to the next multiple of 16 | SP current --> +---------------------------------------+ 176 <- parent frame - | back chain to caller 4 | - +---------------------------------------+ 180 - | saved CR 4 | - +---------------------------------------+ 184 - | saved LR 4 | - +---------------------------------------+ 188 - | reserved for compilers 4 | - +---------------------------------------+ 192 - | reserved for binders 4 | - +---------------------------------------+ 196 - | saved TOC pointer 4 | - +---------------------------------------+ 200 - | always reserved 8*4=32 we store our | - | GPRs here | - | r3 | - | . | - | r10 | - +---------------------------------------+ 232 - | overflow part | - +---------------------------------------+ xxx - | ???? | - +---------------------------------------+ xxx + | back chain to caller 4 | + +---------------------------------------+ 180 + | saved CR 4 | + +---------------------------------------+ 184 + | saved LR 4 | + +---------------------------------------+ 188 + | reserved for compilers 4 | + +---------------------------------------+ 192 + | reserved for binders 4 | + +---------------------------------------+ 196 + | saved TOC pointer 4 | + +---------------------------------------+ 200 + | always reserved 8*4=32 we store our | + | GPRs here | + | r3 | + | . | + | r10 | + +---------------------------------------+ 232 + | overflow part | + +---------------------------------------+ xxx + | ???? | + +---------------------------------------+ xxx */ #if !defined(POWERPC_DARWIN) @@ -682,1095 +682,1095 @@ SP current --> +---------------------------------------+ 176 <- parent frame static void flush_icache( - char* addr) + char* addr) { #ifndef _AIX - __asm__ volatile ( - "dcbf 0,%0\n" - "sync\n" - "icbi 0,%0\n" - "sync\n" - "isync" - : : "r" (addr) : "memory"); + __asm__ volatile ( + "dcbf 0,%0\n" + "sync\n" + "icbi 0,%0\n" + "sync\n" + "isync" + : : "r" (addr) : "memory"); #endif } static void flush_range( - char* addr, - int size) + char* addr, + int size) { - int i; + int i; - for (i = 0; i < size; i += MIN_LINE_SIZE) - flush_icache(addr + i); + for (i = 0; i < size; i += MIN_LINE_SIZE) + flush_icache(addr + i); - flush_icache(addr + size - 1); + flush_icache(addr + size - 1); } -#endif // !defined(POWERPC_DARWIN) +#endif // !defined(POWERPC_DARWIN) ffi_status ffi_prep_closure( - ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void* user_data) + ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void* user_data) { - switch (cif->abi) - { - case FFI_DARWIN: - { - FFI_ASSERT (cif->abi == FFI_DARWIN); + switch (cif->abi) + { + case FFI_DARWIN: + { + FFI_ASSERT (cif->abi == FFI_DARWIN); - unsigned int* tramp = (unsigned int*)&closure->tramp[0]; + unsigned int* tramp = (unsigned int*)&closure->tramp[0]; #if defined(__ppc64__) - tramp[0] = 0x7c0802a6; // mflr r0 - tramp[1] = 0x429f0005; // bcl 20,31,+0x8 - tramp[2] = 0x7d6802a6; // mflr r11 - tramp[3] = 0x7c0803a6; // mtlr r0 - tramp[4] = 0xe98b0018; // ld r12,24(r11) - tramp[5] = 0x7d8903a6; // mtctr r12 - tramp[6] = 0xe96b0020; // ld r11,32(r11) - tramp[7] = 0x4e800420; // bctr - *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM; - *(unsigned long*)&tramp[10] = (unsigned long)closure; + tramp[0] = 0x7c0802a6; // mflr r0 + tramp[1] = 0x429f0005; // bcl 20,31,+0x8 + tramp[2] = 0x7d6802a6; // mflr r11 + tramp[3] = 0x7c0803a6; // mtlr r0 + tramp[4] = 0xe98b0018; // ld r12,24(r11) + tramp[5] = 0x7d8903a6; // mtctr r12 + tramp[6] = 0xe96b0020; // ld r11,32(r11) + tramp[7] = 0x4e800420; // bctr + *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM; + *(unsigned long*)&tramp[10] = (unsigned long)closure; #elif defined(__ppc__) - tramp[0] = 0x7c0802a6; // mflr r0 - tramp[1] = 0x429f0005; // bcl 20,31,+0x8 - tramp[2] = 0x7d6802a6; // mflr r11 - tramp[3] = 0x7c0803a6; // mtlr r0 - tramp[4] = 0x818b0018; // lwz r12,24(r11) - tramp[5] = 0x7d8903a6; // mtctr r12 - tramp[6] = 0x816b001c; // lwz r11,28(r11) - tramp[7] = 0x4e800420; // bctr - tramp[8] = (unsigned long)ffi_closure_ASM; - tramp[9] = (unsigned long)closure; + tramp[0] = 0x7c0802a6; // mflr r0 + tramp[1] = 0x429f0005; // bcl 20,31,+0x8 + tramp[2] = 0x7d6802a6; // mflr r11 + tramp[3] = 0x7c0803a6; // mtlr r0 + tramp[4] = 0x818b0018; // lwz r12,24(r11) + tramp[5] = 0x7d8903a6; // mtctr r12 + tramp[6] = 0x816b001c; // lwz r11,28(r11) + tramp[7] = 0x4e800420; // bctr + tramp[8] = (unsigned long)ffi_closure_ASM; + tramp[9] = (unsigned long)closure; #else #error undefined architecture #endif - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; - // Flush the icache. Only necessary on Darwin. + // Flush the icache. Only necessary on Darwin. #if defined(POWERPC_DARWIN) - sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE); + sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE); #else - flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE); + flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE); #endif - break; - } + break; + } - case FFI_AIX: - { - FFI_ASSERT (cif->abi == FFI_AIX); + case FFI_AIX: + { + FFI_ASSERT (cif->abi == FFI_AIX); - ffi_aix_trampoline_struct* tramp_aix = - (ffi_aix_trampoline_struct*)(closure->tramp); - aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM; + ffi_aix_trampoline_struct* tramp_aix = + (ffi_aix_trampoline_struct*)(closure->tramp); + aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM; - tramp_aix->code_pointer = fd->code_pointer; - tramp_aix->toc = fd->toc; - tramp_aix->static_chain = closure; - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - break; - } + tramp_aix->code_pointer = fd->code_pointer; + tramp_aix->toc = fd->toc; + tramp_aix->static_chain = closure; + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + break; + } - default: - return FFI_BAD_ABI; - } + default: + return FFI_BAD_ABI; + } - return FFI_OK; + return FFI_OK; } #if defined(__ppc__) - typedef double ldbits[2]; + typedef double ldbits[2]; - typedef union - { - ldbits lb; - long double ld; - } ldu; + typedef union + { + ldbits lb; + long double ld; + } ldu; #endif typedef union { - float f; - double d; + float f; + double d; } ffi_dblfl; -/* The trampoline invokes ffi_closure_ASM, and on entry, r11 holds the - address of the closure. After storing the registers that could possibly - contain parameters to be passed into the stack frame and setting up space - for a return value, ffi_closure_ASM invokes the following helper function - to do most of the work. */ +/* The trampoline invokes ffi_closure_ASM, and on entry, r11 holds the + address of the closure. After storing the registers that could possibly + contain parameters to be passed into the stack frame and setting up space + for a return value, ffi_closure_ASM invokes the following helper function + to do most of the work. */ int ffi_closure_helper_DARWIN( - ffi_closure* closure, - void* rvalue, - unsigned long* pgr, - ffi_dblfl* pfr) + ffi_closure* closure, + void* rvalue, + unsigned long* pgr, + ffi_dblfl* pfr) { - /* rvalue is the pointer to space for return value in closure assembly - pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM - pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ + /* rvalue is the pointer to space for return value in closure assembly + pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM + pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ #if defined(__ppc__) - ldu temp_ld; + ldu temp_ld; #endif - double temp; - unsigned int i; - unsigned int nf = 0; /* number of FPRs already used. */ - unsigned int ng = 0; /* number of GPRs already used. */ - ffi_cif* cif = closure->cif; - long avn = cif->nargs; - void** avalue = alloca(cif->nargs * sizeof(void*)); - ffi_type** arg_types = cif->arg_types; - - /* Copy the caller's structure return value address so that the closure - returns the data directly to the caller. */ + double temp; + unsigned int i; + unsigned int nf = 0; /* number of FPRs already used. */ + unsigned int ng = 0; /* number of GPRs already used. */ + ffi_cif* cif = closure->cif; + long avn = cif->nargs; + void** avalue = alloca(cif->nargs * sizeof(void*)); + ffi_type** arg_types = cif->arg_types; + + /* Copy the caller's structure return value address so that the closure + returns the data directly to the caller. */ #if defined(__ppc64__) - if (cif->rtype->type == FFI_TYPE_STRUCT && - ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) + if (cif->rtype->type == FFI_TYPE_STRUCT && + ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) #elif defined(__ppc__) - if (cif->rtype->type == FFI_TYPE_STRUCT) + if (cif->rtype->type == FFI_TYPE_STRUCT) #else #error undefined architecture #endif - { - rvalue = (void*)*pgr; - pgr++; - ng++; - } - - /* Grab the addresses of the arguments from the stack frame. */ - for (i = 0; i < avn; i++) - { - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - avalue[i] = (char*)pgr + MODE_CHOICE(3,7); - ng++; - pgr++; - break; - - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - avalue[i] = (char*)pgr + MODE_CHOICE(2,6); - ng++; - pgr++; - break; + { + rvalue = (void*)*pgr; + pgr++; + ng++; + } + + /* Grab the addresses of the arguments from the stack frame. */ + for (i = 0; i < avn; i++) + { + switch (arg_types[i]->type) + { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + avalue[i] = (char*)pgr + MODE_CHOICE(3,7); + ng++; + pgr++; + break; + + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + avalue[i] = (char*)pgr + MODE_CHOICE(2,6); + ng++; + pgr++; + break; #if defined(__ppc__) - case FFI_TYPE_POINTER: + case FFI_TYPE_POINTER: #endif - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT32: - avalue[i] = (char*)pgr + MODE_CHOICE(0,4); - ng++; - pgr++; + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + avalue[i] = (char*)pgr + MODE_CHOICE(0,4); + ng++; + pgr++; - break; + break; - case FFI_TYPE_STRUCT: - if (cif->abi == FFI_DARWIN) - { + case FFI_TYPE_STRUCT: + if (cif->abi == FFI_DARWIN) + { #if defined(__ppc64__) - unsigned int gprSize = 0; - unsigned int fprSize = 0; - unsigned int savedFPRSize = fprSize; + unsigned int gprSize = 0; + unsigned int fprSize = 0; + unsigned int savedFPRSize = fprSize; - avalue[i] = alloca(arg_types[i]->size); - ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr, - &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL); + avalue[i] = alloca(arg_types[i]->size); + ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr, + &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL); - ng += gprSize / sizeof(long); - pgr += gprSize / sizeof(long); - pfr += (fprSize - savedFPRSize) / sizeof(double); + ng += gprSize / sizeof(long); + pgr += gprSize / sizeof(long); + pfr += (fprSize - savedFPRSize) / sizeof(double); #elif defined(__ppc__) - /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, - SI 4 bytes) are aligned as if they were those modes. */ - unsigned int size_al = size_al = arg_types[i]->size; - - /* If the first member of the struct is a double, then align - the struct to double-word. */ - if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN(arg_types[i]->size, 8); - - if (size_al < 3) - avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al; - else - avalue[i] = (void*)pgr; - - ng += (size_al + 3) / sizeof(long); - pgr += (size_al + 3) / sizeof(long); + /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, + SI 4 bytes) are aligned as if they were those modes. */ + unsigned int size_al = size_al = arg_types[i]->size; + + /* If the first member of the struct is a double, then align + the struct to double-word. */ + if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) + size_al = ALIGN(arg_types[i]->size, 8); + + if (size_al < 3) + avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al; + else + avalue[i] = (void*)pgr; + + ng += (size_al + 3) / sizeof(long); + pgr += (size_al + 3) / sizeof(long); #else #error undefined architecture #endif - } + } - break; + break; #if defined(__ppc64__) - case FFI_TYPE_POINTER: + case FFI_TYPE_POINTER: #endif - case FFI_TYPE_SINT64: - case FFI_TYPE_UINT64: - /* Long long ints are passed in 1 or 2 GPRs. */ - avalue[i] = pgr; - ng += MODE_CHOICE(2,1); - pgr += MODE_CHOICE(2,1); - - break; - - case FFI_TYPE_FLOAT: - /* A float value consumes a GPR. - There are 13 64-bit floating point registers. */ - if (nf < NUM_FPR_ARG_REGISTERS) - { - temp = pfr->d; - pfr->f = (float)temp; - avalue[i] = pfr; - pfr++; - } - else - avalue[i] = pgr; - - nf++; - ng++; - pgr++; - break; - - case FFI_TYPE_DOUBLE: - /* A double value consumes one or two GPRs. - There are 13 64bit floating point registers. */ - if (nf < NUM_FPR_ARG_REGISTERS) - { - avalue[i] = pfr; - pfr++; - } - else - avalue[i] = pgr; - - nf++; - ng += MODE_CHOICE(2,1); - pgr += MODE_CHOICE(2,1); - - break; + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + /* Long long ints are passed in 1 or 2 GPRs. */ + avalue[i] = pgr; + ng += MODE_CHOICE(2,1); + pgr += MODE_CHOICE(2,1); + + break; + + case FFI_TYPE_FLOAT: + /* A float value consumes a GPR. + There are 13 64-bit floating point registers. */ + if (nf < NUM_FPR_ARG_REGISTERS) + { + temp = pfr->d; + pfr->f = (float)temp; + avalue[i] = pfr; + pfr++; + } + else + avalue[i] = pgr; + + nf++; + ng++; + pgr++; + break; + + case FFI_TYPE_DOUBLE: + /* A double value consumes one or two GPRs. + There are 13 64bit floating point registers. */ + if (nf < NUM_FPR_ARG_REGISTERS) + { + avalue[i] = pfr; + pfr++; + } + else + avalue[i] = pgr; + + nf++; + ng += MODE_CHOICE(2,1); + pgr += MODE_CHOICE(2,1); + + break; #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: + case FFI_TYPE_LONGDOUBLE: #if defined(__ppc64__) - if (nf < NUM_FPR_ARG_REGISTERS) - { - avalue[i] = pfr; - pfr += 2; - } + if (nf < NUM_FPR_ARG_REGISTERS) + { + avalue[i] = pfr; + pfr += 2; + } #elif defined(__ppc__) - /* A long double value consumes 2/4 GPRs and 2 FPRs. - There are 13 64bit floating point registers. */ - if (nf < NUM_FPR_ARG_REGISTERS - 1) - { - avalue[i] = pfr; - pfr += 2; - } - /* Here we have the situation where one part of the long double - is stored in fpr13 and the other part is already on the stack. - We use a union to pass the long double to avalue[i]. */ - else if (nf == NUM_FPR_ARG_REGISTERS - 1) - { - memcpy (&temp_ld.lb[0], pfr, sizeof(temp_ld.lb[0])); - memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1])); - avalue[i] = &temp_ld.ld; - } + /* A long double value consumes 2/4 GPRs and 2 FPRs. + There are 13 64bit floating point registers. */ + if (nf < NUM_FPR_ARG_REGISTERS - 1) + { + avalue[i] = pfr; + pfr += 2; + } + /* Here we have the situation where one part of the long double + is stored in fpr13 and the other part is already on the stack. + We use a union to pass the long double to avalue[i]. */ + else if (nf == NUM_FPR_ARG_REGISTERS - 1) + { + memcpy (&temp_ld.lb[0], pfr, sizeof(temp_ld.lb[0])); + memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1])); + avalue[i] = &temp_ld.ld; + } #else #error undefined architecture #endif - else - avalue[i] = pgr; + else + avalue[i] = pgr; - nf += 2; - ng += MODE_CHOICE(4,2); - pgr += MODE_CHOICE(4,2); + nf += 2; + ng += MODE_CHOICE(4,2); + pgr += MODE_CHOICE(4,2); - break; + break; -#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */ +#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */ - default: - FFI_ASSERT(0); - break; - } - } + default: + FFI_ASSERT(0); + break; + } + } - (closure->fun)(cif, rvalue, avalue, closure->user_data); + (closure->fun)(cif, rvalue, avalue, closure->user_data); - /* Tell ffi_closure_ASM to perform return type promotions. */ - return cif->rtype->type; + /* Tell ffi_closure_ASM to perform return type promotions. */ + return cif->rtype->type; } #if defined(__ppc64__) -/* ffi64_struct_to_ram_form +/* ffi64_struct_to_ram_form - Rebuild a struct's natural layout from buffers of concatenated registers. - Return the number of registers used. - inGPRs[0-7] == r3, inFPRs[0-7] == f1 ... + Rebuild a struct's natural layout from buffers of concatenated registers. + Return the number of registers used. + inGPRs[0-7] == r3, inFPRs[0-7] == f1 ... */ void ffi64_struct_to_ram_form( - const ffi_type* inType, - const char* inGPRs, - unsigned int* ioGPRMarker, - const char* inFPRs, - unsigned int* ioFPRMarker, - unsigned int* ioFPRsUsed, - char* outStruct, // caller-allocated - unsigned int* ioStructMarker) + const ffi_type* inType, + const char* inGPRs, + unsigned int* ioGPRMarker, + const char* inFPRs, + unsigned int* ioFPRMarker, + unsigned int* ioFPRsUsed, + char* outStruct, // caller-allocated + unsigned int* ioStructMarker) { - unsigned int srcGMarker = 0; - unsigned int srcFMarker = 0; - unsigned int savedFMarker = 0; - unsigned int fprsUsed = 0; - unsigned int savedFPRsUsed = 0; - unsigned int destMarker = 0; - - static unsigned int recurseCount = 0; - - if (ioGPRMarker) - srcGMarker = *ioGPRMarker; - - if (ioFPRMarker) - { - srcFMarker = *ioFPRMarker; - savedFMarker = srcFMarker; - } - - if (ioFPRsUsed) - { - fprsUsed = *ioFPRsUsed; - savedFPRsUsed = fprsUsed; - } - - if (ioStructMarker) - destMarker = *ioStructMarker; - - size_t i; - - switch (inType->size) - { - case 1: case 2: case 4: - srcGMarker += 8 - inType->size; - break; - - default: - break; - } - - for (i = 0; inType->elements[i] != NULL; i++) - { - switch (inType->elements[i]->type) - { - case FFI_TYPE_FLOAT: - srcFMarker = ALIGN(srcFMarker, 4); - srcGMarker = ALIGN(srcGMarker, 4); - destMarker = ALIGN(destMarker, 4); - - if (fprsUsed < NUM_FPR_ARG_REGISTERS) - { - *(float*)&outStruct[destMarker] = - (float)*(double*)&inFPRs[srcFMarker]; - srcFMarker += 8; - fprsUsed++; - } - else - *(float*)&outStruct[destMarker] = - (float)*(double*)&inGPRs[srcGMarker]; - - srcGMarker += 4; - destMarker += 4; - - // Skip to next GPR if next element won't fit and we're - // not already at a register boundary. - if (inType->elements[i + 1] != NULL && (destMarker % 8)) - { - if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && - (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || - (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && - (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || - (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) - srcGMarker = ALIGN(srcGMarker, 8); - } - - break; - - case FFI_TYPE_DOUBLE: - srcFMarker = ALIGN(srcFMarker, 8); - destMarker = ALIGN(destMarker, 8); - - if (fprsUsed < NUM_FPR_ARG_REGISTERS) - { - *(double*)&outStruct[destMarker] = - *(double*)&inFPRs[srcFMarker]; - srcFMarker += 8; - fprsUsed++; - } - else - *(double*)&outStruct[destMarker] = - *(double*)&inGPRs[srcGMarker]; - - destMarker += 8; - - // Skip next GPR - srcGMarker += 8; - srcGMarker = ALIGN(srcGMarker, 8); - - break; - - case FFI_TYPE_LONGDOUBLE: - destMarker = ALIGN(destMarker, 16); - - if (fprsUsed < NUM_FPR_ARG_REGISTERS) - { - srcFMarker = ALIGN(srcFMarker, 8); - srcGMarker = ALIGN(srcGMarker, 8); - *(long double*)&outStruct[destMarker] = - *(long double*)&inFPRs[srcFMarker]; - srcFMarker += 16; - fprsUsed += 2; - } - else - { - srcFMarker = ALIGN(srcFMarker, 16); - srcGMarker = ALIGN(srcGMarker, 16); - *(long double*)&outStruct[destMarker] = - *(long double*)&inGPRs[srcGMarker]; - } - - destMarker += 16; - - // Skip next 2 GPRs - srcGMarker += 16; - srcGMarker = ALIGN(srcGMarker, 8); - - break; - - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - { - if (inType->alignment == 1) // chars only - { - if (inType->size == 1) - outStruct[destMarker++] = inGPRs[srcGMarker++]; - else if (inType->size == 2) - { - outStruct[destMarker++] = inGPRs[srcGMarker++]; - outStruct[destMarker++] = inGPRs[srcGMarker++]; - i++; - } - else - { - memcpy(&outStruct[destMarker], - &inGPRs[srcGMarker], inType->size); - srcGMarker += inType->size; - destMarker += inType->size; - i += inType->size - 1; - } - } - else // chars and other stuff - { - outStruct[destMarker++] = inGPRs[srcGMarker++]; - - // Skip to next GPR if next element won't fit and we're - // not already at a register boundary. - if (inType->elements[i + 1] != NULL && (srcGMarker % 8)) - { - if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && - (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || - (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && - (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || - (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) - srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8 - } - } - - break; - } - - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - srcGMarker = ALIGN(srcGMarker, 2); - destMarker = ALIGN(destMarker, 2); - - *(short*)&outStruct[destMarker] = - *(short*)&inGPRs[srcGMarker]; - srcGMarker += 2; - destMarker += 2; - - break; - - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - srcGMarker = ALIGN(srcGMarker, 4); - destMarker = ALIGN(destMarker, 4); - - *(int*)&outStruct[destMarker] = - *(int*)&inGPRs[srcGMarker]; - srcGMarker += 4; - destMarker += 4; - - break; - - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - srcGMarker = ALIGN(srcGMarker, 8); - destMarker = ALIGN(destMarker, 8); - - *(long long*)&outStruct[destMarker] = - *(long long*)&inGPRs[srcGMarker]; - srcGMarker += 8; - destMarker += 8; - - break; - - case FFI_TYPE_STRUCT: - recurseCount++; - ffi64_struct_to_ram_form(inType->elements[i], inGPRs, - &srcGMarker, inFPRs, &srcFMarker, &fprsUsed, - outStruct, &destMarker); - recurseCount--; - break; - - default: - FFI_ASSERT(0); // unknown element type - break; - } - } - - srcGMarker = ALIGN(srcGMarker, inType->alignment); - - // Take care of the special case for 16-byte structs, but not for - // nested structs. - if (recurseCount == 0 && srcGMarker == 16) - { - *(long double*)&outStruct[0] = *(long double*)&inGPRs[0]; - srcFMarker = savedFMarker; - fprsUsed = savedFPRsUsed; - } - - if (ioGPRMarker) - *ioGPRMarker = ALIGN(srcGMarker, 8); - - if (ioFPRMarker) - *ioFPRMarker = srcFMarker; - - if (ioFPRsUsed) - *ioFPRsUsed = fprsUsed; - - if (ioStructMarker) - *ioStructMarker = ALIGN(destMarker, 8); + unsigned int srcGMarker = 0; + unsigned int srcFMarker = 0; + unsigned int savedFMarker = 0; + unsigned int fprsUsed = 0; + unsigned int savedFPRsUsed = 0; + unsigned int destMarker = 0; + + static unsigned int recurseCount = 0; + + if (ioGPRMarker) + srcGMarker = *ioGPRMarker; + + if (ioFPRMarker) + { + srcFMarker = *ioFPRMarker; + savedFMarker = srcFMarker; + } + + if (ioFPRsUsed) + { + fprsUsed = *ioFPRsUsed; + savedFPRsUsed = fprsUsed; + } + + if (ioStructMarker) + destMarker = *ioStructMarker; + + size_t i; + + switch (inType->size) + { + case 1: case 2: case 4: + srcGMarker += 8 - inType->size; + break; + + default: + break; + } + + for (i = 0; inType->elements[i] != NULL; i++) + { + switch (inType->elements[i]->type) + { + case FFI_TYPE_FLOAT: + srcFMarker = ALIGN(srcFMarker, 4); + srcGMarker = ALIGN(srcGMarker, 4); + destMarker = ALIGN(destMarker, 4); + + if (fprsUsed < NUM_FPR_ARG_REGISTERS) + { + *(float*)&outStruct[destMarker] = + (float)*(double*)&inFPRs[srcFMarker]; + srcFMarker += 8; + fprsUsed++; + } + else + *(float*)&outStruct[destMarker] = + (float)*(double*)&inGPRs[srcGMarker]; + + srcGMarker += 4; + destMarker += 4; + + // Skip to next GPR if next element won't fit and we're + // not already at a register boundary. + if (inType->elements[i + 1] != NULL && (destMarker % 8)) + { + if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && + (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || + (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && + (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || + (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) + srcGMarker = ALIGN(srcGMarker, 8); + } + + break; + + case FFI_TYPE_DOUBLE: + srcFMarker = ALIGN(srcFMarker, 8); + destMarker = ALIGN(destMarker, 8); + + if (fprsUsed < NUM_FPR_ARG_REGISTERS) + { + *(double*)&outStruct[destMarker] = + *(double*)&inFPRs[srcFMarker]; + srcFMarker += 8; + fprsUsed++; + } + else + *(double*)&outStruct[destMarker] = + *(double*)&inGPRs[srcGMarker]; + + destMarker += 8; + + // Skip next GPR + srcGMarker += 8; + srcGMarker = ALIGN(srcGMarker, 8); + + break; + + case FFI_TYPE_LONGDOUBLE: + destMarker = ALIGN(destMarker, 16); + + if (fprsUsed < NUM_FPR_ARG_REGISTERS) + { + srcFMarker = ALIGN(srcFMarker, 8); + srcGMarker = ALIGN(srcGMarker, 8); + *(long double*)&outStruct[destMarker] = + *(long double*)&inFPRs[srcFMarker]; + srcFMarker += 16; + fprsUsed += 2; + } + else + { + srcFMarker = ALIGN(srcFMarker, 16); + srcGMarker = ALIGN(srcGMarker, 16); + *(long double*)&outStruct[destMarker] = + *(long double*)&inGPRs[srcGMarker]; + } + + destMarker += 16; + + // Skip next 2 GPRs + srcGMarker += 16; + srcGMarker = ALIGN(srcGMarker, 8); + + break; + + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + { + if (inType->alignment == 1) // chars only + { + if (inType->size == 1) + outStruct[destMarker++] = inGPRs[srcGMarker++]; + else if (inType->size == 2) + { + outStruct[destMarker++] = inGPRs[srcGMarker++]; + outStruct[destMarker++] = inGPRs[srcGMarker++]; + i++; + } + else + { + memcpy(&outStruct[destMarker], + &inGPRs[srcGMarker], inType->size); + srcGMarker += inType->size; + destMarker += inType->size; + i += inType->size - 1; + } + } + else // chars and other stuff + { + outStruct[destMarker++] = inGPRs[srcGMarker++]; + + // Skip to next GPR if next element won't fit and we're + // not already at a register boundary. + if (inType->elements[i + 1] != NULL && (srcGMarker % 8)) + { + if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && + (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || + (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && + (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || + (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) + srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8 + } + } + + break; + } + + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + srcGMarker = ALIGN(srcGMarker, 2); + destMarker = ALIGN(destMarker, 2); + + *(short*)&outStruct[destMarker] = + *(short*)&inGPRs[srcGMarker]; + srcGMarker += 2; + destMarker += 2; + + break; + + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + srcGMarker = ALIGN(srcGMarker, 4); + destMarker = ALIGN(destMarker, 4); + + *(int*)&outStruct[destMarker] = + *(int*)&inGPRs[srcGMarker]; + srcGMarker += 4; + destMarker += 4; + + break; + + case FFI_TYPE_POINTER: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + srcGMarker = ALIGN(srcGMarker, 8); + destMarker = ALIGN(destMarker, 8); + + *(long long*)&outStruct[destMarker] = + *(long long*)&inGPRs[srcGMarker]; + srcGMarker += 8; + destMarker += 8; + + break; + + case FFI_TYPE_STRUCT: + recurseCount++; + ffi64_struct_to_ram_form(inType->elements[i], inGPRs, + &srcGMarker, inFPRs, &srcFMarker, &fprsUsed, + outStruct, &destMarker); + recurseCount--; + break; + + default: + FFI_ASSERT(0); // unknown element type + break; + } + } + + srcGMarker = ALIGN(srcGMarker, inType->alignment); + + // Take care of the special case for 16-byte structs, but not for + // nested structs. + if (recurseCount == 0 && srcGMarker == 16) + { + *(long double*)&outStruct[0] = *(long double*)&inGPRs[0]; + srcFMarker = savedFMarker; + fprsUsed = savedFPRsUsed; + } + + if (ioGPRMarker) + *ioGPRMarker = ALIGN(srcGMarker, 8); + + if (ioFPRMarker) + *ioFPRMarker = srcFMarker; + + if (ioFPRsUsed) + *ioFPRsUsed = fprsUsed; + + if (ioStructMarker) + *ioStructMarker = ALIGN(destMarker, 8); } -/* ffi64_struct_to_reg_form +/* ffi64_struct_to_reg_form - Copy a struct's elements into buffers that can be sliced into registers. - Return the sizes of the output buffers in bytes. Pass NULL buffer pointers - to calculate size only. - outGPRs[0-7] == r3, outFPRs[0-7] == f1 ... + Copy a struct's elements into buffers that can be sliced into registers. + Return the sizes of the output buffers in bytes. Pass NULL buffer pointers + to calculate size only. + outGPRs[0-7] == r3, outFPRs[0-7] == f1 ... */ void ffi64_struct_to_reg_form( - const ffi_type* inType, - const char* inStruct, - unsigned int* ioStructMarker, - unsigned int* ioFPRsUsed, - char* outGPRs, // caller-allocated - unsigned int* ioGPRSize, - char* outFPRs, // caller-allocated - unsigned int* ioFPRSize) + const ffi_type* inType, + const char* inStruct, + unsigned int* ioStructMarker, + unsigned int* ioFPRsUsed, + char* outGPRs, // caller-allocated + unsigned int* ioGPRSize, + char* outFPRs, // caller-allocated + unsigned int* ioFPRSize) { - size_t i; - unsigned int srcMarker = 0; - unsigned int destGMarker = 0; - unsigned int destFMarker = 0; - unsigned int savedFMarker = 0; - unsigned int fprsUsed = 0; - unsigned int savedFPRsUsed = 0; - - static unsigned int recurseCount = 0; - - if (ioStructMarker) - srcMarker = *ioStructMarker; - - if (ioFPRsUsed) - { - fprsUsed = *ioFPRsUsed; - savedFPRsUsed = fprsUsed; - } - - if (ioGPRSize) - destGMarker = *ioGPRSize; - - if (ioFPRSize) - { - destFMarker = *ioFPRSize; - savedFMarker = destFMarker; - } - - switch (inType->size) - { - case 1: case 2: case 4: - destGMarker += 8 - inType->size; - break; - - default: - break; - } - - for (i = 0; inType->elements[i] != NULL; i++) - { - switch (inType->elements[i]->type) - { - // Shadow floating-point types in GPRs for vararg and pre-ANSI - // functions. - case FFI_TYPE_FLOAT: - // Nudge markers to next 4/8-byte boundary - srcMarker = ALIGN(srcMarker, 4); - destGMarker = ALIGN(destGMarker, 4); - destFMarker = ALIGN(destFMarker, 8); - - if (fprsUsed < NUM_FPR_ARG_REGISTERS) - { - if (outFPRs != NULL && inStruct != NULL) - *(double*)&outFPRs[destFMarker] = - (double)*(float*)&inStruct[srcMarker]; - - destFMarker += 8; - fprsUsed++; - } - - if (outGPRs != NULL && inStruct != NULL) - *(double*)&outGPRs[destGMarker] = - (double)*(float*)&inStruct[srcMarker]; - - srcMarker += 4; - destGMarker += 4; - - // Skip to next GPR if next element won't fit and we're - // not already at a register boundary. - if (inType->elements[i + 1] != NULL && (srcMarker % 8)) - { - if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && - (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || - (ALIGN(destGMarker, 8) - destGMarker) < 2) && - (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || - (ALIGN(destGMarker, 8) - destGMarker) < 4)) - destGMarker = ALIGN(destGMarker, 8); - } - - break; - - case FFI_TYPE_DOUBLE: - srcMarker = ALIGN(srcMarker, 8); - destFMarker = ALIGN(destFMarker, 8); - - if (fprsUsed < NUM_FPR_ARG_REGISTERS) - { - if (outFPRs != NULL && inStruct != NULL) - *(double*)&outFPRs[destFMarker] = - *(double*)&inStruct[srcMarker]; - - destFMarker += 8; - fprsUsed++; - } - - if (outGPRs != NULL && inStruct != NULL) - *(double*)&outGPRs[destGMarker] = - *(double*)&inStruct[srcMarker]; - - srcMarker += 8; - - // Skip next GPR - destGMarker += 8; - destGMarker = ALIGN(destGMarker, 8); - - break; - - case FFI_TYPE_LONGDOUBLE: - srcMarker = ALIGN(srcMarker, 16); - - if (fprsUsed < NUM_FPR_ARG_REGISTERS) - { - destFMarker = ALIGN(destFMarker, 8); - destGMarker = ALIGN(destGMarker, 8); - - if (outFPRs != NULL && inStruct != NULL) - *(long double*)&outFPRs[destFMarker] = - *(long double*)&inStruct[srcMarker]; - - if (outGPRs != NULL && inStruct != NULL) - *(long double*)&outGPRs[destGMarker] = - *(long double*)&inStruct[srcMarker]; - - destFMarker += 16; - fprsUsed += 2; - } - else - { - destGMarker = ALIGN(destGMarker, 16); - - if (outGPRs != NULL && inStruct != NULL) - *(long double*)&outGPRs[destGMarker] = - *(long double*)&inStruct[srcMarker]; - } - - srcMarker += 16; - destGMarker += 16; // Skip next 2 GPRs - destGMarker = ALIGN(destGMarker, 8); // was 16 - - break; - - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - if (inType->alignment == 1) // bytes only - { - if (inType->size == 1) - { - if (outGPRs != NULL && inStruct != NULL) - outGPRs[destGMarker] = inStruct[srcMarker]; - - srcMarker++; - destGMarker++; - } - else if (inType->size == 2) - { - if (outGPRs != NULL && inStruct != NULL) - { - outGPRs[destGMarker] = inStruct[srcMarker]; - outGPRs[destGMarker + 1] = inStruct[srcMarker + 1]; - } - - srcMarker += 2; - destGMarker += 2; - - i++; - } - else - { - if (outGPRs != NULL && inStruct != NULL) - { - // Avoid memcpy for small chunks. - if (inType->size <= sizeof(long)) - *(long*)&outGPRs[destGMarker] = - *(long*)&inStruct[srcMarker]; - else - memcpy(&outGPRs[destGMarker], - &inStruct[srcMarker], inType->size); - } - - srcMarker += inType->size; - destGMarker += inType->size; - i += inType->size - 1; - } - } - else // bytes and other stuff - { - if (outGPRs != NULL && inStruct != NULL) - outGPRs[destGMarker] = inStruct[srcMarker]; - - srcMarker++; - destGMarker++; - - // Skip to next GPR if next element won't fit and we're - // not already at a register boundary. - if (inType->elements[i + 1] != NULL && (destGMarker % 8)) - { - if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && - (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || - (ALIGN(destGMarker, 8) - destGMarker) < 2) && - (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || - (ALIGN(destGMarker, 8) - destGMarker) < 4)) - destGMarker = ALIGN(destGMarker, inType->alignment); // was 8 - } - } - - break; - - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - srcMarker = ALIGN(srcMarker, 2); - destGMarker = ALIGN(destGMarker, 2); - - if (outGPRs != NULL && inStruct != NULL) - *(short*)&outGPRs[destGMarker] = - *(short*)&inStruct[srcMarker]; - - srcMarker += 2; - destGMarker += 2; - - if (inType->elements[i + 1] == NULL) - destGMarker = ALIGN(destGMarker, inType->alignment); - - break; - - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - srcMarker = ALIGN(srcMarker, 4); - destGMarker = ALIGN(destGMarker, 4); - - if (outGPRs != NULL && inStruct != NULL) - *(int*)&outGPRs[destGMarker] = - *(int*)&inStruct[srcMarker]; - - srcMarker += 4; - destGMarker += 4; - - break; - - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - srcMarker = ALIGN(srcMarker, 8); - destGMarker = ALIGN(destGMarker, 8); - - if (outGPRs != NULL && inStruct != NULL) - *(long long*)&outGPRs[destGMarker] = - *(long long*)&inStruct[srcMarker]; - - srcMarker += 8; - destGMarker += 8; - - if (inType->elements[i + 1] == NULL) - destGMarker = ALIGN(destGMarker, inType->alignment); - - break; - - case FFI_TYPE_STRUCT: - recurseCount++; - ffi64_struct_to_reg_form(inType->elements[i], - inStruct, &srcMarker, &fprsUsed, outGPRs, - &destGMarker, outFPRs, &destFMarker); - recurseCount--; - break; - - default: - FFI_ASSERT(0); - break; - } - } - - destGMarker = ALIGN(destGMarker, inType->alignment); - - // Take care of the special case for 16-byte structs, but not for - // nested structs. - if (recurseCount == 0 && destGMarker == 16) - { - if (outGPRs != NULL && inStruct != NULL) - *(long double*)&outGPRs[0] = *(long double*)&inStruct[0]; - - destFMarker = savedFMarker; - fprsUsed = savedFPRsUsed; - } - - if (ioStructMarker) - *ioStructMarker = ALIGN(srcMarker, 8); - - if (ioFPRsUsed) - *ioFPRsUsed = fprsUsed; - - if (ioGPRSize) - *ioGPRSize = ALIGN(destGMarker, 8); - - if (ioFPRSize) - *ioFPRSize = ALIGN(destFMarker, 8); + size_t i; + unsigned int srcMarker = 0; + unsigned int destGMarker = 0; + unsigned int destFMarker = 0; + unsigned int savedFMarker = 0; + unsigned int fprsUsed = 0; + unsigned int savedFPRsUsed = 0; + + static unsigned int recurseCount = 0; + + if (ioStructMarker) + srcMarker = *ioStructMarker; + + if (ioFPRsUsed) + { + fprsUsed = *ioFPRsUsed; + savedFPRsUsed = fprsUsed; + } + + if (ioGPRSize) + destGMarker = *ioGPRSize; + + if (ioFPRSize) + { + destFMarker = *ioFPRSize; + savedFMarker = destFMarker; + } + + switch (inType->size) + { + case 1: case 2: case 4: + destGMarker += 8 - inType->size; + break; + + default: + break; + } + + for (i = 0; inType->elements[i] != NULL; i++) + { + switch (inType->elements[i]->type) + { + // Shadow floating-point types in GPRs for vararg and pre-ANSI + // functions. + case FFI_TYPE_FLOAT: + // Nudge markers to next 4/8-byte boundary + srcMarker = ALIGN(srcMarker, 4); + destGMarker = ALIGN(destGMarker, 4); + destFMarker = ALIGN(destFMarker, 8); + + if (fprsUsed < NUM_FPR_ARG_REGISTERS) + { + if (outFPRs != NULL && inStruct != NULL) + *(double*)&outFPRs[destFMarker] = + (double)*(float*)&inStruct[srcMarker]; + + destFMarker += 8; + fprsUsed++; + } + + if (outGPRs != NULL && inStruct != NULL) + *(double*)&outGPRs[destGMarker] = + (double)*(float*)&inStruct[srcMarker]; + + srcMarker += 4; + destGMarker += 4; + + // Skip to next GPR if next element won't fit and we're + // not already at a register boundary. + if (inType->elements[i + 1] != NULL && (srcMarker % 8)) + { + if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && + (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || + (ALIGN(destGMarker, 8) - destGMarker) < 2) && + (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || + (ALIGN(destGMarker, 8) - destGMarker) < 4)) + destGMarker = ALIGN(destGMarker, 8); + } + + break; + + case FFI_TYPE_DOUBLE: + srcMarker = ALIGN(srcMarker, 8); + destFMarker = ALIGN(destFMarker, 8); + + if (fprsUsed < NUM_FPR_ARG_REGISTERS) + { + if (outFPRs != NULL && inStruct != NULL) + *(double*)&outFPRs[destFMarker] = + *(double*)&inStruct[srcMarker]; + + destFMarker += 8; + fprsUsed++; + } + + if (outGPRs != NULL && inStruct != NULL) + *(double*)&outGPRs[destGMarker] = + *(double*)&inStruct[srcMarker]; + + srcMarker += 8; + + // Skip next GPR + destGMarker += 8; + destGMarker = ALIGN(destGMarker, 8); + + break; + + case FFI_TYPE_LONGDOUBLE: + srcMarker = ALIGN(srcMarker, 16); + + if (fprsUsed < NUM_FPR_ARG_REGISTERS) + { + destFMarker = ALIGN(destFMarker, 8); + destGMarker = ALIGN(destGMarker, 8); + + if (outFPRs != NULL && inStruct != NULL) + *(long double*)&outFPRs[destFMarker] = + *(long double*)&inStruct[srcMarker]; + + if (outGPRs != NULL && inStruct != NULL) + *(long double*)&outGPRs[destGMarker] = + *(long double*)&inStruct[srcMarker]; + + destFMarker += 16; + fprsUsed += 2; + } + else + { + destGMarker = ALIGN(destGMarker, 16); + + if (outGPRs != NULL && inStruct != NULL) + *(long double*)&outGPRs[destGMarker] = + *(long double*)&inStruct[srcMarker]; + } + + srcMarker += 16; + destGMarker += 16; // Skip next 2 GPRs + destGMarker = ALIGN(destGMarker, 8); // was 16 + + break; + + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + if (inType->alignment == 1) // bytes only + { + if (inType->size == 1) + { + if (outGPRs != NULL && inStruct != NULL) + outGPRs[destGMarker] = inStruct[srcMarker]; + + srcMarker++; + destGMarker++; + } + else if (inType->size == 2) + { + if (outGPRs != NULL && inStruct != NULL) + { + outGPRs[destGMarker] = inStruct[srcMarker]; + outGPRs[destGMarker + 1] = inStruct[srcMarker + 1]; + } + + srcMarker += 2; + destGMarker += 2; + + i++; + } + else + { + if (outGPRs != NULL && inStruct != NULL) + { + // Avoid memcpy for small chunks. + if (inType->size <= sizeof(long)) + *(long*)&outGPRs[destGMarker] = + *(long*)&inStruct[srcMarker]; + else + memcpy(&outGPRs[destGMarker], + &inStruct[srcMarker], inType->size); + } + + srcMarker += inType->size; + destGMarker += inType->size; + i += inType->size - 1; + } + } + else // bytes and other stuff + { + if (outGPRs != NULL && inStruct != NULL) + outGPRs[destGMarker] = inStruct[srcMarker]; + + srcMarker++; + destGMarker++; + + // Skip to next GPR if next element won't fit and we're + // not already at a register boundary. + if (inType->elements[i + 1] != NULL && (destGMarker % 8)) + { + if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && + (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || + (ALIGN(destGMarker, 8) - destGMarker) < 2) && + (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || + (ALIGN(destGMarker, 8) - destGMarker) < 4)) + destGMarker = ALIGN(destGMarker, inType->alignment); // was 8 + } + } + + break; + + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + srcMarker = ALIGN(srcMarker, 2); + destGMarker = ALIGN(destGMarker, 2); + + if (outGPRs != NULL && inStruct != NULL) + *(short*)&outGPRs[destGMarker] = + *(short*)&inStruct[srcMarker]; + + srcMarker += 2; + destGMarker += 2; + + if (inType->elements[i + 1] == NULL) + destGMarker = ALIGN(destGMarker, inType->alignment); + + break; + + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + srcMarker = ALIGN(srcMarker, 4); + destGMarker = ALIGN(destGMarker, 4); + + if (outGPRs != NULL && inStruct != NULL) + *(int*)&outGPRs[destGMarker] = + *(int*)&inStruct[srcMarker]; + + srcMarker += 4; + destGMarker += 4; + + break; + + case FFI_TYPE_POINTER: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + srcMarker = ALIGN(srcMarker, 8); + destGMarker = ALIGN(destGMarker, 8); + + if (outGPRs != NULL && inStruct != NULL) + *(long long*)&outGPRs[destGMarker] = + *(long long*)&inStruct[srcMarker]; + + srcMarker += 8; + destGMarker += 8; + + if (inType->elements[i + 1] == NULL) + destGMarker = ALIGN(destGMarker, inType->alignment); + + break; + + case FFI_TYPE_STRUCT: + recurseCount++; + ffi64_struct_to_reg_form(inType->elements[i], + inStruct, &srcMarker, &fprsUsed, outGPRs, + &destGMarker, outFPRs, &destFMarker); + recurseCount--; + break; + + default: + FFI_ASSERT(0); + break; + } + } + + destGMarker = ALIGN(destGMarker, inType->alignment); + + // Take care of the special case for 16-byte structs, but not for + // nested structs. + if (recurseCount == 0 && destGMarker == 16) + { + if (outGPRs != NULL && inStruct != NULL) + *(long double*)&outGPRs[0] = *(long double*)&inStruct[0]; + + destFMarker = savedFMarker; + fprsUsed = savedFPRsUsed; + } + + if (ioStructMarker) + *ioStructMarker = ALIGN(srcMarker, 8); + + if (ioFPRsUsed) + *ioFPRsUsed = fprsUsed; + + if (ioGPRSize) + *ioGPRSize = ALIGN(destGMarker, 8); + + if (ioFPRSize) + *ioFPRSize = ALIGN(destFMarker, 8); } -/* ffi64_stret_needs_ptr +/* ffi64_stret_needs_ptr - Determine whether a returned struct needs a pointer in r3 or can fit - in registers. + Determine whether a returned struct needs a pointer in r3 or can fit + in registers. */ bool ffi64_stret_needs_ptr( - const ffi_type* inType, - unsigned short* ioGPRCount, - unsigned short* ioFPRCount) + const ffi_type* inType, + unsigned short* ioGPRCount, + unsigned short* ioFPRCount) { - // Obvious case first- struct is larger than combined FPR size. - if (inType->size > 14 * 8) - return true; + // Obvious case first- struct is larger than combined FPR size. + if (inType->size > 14 * 8) + return true; - // Now the struct can physically fit in registers, determine if it - // also fits logically. - bool needsPtr = false; - unsigned short gprsUsed = 0; - unsigned short fprsUsed = 0; - size_t i; + // Now the struct can physically fit in registers, determine if it + // also fits logically. + bool needsPtr = false; + unsigned short gprsUsed = 0; + unsigned short fprsUsed = 0; + size_t i; - if (ioGPRCount) - gprsUsed = *ioGPRCount; + if (ioGPRCount) + gprsUsed = *ioGPRCount; - if (ioFPRCount) - fprsUsed = *ioFPRCount; + if (ioFPRCount) + fprsUsed = *ioFPRCount; - for (i = 0; inType->elements[i] != NULL && !needsPtr; i++) - { - switch (inType->elements[i]->type) - { - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - gprsUsed++; - fprsUsed++; + for (i = 0; inType->elements[i] != NULL && !needsPtr; i++) + { + switch (inType->elements[i]->type) + { + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + gprsUsed++; + fprsUsed++; - if (fprsUsed > 13) - needsPtr = true; + if (fprsUsed > 13) + needsPtr = true; - break; + break; - case FFI_TYPE_LONGDOUBLE: - gprsUsed += 2; - fprsUsed += 2; + case FFI_TYPE_LONGDOUBLE: + gprsUsed += 2; + fprsUsed += 2; - if (fprsUsed > 14) - needsPtr = true; + if (fprsUsed > 14) + needsPtr = true; - break; + break; - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - { - gprsUsed++; + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + { + gprsUsed++; - if (gprsUsed > 8) - { - needsPtr = true; - break; - } + if (gprsUsed > 8) + { + needsPtr = true; + break; + } - if (inType->elements[i + 1] == NULL) // last byte in the struct - break; + if (inType->elements[i + 1] == NULL) // last byte in the struct + break; - // Count possible contiguous bytes ahead, up to 8. - unsigned short j; + // Count possible contiguous bytes ahead, up to 8. + unsigned short j; - for (j = 1; j < 8; j++) - { - if (inType->elements[i + j] == NULL || - !FFI_TYPE_1_BYTE(inType->elements[i + j]->type)) - break; - } + for (j = 1; j < 8; j++) + { + if (inType->elements[i + j] == NULL || + !FFI_TYPE_1_BYTE(inType->elements[i + j]->type)) + break; + } - i += j - 1; // allow for i++ before the test condition + i += j - 1; // allow for i++ before the test condition - break; - } + break; + } - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - gprsUsed++; + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_POINTER: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + gprsUsed++; - if (gprsUsed > 8) - needsPtr = true; + if (gprsUsed > 8) + needsPtr = true; - break; + break; - case FFI_TYPE_STRUCT: - needsPtr = ffi64_stret_needs_ptr( - inType->elements[i], &gprsUsed, &fprsUsed); + case FFI_TYPE_STRUCT: + needsPtr = ffi64_stret_needs_ptr( + inType->elements[i], &gprsUsed, &fprsUsed); - break; + break; - default: - FFI_ASSERT(0); - break; - } - } + default: + FFI_ASSERT(0); + break; + } + } - if (ioGPRCount) - *ioGPRCount = gprsUsed; + if (ioGPRCount) + *ioGPRCount = gprsUsed; - if (ioFPRCount) - *ioFPRCount = fprsUsed; + if (ioFPRCount) + *ioFPRCount = fprsUsed; - return needsPtr; + return needsPtr; } -/* ffi64_data_size +/* ffi64_data_size - Calculate the size in bytes of an ffi type. + Calculate the size in bytes of an ffi type. */ unsigned int ffi64_data_size( - const ffi_type* inType) + const ffi_type* inType) { - unsigned int size = 0; - - switch (inType->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - size = 1; - break; - - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - size = 2; - break; - - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_FLOAT: - size = 4; - break; - - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_DOUBLE: - size = 8; - break; - - case FFI_TYPE_LONGDOUBLE: - size = 16; - break; - - case FFI_TYPE_STRUCT: - ffi64_struct_to_reg_form( - inType, NULL, NULL, NULL, NULL, &size, NULL, NULL); - break; - - case FFI_TYPE_VOID: - break; - - default: - FFI_ASSERT(0); - break; - } - - return size; + unsigned int size = 0; + + switch (inType->type) + { + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + size = 1; + break; + + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + size = 2; + break; + + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_FLOAT: + size = 4; + break; + + case FFI_TYPE_POINTER: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + case FFI_TYPE_DOUBLE: + size = 8; + break; + + case FFI_TYPE_LONGDOUBLE: + size = 16; + break; + + case FFI_TYPE_STRUCT: + ffi64_struct_to_reg_form( + inType, NULL, NULL, NULL, NULL, &size, NULL, NULL); + break; + + case FFI_TYPE_VOID: + break; + + default: + FFI_ASSERT(0); + break; + } + + return size; } -#endif /* defined(__ppc64__) */ -#endif /* __ppc__ || __ppc64__ */ +#endif /* defined(__ppc64__) */ +#endif /* __ppc__ || __ppc64__ */ -- cgit v0.12 From 7dedcb46441803444a3bdb0f9773d9d9b10186e9 Mon Sep 17 00:00:00 2001 From: R David Murray Date: Tue, 15 Mar 2011 14:01:18 -0400 Subject: #11555: update doc for 3.x change to as_string mangle_from default. --- Doc/library/email.message.rst | 7 ++++--- Lib/email/message.py | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/email.message.rst b/Doc/library/email.message.rst index f261b9c..d1a12c5 100644 --- a/Doc/library/email.message.rst +++ b/Doc/library/email.message.rst @@ -46,15 +46,16 @@ Here are the methods of the :class:`Message` class: be generated or modified). Note that this method is provided as a convenience and may not always - format the message the way you want. For example, by default it mangles - lines that begin with ``From``. For more flexibility, instantiate a + format the message the way you want. For example, by default it does + not do the mangling of lines that begin with ``From`` that is + required by the unix mbox format. For more flexibility, instantiate a :class:`~email.generator.Generator` instance and use its :meth:`flatten` method directly. For example:: from io import StringIO from email.generator import Generator fp = StringIO() - g = Generator(fp, mangle_from_=False, maxheaderlen=60) + g = Generator(fp, mangle_from_=True, maxheaderlen=60) g.flatten(msg) text = fp.getvalue() diff --git a/Lib/email/message.py b/Lib/email/message.py index 9ef2363..d30f109 100644 --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -136,8 +136,7 @@ class Message: header. This is a convenience method and may not generate the message exactly - as you intend because by default it mangles lines that begin with - "From ". For more flexibility, use the flatten() method of a + as you intend. For more flexibility, use the flatten() method of a Generator instance. """ from email.generator import Generator -- cgit v0.12 From 1f5c958721a1f9329cb23b17cf5e36548855d72f Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Tue, 15 Mar 2011 15:04:44 -0400 Subject: - Issue #11289: `smtp.SMTP` class becomes a context manager so it can be used in a `with` statement. Contributed by Giampaolo Rodola. --- Doc/library/smtplib.rst | 14 ++++++++++++++ Lib/smtplib.py | 13 +++++++++++++ Lib/test/test_smtplib.py | 38 ++++++++++++++++++++++++++++++++++++-- Misc/NEWS | 3 +++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index 531a64d..4805c8e 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -34,6 +34,20 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions). For normal use, you should only require the initialization/connect, :meth:`sendmail`, and :meth:`quit` methods. An example is included below. + The :class:`SMTP` class supports the :keyword:`with` statement. When used + like this, the SMTP ``QUIT`` command is issued automatically when the + :keyword:`with` statement exits. E.g.:: + + >>> from smtplib import SMTP + >>> with SMTP("domain.org") as smtp: + ... smtp.noop() + ... + (250, b'Ok') + >>> + + .. versionadded:: 3.3 + Support for the :keyword:`with` statement was added. + .. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None[, timeout]) diff --git a/Lib/smtplib.py b/Lib/smtplib.py index 14e6250..213138c 100755 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -269,6 +269,19 @@ class SMTP: pass self.local_hostname = '[%s]' % addr + def __enter__(self): + return self + + def __exit__(self, *args): + try: + code, message = self.docmd("QUIT") + if code != 221: + raise SMTPResponseException(code, message) + except SMTPServerDisconnected: + pass + finally: + self.close() + def set_debuglevel(self, debuglevel): """Set the debug output level. diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index 4651f37..d973faa 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -424,6 +424,9 @@ sim_lists = {'list-1':['Mr.A@somewhere.com','Mrs.C@somewhereesle.com'], # Simulated SMTP channel & server class SimSMTPChannel(smtpd.SMTPChannel): + # For testing failures in QUIT when using the context manager API. + quit_response = None + def __init__(self, extra_features, *args, **kw): self._extrafeatures = ''.join( [ "250-{0}\r\n".format(x) for x in extra_features ]) @@ -475,19 +478,31 @@ class SimSMTPChannel(smtpd.SMTPChannel): else: self.push('550 No access for you!') + def smtp_QUIT(self, arg): + # args is ignored + if self.quit_response is None: + super(SimSMTPChannel, self).smtp_QUIT(arg) + else: + self.push(self.quit_response) + self.close_when_done() + def handle_error(self): raise class SimSMTPServer(smtpd.SMTPServer): + # For testing failures in QUIT when using the context manager API. + quit_response = None + def __init__(self, *args, **kw): self._extra_features = [] smtpd.SMTPServer.__init__(self, *args, **kw) def handle_accepted(self, conn, addr): - self._SMTPchannel = SimSMTPChannel(self._extra_features, - self, conn, addr) + self._SMTPchannel = SimSMTPChannel( + self._extra_features, self, conn, addr) + self._SMTPchannel.quit_response = self.quit_response def process_message(self, peer, mailfrom, rcpttos, data): pass @@ -620,6 +635,25 @@ class SMTPSimTests(unittest.TestCase): self.assertIn(sim_auth_credentials['cram-md5'], str(err)) smtp.close() + def test_with_statement(self): + with smtplib.SMTP(HOST, self.port) as smtp: + code, message = smtp.noop() + self.assertEqual(code, 250) + self.assertRaises(smtplib.SMTPServerDisconnected, smtp.send, b'foo') + with smtplib.SMTP(HOST, self.port) as smtp: + smtp.close() + self.assertRaises(smtplib.SMTPServerDisconnected, smtp.send, b'foo') + + def test_with_statement_QUIT_failure(self): + self.serv.quit_response = '421 QUIT FAILED' + with self.assertRaises(smtplib.SMTPResponseException) as error: + with smtplib.SMTP(HOST, self.port) as smtp: + smtp.noop() + self.assertEqual(error.exception.smtp_code, 421) + self.assertEqual(error.exception.smtp_error, b'QUIT FAILED') + # We don't need to clean up self.serv.quit_response because a new + # server is always instantiated in the setUp(). + #TODO: add tests for correct AUTH method fallback now that the #test infrastructure can support it. diff --git a/Misc/NEWS b/Misc/NEWS index 834fa46..90e402b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -68,6 +68,9 @@ Core and Builtins Library ------- +- Issue #11289: `smtp.SMTP` class becomes a context manager so it can be used + in a `with` statement. Contributed by Giampaolo Rodola. + - Issue #11407: `TestCase.run` returns the result object used or created. Contributed by Janathan Hartley. -- cgit v0.12 From 9bb9877d8079ccfc4f5b5448ba111392140112e4 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 15 Mar 2011 20:22:50 +0100 Subject: Followup to 4c59cd84086f: add an entry in the porting guide and a "versionchanged" attribute. --- Doc/c-api/init.rst | 5 +++-- Doc/whatsnew/3.2.rst | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 2641c8b..623bd7c 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -537,10 +537,11 @@ code, or when embedding the Python interpreter: operations such as ``PyEval_ReleaseThread(tstate)``. It is not needed before calling :c:func:`PyEval_SaveThread` or :c:func:`PyEval_RestoreThread`. - .. index:: single: Py_Initialize() - This is a no-op when called for a second time. + .. versionchanged:: 3.2 + This function cannot be called before :c:func:`Py_Initialize()` anymore. + .. index:: module: _thread .. note:: diff --git a/Doc/whatsnew/3.2.rst b/Doc/whatsnew/3.2.rst index 3829ce1..20ce228 100644 --- a/Doc/whatsnew/3.2.rst +++ b/Doc/whatsnew/3.2.rst @@ -2698,3 +2698,7 @@ require changes to your code: a new function, :func:`asyncore.handle_accepted`, was added to replace it. (Contributed by Giampaolo Rodola in :issue:`6706`.) + +* Due to the new :term:`GIL` implementation, :c:func:`PyEval_InitThreads()` + cannot be called before :c:func:`Py_Initialize()` anymore. + -- cgit v0.12