Merge pull request #231 from berkerpeksag/simplfy-oserror
authorTom Tromey <tom@tromey.com>
Tue, 3 May 2016 14:23:51 +0000 (08:23 -0600)
committerTom Tromey <tom@tromey.com>
Tue, 3 May 2016 14:23:51 +0000 (08:23 -0600)
Simplify error handling in mkdir_p()

doc/libffi.texi
include/ffi.h.in
src/aarch64/ffitarget.h
src/prep_cif.c
src/x86/ffiw64.c
src/x86/win64.S
testsuite/lib/libffi.exp
testsuite/libffi.call/ffitest.h
testsuite/libffi.call/offsets.c [new file with mode: 0644]

index 5c9fddd..94b7a9e 100644 (file)
@@ -440,7 +440,8 @@ on the chosen ABI.
 
 @item
 The size and alignment of a new structure type will not be set by
-@code{libffi} until it has been passed to @code{ffi_prep_cif}.
+@code{libffi} until it has been passed to @code{ffi_prep_cif} or
+@code{ffi_get_struct_offsets}.
 
 @item
 A structure type cannot be shared across ABIs.  Instead each ABI needs
@@ -448,8 +449,9 @@ its own copy of the structure type.
 @end itemize
 
 So, before examining these fields, it is safest to pass the
-@code{ffi_type} object to @code{ffi_prep_cif} first.  This function
-will do all the needed setup.
+@code{ffi_type} object to @code{ffi_prep_cif} or
+@code{ffi_get_struct_offsets} first.  This function will do all the
+needed setup.
 
 @example
 ffi_type *desired_type;
@@ -463,6 +465,28 @@ if (ffi_prep_cif (&cif, desired_abi, 0, desired_type, NULL) == FFI_OK)
   @}
 @end example
 
+@code{libffi} also provides a way to get the offsets of the members of
+a structure.
+
+@findex ffi_get_struct_offsets
+@defun ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets)
+Compute the offset of each element of the given structure type.
+@var{abi} is the ABI to use; this is needed because in some cases the
+layout depends on the ABI.
+
+@var{sizes} is an out parameter.  The caller is responsible for
+providing enough space for all the results to be written -- one
+element per element type in @var{struct_type}.  If @var{sizes} is
+@code{NULL}, then the type will be laid out but not otherwise
+modified.  This can be useful for accessing the type's size or layout,
+as mentioned above.
+
+This function returns @code{FFI_OK} on success; @code{FFI_BAD_ABI} if
+@var{abi} is invalid; or @code{FFI_BAD_TYPEDEF} if @var{struct_type}
+is invalid in some way.  Note that only @code{FFI_STRUCT} types are
+valid here.
+@end defun
+
 @node Arrays Unions Enums
 @subsection Arrays, Unions, and Enumerations
 
index cd3358f..9e65277 100644 (file)
@@ -458,6 +458,9 @@ void ffi_call(ffi_cif *cif,
              void *rvalue,
              void **avalue);
 
+ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
+                                  size_t *offsets);
+
 /* Useful for eliminating compiler warnings */
 #define FFI_FN(f) ((void (*)(void))f)
 
index 5ded0e4..65086cd 100644 (file)
@@ -29,6 +29,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #ifndef LIBFFI_ASM
 #ifdef __ILP32__
 #define FFI_SIZEOF_ARG 8
+#define FFI_SIZEOF_JAVA_RAW  4
 typedef unsigned long long ffi_arg;
 typedef signed long long ffi_sarg;
 #else
index 5881ceb..43f0487 100644 (file)
@@ -34,7 +34,7 @@
 /* Perform machine independent initialization of aggregate type
    specifications. */
 
-static ffi_status initialize_aggregate(ffi_type *arg)
+static ffi_status initialize_aggregate(ffi_type *arg, size_t *offsets)
 {
   ffi_type **ptr;
 
@@ -52,13 +52,15 @@ static ffi_status initialize_aggregate(ffi_type *arg)
   while ((*ptr) != NULL)
     {
       if (UNLIKELY(((*ptr)->size == 0)
-                   && (initialize_aggregate((*ptr)) != FFI_OK)))
+                   && (initialize_aggregate((*ptr), NULL) != FFI_OK)))
        return FFI_BAD_TYPEDEF;
 
       /* Perform a sanity check on the argument type */
       FFI_ASSERT_VALID_TYPE(*ptr);
 
       arg->size = ALIGN(arg->size, (*ptr)->alignment);
+      if (offsets)
+       *offsets++ = arg->size;
       arg->size += (*ptr)->size;
 
       arg->alignment = (arg->alignment > (*ptr)->alignment) ?
@@ -133,7 +135,8 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
 #endif
 
   /* Initialize the return type if necessary */
-  if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
+  if ((cif->rtype->size == 0)
+      && (initialize_aggregate(cif->rtype, NULL) != FFI_OK))
     return FFI_BAD_TYPEDEF;
 
 #ifndef FFI_TARGET_HAS_COMPLEX_TYPE
