github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/prep_cif.c (about)

     1  /* -----------------------------------------------------------------------
     2     prep_cif.c - Copyright (c) 2011, 2012  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) 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)
    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)) != 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 = ALIGN(arg->size, (*ptr)->alignment);
    62        arg->size += (*ptr)->size;
    63  
    64        arg->alignment = (arg->alignment > (*ptr)->alignment) ?
    65  	arg->alignment : (*ptr)->alignment;
    66  
    67        ptr++;
    68      }
    69  
    70    /* Structure size includes tail padding.  This is important for
    71       structures that fit in one register on ABIs like the PowerPC64
    72       Linux ABI that right justify small structs in a register.
    73       It's also needed for nested structure layout, for example
    74       struct A { long a; char b; }; struct B { struct A x; char y; };
    75       should find y at an offset of 2*sizeof(long) and result in a
    76       total size of 3*sizeof(long).  */
    77    arg->size = ALIGN (arg->size, arg->alignment);
    78  
    79    /* On some targets, the ABI defines that structures have an additional
    80       alignment beyond the "natural" one based on their elements.  */
    81  #ifdef FFI_AGGREGATE_ALIGNMENT
    82    if (FFI_AGGREGATE_ALIGNMENT > arg->alignment)
    83      arg->alignment = FFI_AGGREGATE_ALIGNMENT;
    84  #endif
    85  
    86    if (arg->size == 0)
    87      return FFI_BAD_TYPEDEF;
    88    else
    89      return FFI_OK;
    90  }
    91  
    92  #ifndef __CRIS__
    93  /* The CRIS ABI specifies structure elements to have byte
    94     alignment only, so it completely overrides this functions,
    95     which assumes "natural" alignment and padding.  */
    96  
    97  /* Perform machine independent ffi_cif preparation, then call
    98     machine dependent routine. */
    99  
   100  /* For non variadic functions isvariadic should be 0 and
   101     nfixedargs==ntotalargs.
   102  
   103     For variadic calls, isvariadic should be 1 and nfixedargs
   104     and ntotalargs set as appropriate. nfixedargs must always be >=1 */
   105  
   106  
   107  ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
   108  			     unsigned int isvariadic,
   109                               unsigned int nfixedargs,
   110                               unsigned int ntotalargs,
   111  			     ffi_type *rtype, ffi_type **atypes)
   112  {
   113    unsigned bytes = 0;
   114    unsigned int i;
   115    ffi_type **ptr;
   116  
   117    FFI_ASSERT(cif != NULL);
   118    FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
   119    FFI_ASSERT(nfixedargs <= ntotalargs);
   120  
   121    if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
   122      return FFI_BAD_ABI;
   123  
   124    cif->abi = abi;
   125    cif->arg_types = atypes;
   126    cif->nargs = ntotalargs;
   127    cif->rtype = rtype;
   128  
   129    cif->flags = 0;
   130  
   131  #if HAVE_LONG_DOUBLE_VARIANT
   132    ffi_prep_types (abi);
   133  #endif
   134  
   135    /* Initialize the return type if necessary */
   136    if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
   137      return FFI_BAD_TYPEDEF;
   138  
   139  #ifndef FFI_TARGET_HAS_COMPLEX_TYPE
   140    if (rtype->type == FFI_TYPE_COMPLEX)
   141      abort();
   142  #endif
   143    /* Perform a sanity check on the return type */
   144    FFI_ASSERT_VALID_TYPE(cif->rtype);
   145  
   146    /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
   147  #if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
   148    /* Make space for the return structure pointer */
   149    if (cif->rtype->type == FFI_TYPE_STRUCT
   150  #ifdef TILE
   151        && (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
   152  #endif
   153  #ifdef XTENSA
   154        && (cif->rtype->size > 16)
   155  #endif
   156  #ifdef NIOS2
   157        && (cif->rtype->size > 8)
   158  #endif
   159       )
   160      bytes = STACK_ARG_SIZE(sizeof(void*));
   161  #endif
   162  
   163    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
   164      {
   165  
   166        /* Initialize any uninitialized aggregate type definitions */
   167        if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
   168  	return FFI_BAD_TYPEDEF;
   169  
   170  #ifndef FFI_TARGET_HAS_COMPLEX_TYPE
   171        if ((*ptr)->type == FFI_TYPE_COMPLEX)
   172  	abort();
   173  #endif
   174        /* Perform a sanity check on the argument type, do this
   175  	 check after the initialization.  */
   176        FFI_ASSERT_VALID_TYPE(*ptr);
   177  
   178  #if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
   179  	{
   180  	  /* Add any padding if necessary */
   181  	  if (((*ptr)->alignment - 1) & bytes)
   182  	    bytes = (unsigned)ALIGN(bytes, (*ptr)->alignment);
   183  
   184  #ifdef TILE
   185  	  if (bytes < 10 * FFI_SIZEOF_ARG &&
   186  	      bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
   187  	    {
   188  	      /* An argument is never split between the 10 parameter
   189  		 registers and the stack.  */
   190  	      bytes = 10 * FFI_SIZEOF_ARG;
   191  	    }
   192  #endif
   193  #ifdef XTENSA
   194  	  if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
   195  	    bytes = 6*4;
   196  #endif
   197  
   198  	  bytes += STACK_ARG_SIZE((*ptr)->size);
   199  	}
   200  #endif
   201      }
   202  
   203    cif->bytes = bytes;
   204  
   205    /* Perform machine dependent cif processing */
   206  #ifdef FFI_TARGET_SPECIFIC_VARIADIC
   207    if (isvariadic)
   208  	return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
   209  #endif
   210  
   211    return ffi_prep_cif_machdep(cif);
   212  }
   213  #endif /* not __CRIS__ */
   214  
   215  ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
   216  			     ffi_type *rtype, ffi_type **atypes)
   217  {
   218    return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
   219  }
   220  
   221  ffi_status ffi_prep_cif_var(ffi_cif *cif,
   222                              ffi_abi abi,
   223                              unsigned int nfixedargs,
   224                              unsigned int ntotalargs,
   225                              ffi_type *rtype,
   226                              ffi_type **atypes)
   227  {
   228    return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
   229  }
   230  
   231  #if FFI_CLOSURES
   232  
   233  ffi_status
   234  ffi_prep_closure (ffi_closure* closure,
   235  		  ffi_cif* cif,
   236  		  void (*fun)(ffi_cif*,void*,void**,void*),
   237  		  void *user_data)
   238  {
   239    return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
   240  }
   241  
   242  #endif