ffi.c (ffi_call): Handle small structures correctly.
authorKaz Kojima <kkojima@gcc.gnu.org>
Wed, 20 Jul 2005 23:32:01 +0000 (23:32 +0000)
committerKaz Kojima <kkojima@gcc.gnu.org>
Wed, 20 Jul 2005 23:32:01 +0000 (23:32 +0000)
* src/sh/ffi.c (ffi_call): Handle small structures correctly.
Remove empty line.
* src/sh64/ffi.c (simple_type): Remove.
(return_type): Handle small structures correctly.
(ffi_prep_args): Likewise.
(ffi_call): Likewise.
(ffi_closure_helper_SYSV): Likewise.
* src/sh64/sysv.S (ffi_call_SYSV): Handle 1, 2 and 4-byte return.
Emit position independent code if PIC and remove wrong datalabel
prefixes from EH data.

From-SVN: r102210

libffi/ChangeLog
libffi/src/sh/ffi.c
libffi/src/sh64/ffi.c
libffi/src/sh64/sysv.S

index 00bd80c..bd6a638 100644 (file)
@@ -1,3 +1,16 @@
+2005-07-20  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * src/sh/ffi.c (ffi_call): Handle small structures correctly.
+       Remove empty line.
+       * src/sh64/ffi.c (simple_type): Remove.
+       (return_type): Handle small structures correctly.
+       (ffi_prep_args): Likewise.
+       (ffi_call): Likewise.
+       (ffi_closure_helper_SYSV): Likewise.
+       * src/sh64/sysv.S (ffi_call_SYSV): Handle 1, 2 and 4-byte return.
+       Emit position independent code if PIC and remove wrong datalabel
+       prefixes from EH data.
+
 2005-07-19  Andreas Tobler  <a.tobler@schweiz.ch>
 
        * Makefile.am (nodist_libffi_la_SOURCES): Add POWERPC_FREEBSD.
index 2045419..ddf562f 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   ffi.c - Copyright (c) 2002, 2003, 2004 Kaz Kojima
+   ffi.c - Copyright (c) 2002, 2003, 2004, 2005 Kaz Kojima
    
    SuperH Foreign Function Interface 
 
@@ -427,6 +427,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
              /*@dependent@*/ void **avalue)
 {
   extended_cif ecif;
+  UINT64 trvalue;
 
   ecif.cif = cif;
   ecif.avalue = avalue;
@@ -434,7 +435,10 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
   /* 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) && 
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    ecif.rvalue = &trvalue;
+  else if ((rvalue == NULL) && 
       (cif->rtype->type == FFI_TYPE_STRUCT))
     {
       /*@-sysunrecog@*/
@@ -443,7 +447,6 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
     }
   else
     ecif.rvalue = rvalue;
-    
 
   switch (cif->abi) 
     {
@@ -457,6 +460,11 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
       FFI_ASSERT(0);
       break;
     }
+
+  if (rvalue
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    memcpy (rvalue, &trvalue, cif->rtype->size);
 }
 
 extern void ffi_closure_SYSV (void);
index 7709603..abf3f0d 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   ffi.c - Copyright (c) 2003 Kaz Kojima
+   ffi.c - Copyright (c) 2003, 2004 Kaz Kojima
    
    SuperH SHmedia Foreign Function Interface 
 
 #define NGREGARG 8
 #define NFREGARG 12
 