@@ -164,7 +167,8 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
     {
 
       /* Initialize any uninitialized aggregate type definitions */
-      if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
+      if (((*ptr)->size == 0)
+         && (initialize_aggregate((*ptr), NULL) != FFI_OK))
        return FFI_BAD_TYPEDEF;
 
 #ifndef FFI_TARGET_HAS_COMPLEX_TYPE
@@ -240,3 +244,18 @@ ffi_prep_closure (ffi_closure* closure,
 }
 
 #endif
+
+ffi_status
+ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets)
+{
+  if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
+    return FFI_BAD_ABI;
+  if (struct_type->type != FFI_TYPE_STRUCT)
+    return FFI_BAD_TYPEDEF;
+
+#if HAVE_LONG_DOUBLE_VARIANT
+  ffi_prep_types (abi);
+#endif
+
+  return initialize_aggregate(struct_type, offsets);
+}
index 0029be0..fd47c58 100644 (file)
@@ -231,7 +231,11 @@ struct win64_closure_frame
   UINT64 args[];
 };
 
-int FFI_HIDDEN
+/* Force the inner function to use the MS ABI.  When compiling on win64
+   this is a nop.  When compiling on unix, this simplifies the assembly,
+   and places the burden of saving the extra call-saved registers on
+   the compiler.  */
+int FFI_HIDDEN __attribute__((ms_abi))
 ffi_closure_win64_inner(ffi_cif *cif,
                        void (*fun)(ffi_cif*, void*, void**, void*),
                        void *user_data,
index 9d4f8b9..1f82a3e 100644 (file)
 #define arg3   %rcx
 #endif
 
-.macro E which
-       .align  8
-       .org    0b + \which * 8
-.endm
+/* This macro allows the safe creation of jump tables without an
+   actual table.  The entry points into the table are all 8 bytes.
+   The use of ORG asserts that we're at the correct location.  */
+/* ??? The clang assembler doesn't handle .org with symbolic expressions.  */
+#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__))
+# define E(BASE, X)    .balign 8
+#else
+# define E(BASE, X)    .balign 8; .org BASE + X * 8
+#endif
 
        .text
 
@@ -88,62 +93,62 @@ ffi_call_win64:
 
        .align  8
 0:
-E FFI_TYPE_VOID
+E(0b, FFI_TYPE_VOID)
        epilogue
-E FFI_TYPE_INT
+E(0b, FFI_TYPE_INT)
        movslq  %eax, %rax
        movq    %rax, (%r8)
        epilogue
-E FFI_TYPE_FLOAT
+E(0b, FFI_TYPE_FLOAT)
        movss   %xmm0, (%r8)
        epilogue
-E FFI_TYPE_DOUBLE
+E(0b, FFI_TYPE_DOUBLE)
        movsd   %xmm0, (%r8)
        epilogue
-E FFI_TYPE_LONGDOUBLE
+E(0b, FFI_TYPE_LONGDOUBLE)
        call    PLT(C(abort))
-E FFI_TYPE_UINT8
+E(0b, FFI_TYPE_UINT8)
        movzbl  %al, %eax
        movq    %rax, (%r8)
        epilogue
-E FFI_TYPE_SINT8
+E(0b, FFI_TYPE_SINT8)
        movsbq  %al, %rax
        jmp     98f
-E FFI_TYPE_UINT16
+E(0b, FFI_TYPE_UINT16)
        movzwl  %ax, %eax
        movq    %rax, (%r8)
        epilogue
-E FFI_TYPE_SINT16
+E(0b, FFI_TYPE_SINT16)
        movswq  %ax, %rax
        jmp     98f
-E FFI_TYPE_UINT32
+E(0b, FFI_TYPE_UINT32)
        movl    %eax, %eax
        movq    %rax, (%r8)
        epilogue
-E FFI_TYPE_SINT32
+E(0b, FFI_TYPE_SINT32)
        movslq  %eax, %rax
        movq    %rax, (%r8)
        epilogue
-E FFI_TYPE_UINT64
+E(0b, FFI_TYPE_UINT64)
 98:    movq    %rax, (%r8)
        epilogue
-E FFI_TYPE_SINT64
+E(0b, FFI_TYPE_SINT64)
        movq    %rax, (%r8)
        epilogue
-E FFI_TYPE_STRUCT
+E(0b, FFI_TYPE_STRUCT)
        epilogue
-E FFI_TYPE_POINTER
+E(0b, FFI_TYPE_POINTER)
        movq    %rax, (%r8)
        epilogue
-E FFI_TYPE_COMPLEX
+E(0b, FFI_TYPE_COMPLEX)
        call    PLT(C(abort))
-E FFI_TYPE_SMALL_STRUCT_1B
+E(0b, FFI_TYPE_SMALL_STRUCT_1B)
        movb    %al, (%r8)
        epilogue
-E FFI_TYPE_SMALL_STRUCT_2B
+E(0b, FFI_TYPE_SMALL_STRUCT_2B)
        movw    %ax, (%r8)
        epilogue
-E FFI_TYPE_SMALL_STRUCT_4B
+E(0b, FFI_TYPE_SMALL_STRUCT_4B)
        movl    %eax, (%r8)
        epilogue
 
@@ -174,9 +179,9 @@ ffi_go_closure_win64:
        movq    %r8, 24(%rsp)
        movq    %r9, 32(%rsp)
 
-       movq    8(%r10), arg0                   /* load cif */
-       movq    16(%r10), arg1                  /* load fun */
-       movq    %r10, arg2                      /* closure is user_data */
+       movq    8(%r10), %rcx                   /* load cif */
+       movq    16(%r10), %rdx                  /* load fun */
+       movq    %r10, %r8                       /* closure is user_data */
        jmp     0f
        cfi_endproc
        SEH(.seh_endproc)
@@ -193,9 +198,9 @@ ffi_closure_win64:
        movq    %r8, 24(%rsp)
        movq    %r9, 32(%rsp)
 
-       movq    FFI_TRAMPOLINE_SIZE(%r10), arg0         /* load cif */
-       movq    FFI_TRAMPOLINE_SIZE+8(%r10), arg1       /* load fun */
-       movq    FFI_TRAMPOLINE_SIZE+16(%r10), arg2      /* load user_data */
+       movq    FFI_TRAMPOLINE_SIZE(%r10), %rcx         /* load cif */
+       movq    FFI_TRAMPOLINE_SIZE+8(%r10), %rdx       /* load fun */
+       movq    FFI_TRAMPOLINE_SIZE+16(%r10), %r8       /* load user_data */
 0:
        subq    $ffi_clo_FS, %rsp
        cfi_adjust_cfa_offset(ffi_clo_FS)
@@ -208,7 +213,7 @@ ffi_closure_win64:
        movsd   %xmm2, ffi_clo_OFF_X+16(%rsp)
        movsd   %xmm3, ffi_clo_OFF_X+24(%rsp)
 
-       leaq    ffi_clo_OFF_R(%rsp), arg3
+       leaq    ffi_clo_OFF_R(%rsp), %r9
        call    ffi_closure_win64_inner
 
        /* Load the result into both possible result registers.  */
index 0d74627..6d19393 100644 (file)
@@ -315,6 +315,11 @@ proc run-many-tests { testcases extra_flags } {
                 "-DABI_NUM=FFI_THISCALL -DABI_ATTR=__THISCALL__"
                 "-DABI_NUM=FFI_FASTCALL -DABI_ATTR=__FASTCALL__"
             }
+        } elseif [istarget "x86_64-*-*"] {
+            set targetabis {
+                ""
+                "-DABI_NUM=FFI_WIN64 -DABI_ATTR=__MSABI__"
+            }
         }
     }
 
