(root)/
gcc-13.2.0/
libffi/
src/
prep_cif.c
       1  /* -----------------------------------------------------------------------
       2     prep_cif.c - Copyright (c) 2011, 2012, 2021  Anthony Green
       3                  Copyright (c) 1996, 1998, 2007  Red Hat, Inc.
       4  
       5     Permission is hereby granted, free of charge, to any person obtaining
       6     a copy of this software and associated documentation files (the
       7     ``Software''), to deal in the Software without restriction, including
       8     without limitation the rights to use, copy, modify, merge, publish,
       9     distribute, sublicense, and/or sell copies of the Software, and to
      10     permit persons to whom the Software is furnished to do so, subject to
      11     the following conditions:
      12  
      13     The above copyright notice and this permission notice shall be included
      14     in all copies or substantial portions of the Software.
      15  
      16     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
      17     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      18     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      19     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
      20     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      21     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      22     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      23     DEALINGS IN THE SOFTWARE.
      24     ----------------------------------------------------------------------- */
      25  
      26  #include <ffi.h>
      27  #include <ffi_common.h>
      28  #include <stdlib.h>
      29  
      30  /* Round up to FFI_SIZEOF_ARG. */
      31  
      32  #define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG)
      33  
      34  /* Perform machine independent initialization of aggregate type
      35     specifications. */
      36  
      37  static ffi_status initialize_aggregate(ffi_type *arg, size_t *offsets)
      38  {
      39    ffi_type **ptr;
      40  
      41    if (UNLIKELY(arg == NULL || arg->elements == NULL))
      42      return FFI_BAD_TYPEDEF;
      43  
      44    arg->size = 0;
      45    arg->alignment = 0;
      46  
      47    ptr = &(arg->elements[0]);
      48  
      49    if (UNLIKELY(ptr == 0))
      50      return FFI_BAD_TYPEDEF;
      51  
      52    while ((*ptr) != NULL)
      53      {
      54        if (UNLIKELY(((*ptr)->size == 0)
      55  		    && (initialize_aggregate((*ptr), NULL) != FFI_OK)))
      56  	return FFI_BAD_TYPEDEF;
      57  
      58        /* Perform a sanity check on the argument type */
      59        FFI_ASSERT_VALID_TYPE(*ptr);
      60  
      61        arg->size = FFI_ALIGN(arg->size, (*ptr)->alignment);
      62        if (offsets)
      63  	*offsets++ = arg->size;
      64        arg->size += (*ptr)->size;
      65  
      66        arg->alignment = (arg->alignment > (*ptr)->alignment) ?
      67  	arg->alignment : (*ptr)->alignment;
      68  
      69        ptr++;
      70      }
      71  
      72    /* Structure size includes tail padding.  This is important for
      73       structures that fit in one register on ABIs like the PowerPC64
      74       Linux ABI that right justify small structs in a register.
      75       It's also needed for nested structure layout, for example
      76       struct A { long a; char b; }; struct B { struct A x; char y; };
      77       should find y at an offset of 2*sizeof(long) and result in a
      78       total size of 3*sizeof(long).  */
      79    arg->size = FFI_ALIGN (arg->size, arg->alignment);
      80  
      81    /* On some targets, the ABI defines that structures have an additional
      82       alignment beyond the "natural" one based on their elements.  */
      83  #ifdef FFI_AGGREGATE_ALIGNMENT
      84    if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
      85      arg->alignment = FFI_AGGREGATE_ALIGNMENT;
      86  #endif
      87  
      88    if (arg->size == 0)
      89      return FFI_BAD_TYPEDEF;
      90    else
      91      return FFI_OK;
      92  }
      93  
      94  #ifndef __CRIS__
      95  /* The CRIS ABI specifies structure elements to have byte
      96     alignment only, so it completely overrides this functions,
      97     which assumes "natural" alignment and padding.  */
      98  
      99  /* Perform machine independent ffi_cif preparation, then call
     100     machine dependent routine. */
     101  
     102  /* For non variadic functions isvariadic should be 0 and
     103     nfixedargs==ntotalargs.
     104  
     105     For variadic calls, isvariadic should be 1 and nfixedargs
     106     and ntotalargs set as appropriate. nfixedargs must always be >=1 */
     107  
     108  
     109  ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
     110  			     unsigned int isvariadic,
     111                               unsigned int nfixedargs,
     112                               unsigned int ntotalargs,
     113  			     ffi_type *rtype, ffi_type **atypes)
     114  {
     115    unsigned bytes = 0;
     116    unsigned int i;
     117    ffi_type **ptr;
     118  
     119    FFI_ASSERT(cif != NULL);
     120    FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
     121    FFI_ASSERT(nfixedargs <= ntotalargs);
     122  
     123    if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
     124      return FFI_BAD_ABI;
     125  
     126    cif->abi = abi;
     127    cif->arg_types = atypes;
     128    cif->nargs = ntotalargs;
     129    cif->rtype = rtype;
     130  
     131    cif->flags = 0;
     132  #if (defined(_M_ARM64) || defined(__aarch64__)) && defined(_WIN32)
     133    cif->is_variadic = isvariadic;
     134  #endif
     135  #if HAVE_LONG_DOUBLE_VARIANT
     136    ffi_prep_types (abi);
     137  #endif
     138  
     139    /* Initialize the return type if necessary */
     140    if ((cif->rtype->size == 0)
     141        && (initialize_aggregate(cif->rtype, NULL) != FFI_OK))
     142      return FFI_BAD_TYPEDEF;
     143  
     144  #ifndef FFI_TARGET_HAS_COMPLEX_TYPE
     145    if (rtype->type == FFI_TYPE_COMPLEX)
     146      abort();
     147  #endif
     148    /* Perform a sanity check on the return type */
     149    FFI_ASSERT_VALID_TYPE(cif->rtype);
     150  
     151    /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
     152  #if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
     153    /* Make space for the return structure pointer */
     154    if (cif->rtype->type == FFI_TYPE_STRUCT
     155  #ifdef TILE
     156        && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
     157  #endif
     158  #ifdef XTENSA
     159        && (cif->rtype->size > 16)
     160  #endif
     161  #ifdef NIOS2
     162        && (cif->rtype->size > 8)
     163  #endif
     164       )
     165      bytes = STACK_ARG_SIZE(sizeof(void*));
     166  #endif
     167  
     168    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
     169      {
     170  
     171        /* Initialize any uninitialized aggregate type definitions */
     172        if (((*ptr)->size == 0)
     173  	  && (initialize_aggregate((*ptr), NULL) != FFI_OK))
     174  	return FFI_BAD_TYPEDEF;
     175  
     176  #ifndef FFI_TARGET_HAS_COMPLEX_TYPE
     177        if ((*ptr)->type == FFI_TYPE_COMPLEX)
     178  	abort();
     179  #endif
     180        /* Perform a sanity check on the argument type, do this
     181  	 check after the initialization.  */
     182        FFI_ASSERT_VALID_TYPE(*ptr);
     183  
     184  #if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
     185  	{
     186  	  /* Add any padding if necessary */
     187  	  if (((*ptr)->alignment - 1) & bytes)
     188  	    bytes = (unsigned)FFI_ALIGN(bytes, (*ptr)->alignment);
     189  
     190  #ifdef TILE
     191  	  if (bytes < 10 * FFI_SIZEOF_ARG &&
     192  	      bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
     193  	    {
     194  	      /* An argument is never split between the 10 parameter
     195  		 registers and the stack.  */
     196  	      bytes = 10 * FFI_SIZEOF_ARG;
     197  	    }
     198  #endif
     199  #ifdef XTENSA
     200  	  if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
     201  	    bytes = 6*4;
     202  #endif
     203  
     204  	  bytes += (unsigned int)STACK_ARG_SIZE((*ptr)->size);
     205  	}
     206  #endif
     207      }
     208  
     209    cif->bytes = bytes;
     210  
     211    /* Perform machine dependent cif processing */
     212  #ifdef FFI_TARGET_SPECIFIC_VARIADIC
     213    if (isvariadic)
     214  	return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
     215  #endif
     216  
     217    return ffi_prep_cif_machdep(cif);
     218  }
     219  #endif /* not __CRIS__ */
     220  
     221  ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
     222  			     ffi_type *rtype, ffi_type **atypes)
     223  {
     224    return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
     225  }
     226  
     227  ffi_status ffi_prep_cif_var(ffi_cif *cif,
     228                              ffi_abi abi,
     229                              unsigned int nfixedargs,
     230                              unsigned int ntotalargs,
     231                              ffi_type *rtype,
     232                              ffi_type **atypes)
     233  {
     234    ffi_status rc;
     235    size_t int_size = ffi_type_sint.size;
     236    int i;
     237  
     238    rc = ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
     239  
     240    if (rc != FFI_OK)
     241      return rc;
     242  
     243    for (i = 1; i < ntotalargs; i++)
     244      {
     245        ffi_type *arg_type = atypes[i];
     246        if (arg_type == &ffi_type_float
     247            || ((arg_type->type != FFI_TYPE_STRUCT
     248                 && arg_type->type != FFI_TYPE_COMPLEX)
     249                && arg_type->size < int_size))
     250          return FFI_BAD_ARGTYPE;
     251      }
     252  
     253    return FFI_OK;
     254  }
     255  
     256  #if FFI_CLOSURES
     257  
     258  ffi_status
     259  ffi_prep_closure (ffi_closure* closure,
     260  		  ffi_cif* cif,
     261  		  void (*fun)(ffi_cif*,void*,void**,void*),
     262  		  void *user_data)
     263  {
     264    return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
     265  }
     266  
     267  #endif
     268  
     269  ffi_status
     270  ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets)
     271  {
     272    if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
     273      return FFI_BAD_ABI;
     274    if (struct_type->type != FFI_TYPE_STRUCT)
     275      return FFI_BAD_TYPEDEF;
     276  
     277  #if HAVE_LONG_DOUBLE_VARIANT
     278    ffi_prep_types (abi);
     279  #endif
     280  
     281    return initialize_aggregate(struct_type, offsets);
     282  }