-/* If the structure has essentialy an unique element, return its type.  */
-static int
-simple_type (ffi_type *arg)
-{
-  if (arg->type != FFI_TYPE_STRUCT)
-    return arg->type;
-  else if (arg->elements[1])
-    return FFI_TYPE_STRUCT;
-
-  return simple_type (arg->elements[0]);
-}
-
 static int
 return_type (ffi_type *arg)
 {
-  unsigned short type;
 
   if (arg->type != FFI_TYPE_STRUCT)
     return arg->type;
 
-  type = simple_type (arg->elements[0]);
-  if (! arg->elements[1])
-    {
-      switch (type)
-       {
-       case FFI_TYPE_SINT8:
-       case FFI_TYPE_UINT8:
-       case FFI_TYPE_SINT16:
-       case FFI_TYPE_UINT16:
-       case FFI_TYPE_SINT32:
-       case FFI_TYPE_UINT32:
-       case FFI_TYPE_SINT64:
-       case FFI_TYPE_UINT64:
-         return FFI_TYPE_UINT64;
-
-       default:
-         return type;
-       }
-    }
-
   /* gcc uses r2 if the result can be packed in on register.  */
-  if (arg->size <= sizeof (UINT64))
+  if (arg->size <= sizeof (UINT8))
+    return FFI_TYPE_UINT8;
+  else if (arg->size <= sizeof (UINT16))
+    return FFI_TYPE_UINT16;
+  else if (arg->size <= sizeof (UINT32))
+    return FFI_TYPE_UINT32;
+  else if (arg->size <= sizeof (UINT64))
     return FFI_TYPE_UINT64;
 
   return FFI_TYPE_STRUCT;
@@ -105,8 +78,10 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
   for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
     {
       size_t z;
+      int align;
 
       z = (*p_arg)->size;
+      align = (*p_arg)->alignment;
       if (z < sizeof (UINT32))
        {
          switch ((*p_arg)->type)
@@ -128,7 +103,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
              break;
   
            case FFI_TYPE_STRUCT:
-             *(UINT64 *) argp = (UINT64) *(UINT32 *)(*p_argv);
+             memcpy (argp, *p_argv, z);
              break;
 
            default:
@@ -136,12 +111,31 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
            }
          argp += sizeof (UINT64);
        }
-      else if (z == sizeof (UINT32))
+      else if (z == sizeof (UINT32) && align == sizeof (UINT32))
        {
-         *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
+         switch ((*p_arg)->type)
+           {
+           case FFI_TYPE_INT:
+           case FFI_TYPE_SINT32:
+             *(SINT64 *) argp = (SINT64) *(SINT32 *) (*p_argv);
+             break;
+
+           case FFI_TYPE_FLOAT:
+           case FFI_TYPE_POINTER:
+           case FFI_TYPE_UINT32:
+           case FFI_TYPE_STRUCT:
+             *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
+             break;
+
+           default:
+             FFI_ASSERT(0);
+             break;
+           }
          argp += sizeof (UINT64);
        }
-      else if (z == sizeof (UINT64))
+      else if (z == sizeof (UINT64)
+              && align == sizeof (UINT64)
+              && ((int) *p_argv & (sizeof (UINT64) - 1)) == 0)
        {
          *(UINT64 *) argp = *(UINT64 *) (*p_argv);
          argp += sizeof (UINT64);
@@ -254,6 +248,7 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
              /*@dependent@*/ void **avalue)
 {
   extended_cif ecif;
+  UINT64 trvalue;
 
   ecif.cif = cif;
   ecif.avalue = avalue;
@@ -261,7 +256,10 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
   /* 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) && 
+  if (cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    ecif.rvalue = &trvalue;
+  else if ((rvalue == NULL) && 
       (cif->rtype->type == FFI_TYPE_STRUCT))
     {
       /*@-sysunrecog@*/
@@ -283,6 +281,11 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
       FFI_ASSERT(0);
       break;
     }
+
+  if (rvalue
+      && cif->rtype->type == FFI_TYPE_STRUCT
+      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
+    memcpy (rvalue, &trvalue, cif->rtype->size);
 }
 
 extern void ffi_closure_SYSV (void);
@@ -353,7 +356,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
 
   /* Copy the caller's structure return value address so that the closure
      returns the data directly to the caller.  */
-  if (cif->rtype->type == FFI_TYPE_STRUCT)
+  if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
     {
       rvalue = *pgr;
       greg = 1;
@@ -443,6 +446,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
   (closure->fun) (cif, rvalue, avalue, closure->user_data);
 
   /* Tell ffi_closure_SYSV how to perform return type promotions.  */
-  return cif->rtype->type;
+  return return_type (cif->rtype);
 }
 
index 949f69f..19f1b51 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   sysv.S - Copyright (c) 2003 Kaz Kojima
+   sysv.S - Copyright (c) 2003, 2004 Kaz Kojima
    
    SuperH SHmedia Foreign Function Interface 
 
@@ -64,8 +64,9 @@ ENTRY(ffi_call_SYSV)
        st.q    r15, 8, r28
        st.l    r15, 4, r18
        st.l    r15, 0, r14
-       add.l   r15, r63, r14
 .LCFI1:
+       add.l   r15, r63, r14
+.LCFI2:
 #      add     r4, r63, r28
        add     r5, r63, r29
        add     r6, r63, r30
@@ -252,10 +253,17 @@ ENTRY(ffi_call_SYSV)
        pt/l    .L_epilogue, tr4
 
        beqi/l  r29, FFI_TYPE_INT, tr0
+       beqi/l  r29, FFI_TYPE_UINT32, tr0
        beqi/l  r29, FFI_TYPE_SINT64, tr1
        beqi/l  r29, FFI_TYPE_UINT64, tr1
        beqi/l  r29, FFI_TYPE_DOUBLE, tr2
        beqi/l  r29, FFI_TYPE_FLOAT, tr3
+
+       pt/l    .L_ret_q, tr0
+       pt/l    .L_ret_h, tr1
+
+       beqi/l  r29, FFI_TYPE_UINT8, tr0
+       beqi/l  r29, FFI_TYPE_UINT16, tr1
        blink   tr4, r63
 
 .L_ret_d:
@@ -270,6 +278,14 @@ ENTRY(ffi_call_SYSV)
        fst.s   r31, OFS_FLT, fr0
        blink   tr4, r63
 
+.L_ret_q:
+       st.b    r31, 0, r2
+       blink   tr4, r63
+
+.L_ret_h:
+       st.w    r31, 0, r2
+       blink   tr4, r63
+
 .L_ret_i:
        st.l    r31, 0, r2
        # Fall
@@ -297,12 +313,13 @@ ENTRY(ffi_call_SYSV)
 ENTRY(ffi_closure_SYSV)
 .LFB2:
        addi.l  r15, -136, r15
-.LCFI2:
+.LCFI3:
        st.l    r15, 12, r18
        st.l    r15, 8, r14
        st.l    r15, 4, r12
+.LCFI4:
        add     r15, r63, r14
-.LCFI3:
+.LCFI5:
        /* Stack layout:        
           ...
           64 bytes (register parameters)
@@ -418,12 +435,18 @@ __FRAME_BEGIN__:
 .LSCIE1:
        .4byte  0x0     /* CIE Identifier Tag */
        .byte   0x1     /* CIE Version */
+#ifdef PIC
        .ascii "zR\0"   /* CIE Augmentation */
+#else
+       .byte   0x0     /* CIE Augmentation */
+#endif
        .uleb128 0x1    /* CIE Code Alignment Factor */
        .sleb128 -4     /* CIE Data Alignment Factor */
        .byte   0x12    /* CIE RA Column */
+#ifdef PIC
        .uleb128 0x1    /* Augmentation size */
-       .byte   0x1b    /* FDE Encoding (pcrel sdata4) */
+       .byte   0x10    /* FDE Encoding (pcrel) */
+#endif
        .byte   0xc     /* DW_CFA_def_cfa */
        .uleb128 0xf
        .uleb128 0x0
@@ -433,8 +456,15 @@ __FRAME_BEGIN__:
        .4byte  datalabel .LEFDE1-datalabel .LASFDE1    /* FDE Length */
 .LASFDE1:
        .4byte  datalabel .LASFDE1-datalabel __FRAME_BEGIN__
-       .4byte  datalabel .LFB1-.               /* FDE initial location */
+#ifdef PIC
+       .4byte  .LFB1-. /* FDE initial location */
+#else
+       .4byte  .LFB1   /* FDE initial location */
+#endif
        .4byte  datalabel .LFE1-datalabel .LFB1 /* FDE address range */
+#ifdef PIC
+       .uleb128 0x0    /* Augmentation size */
+#endif
        .byte   0x4     /* DW_CFA_advance_loc4 */
        .4byte  datalabel .LCFI0-datalabel .LFB1
        .byte   0xe     /* DW_CFA_def_cfa_offset */
@@ -455,6 +485,8 @@ __FRAME_BEGIN__:
        .uleb128 0x4
        .byte   0xa0    /* DW_CFA_offset, column 0x20 */
        .uleb128 0x2
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI2-datalabel .LCFI1
        .byte   0xd     /* DW_CFA_def_cfa_register */
        .uleb128 0xe
        .align  2
@@ -464,20 +496,29 @@ __FRAME_BEGIN__:
        .4byte  datalabel .LEFDE3-datalabel .LASFDE3    /* FDE Length */
 .LASFDE3:
        .4byte  datalabel .LASFDE3-datalabel __FRAME_BEGIN__
-       .4byte  datalabel .LFB2-.               /* FDE initial location */
+#ifdef PIC
+       .4byte  .LFB2-. /* FDE initial location */
+#else
+       .4byte  .LFB2   /* FDE initial location */
+#endif
        .4byte  datalabel .LFE2-datalabel .LFB2 /* FDE address range */
+#ifdef PIC
+       .uleb128 0x0    /* Augmentation size */
+#endif
        .byte   0x4     /* DW_CFA_advance_loc4 */
-       .4byte  datalabel .LCFI2-datalabel .LFB2
+       .4byte  datalabel .LCFI3-datalabel .LFB2
        .byte   0xe     /* DW_CFA_def_cfa_offset */
        .uleb128 0x88
        .byte   0x4     /* DW_CFA_advance_loc4 */
-       .4byte  datalabel .LCFI3-datalabel .LCFI2
+       .4byte  datalabel .LCFI4-datalabel .LCFI3
        .byte   0x8c    /* DW_CFA_offset, column 0xc */
        .uleb128 0x21
        .byte   0x8e    /* DW_CFA_offset, column 0xe */
        .uleb128 0x20
        .byte   0x92    /* DW_CFA_offset, column 0x12 */
        .uleb128 0x1f
+       .byte   0x4     /* DW_CFA_advance_loc4 */
+       .4byte  datalabel .LCFI5-datalabel .LCFI4
        .byte   0xd     /* DW_CFA_def_cfa_register */
        .uleb128 0xe
        .align  2