index 15d5e44..5e19451 100644 (file)
@@ -24,6 +24,7 @@
 #define __STDCALL__ __attribute__((stdcall))
 #define __THISCALL__ __attribute__((thiscall))
 #define __FASTCALL__ __attribute__((fastcall))
+#define __MSABI__ __attribute__((ms_abi))
 #else
 #define __UNUSED__
 #define __STDCALL__ __stdcall
diff --git a/testsuite/libffi.call/offsets.c b/testsuite/libffi.call/offsets.c
new file mode 100644 (file)
index 0000000..23d88b3
--- /dev/null
@@ -0,0 +1,46 @@
+/* Area:               Struct layout
+   Purpose:            Test ffi_get_struct_offsets
+   Limitations:                none.
+   PR:                 none.
+   Originator:                 Tom Tromey. */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include <stddef.h>
+
+struct test_1
+{
+  char c;
+  float f;
+  char c2;
+  int i;
+};
+
+int
+main (void)
+{
+  ffi_type test_1_type;
+  ffi_type *test_1_elements[5];
+  size_t test_1_offsets[4];
+
+  test_1_elements[0] = &ffi_type_schar;
+  test_1_elements[1] = &ffi_type_float;
+  test_1_elements[2] = &ffi_type_schar;
+  test_1_elements[3] = &ffi_type_sint;
+  test_1_elements[4] = NULL;
+
+  test_1_type.size = 0;
+  test_1_type.alignment = 0;
+  test_1_type.type = FFI_TYPE_STRUCT;
+  test_1_type.elements = test_1_elements;
+
+  CHECK (ffi_get_struct_offsets (FFI_DEFAULT_ABI, &test_1_type, test_1_offsets)
+        == FFI_OK);
+  CHECK (test_1_type.size == sizeof (struct test_1));
+  CHECK (offsetof (struct test_1, c) == test_1_offsets[0]);
+  CHECK (offsetof (struct test_1, f) == test_1_offsets[1]);
+  CHECK (offsetof (struct test_1, c2) == test_1_offsets[2]);
+  CHECK (offsetof (struct test_1, i) == test_1_offsets[3]);
+
+  return 0;
+}