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

     1  /* -----------------------------------------------------------------------
     2     ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008  Red Hat, Inc.
     3             Copyright (c) 2002  Ranjit Mathew
     4             Copyright (c) 2002  Bo Thorsen
     5             Copyright (c) 2002  Roger Sayle
     6             Copyright (C) 2008, 2010  Free Software Foundation, Inc.
     7  
     8     x86 Foreign Function Interface
     9  
    10     Permission is hereby granted, free of charge, to any person obtaining
    11     a copy of this software and associated documentation files (the
    12     ``Software''), to deal in the Software without restriction, including
    13     without limitation the rights to use, copy, modify, merge, publish,
    14     distribute, sublicense, and/or sell copies of the Software, and to
    15     permit persons to whom the Software is furnished to do so, subject to
    16     the following conditions:
    17  
    18     The above copyright notice and this permission notice shall be included
    19     in all copies or substantial portions of the Software.
    20  
    21     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
    22     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    23     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    24     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    25     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    26     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    27     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    28     DEALINGS IN THE SOFTWARE.
    29     ----------------------------------------------------------------------- */
    30  
    31  #if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__)
    32  
    33  #ifdef _WIN64
    34  #include <windows.h>
    35  #endif
    36  
    37  #include <ffi.h>
    38  #include <ffi_common.h>
    39  
    40  #include <stdlib.h>
    41  
    42  /* ffi_prep_args is called by the assembly routine once stack space
    43     has been allocated for the function's arguments */
    44  
    45  void ffi_prep_args(char *stack, extended_cif *ecif)
    46  {
    47    register unsigned int i;
    48    register void **p_argv;
    49    register char *argp;
    50    register ffi_type **p_arg;
    51  #ifdef X86_WIN32
    52    size_t p_stack_args[2];
    53    void *p_stack_data[2];
    54    char *argp2 = stack;
    55    int stack_args_count = 0;
    56    int cabi = ecif->cif->abi;
    57  #endif
    58  
    59    argp = stack;
    60  
    61    if ((ecif->cif->flags == FFI_TYPE_STRUCT
    62         || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
    63  #ifdef X86_WIN64
    64        && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
    65            && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
    66  #endif
    67        )
    68      {
    69        *(void **) argp = ecif->rvalue;
    70  #ifdef X86_WIN32
    71        /* For fastcall/thiscall this is first register-passed
    72           argument.  */
    73        if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
    74  	{
    75  	  p_stack_args[stack_args_count] = sizeof (void*);
    76  	  p_stack_data[stack_args_count] = argp;
    77  	  ++stack_args_count;
    78  	}
    79  #endif
    80        argp += sizeof(void*);
    81      }
    82  
    83    p_argv = ecif->avalue;
    84  
    85    for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
    86         i != 0;
    87         i--, p_arg++)
    88      {
    89        size_t z;
    90  
    91        /* Align if necessary */
    92        if ((sizeof(void*) - 1) & (size_t) argp)
    93          argp = (char *) ALIGN(argp, sizeof(void*));
    94  
    95        z = (*p_arg)->size;
    96  #ifdef X86_WIN64
    97        if (z > sizeof(ffi_arg)
    98            || ((*p_arg)->type == FFI_TYPE_STRUCT
    99                && (z != 1 && z != 2 && z != 4 && z != 8))
   100  #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
   101            || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
   102  #endif
   103            )
   104          {
   105            z = sizeof(ffi_arg);
   106            *(void **)argp = *p_argv;
   107          }
   108        else if ((*p_arg)->type == FFI_TYPE_FLOAT)
   109          {
   110            memcpy(argp, *p_argv, z);
   111          }
   112        else
   113  #endif
   114        if (z < sizeof(ffi_arg))
   115          {
   116            z = sizeof(ffi_arg);
   117            switch ((*p_arg)->type)
   118              {
   119              case FFI_TYPE_SINT8:
   120                *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
   121                break;
   122  
   123              case FFI_TYPE_UINT8:
   124                *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
   125                break;
   126  
   127              case FFI_TYPE_SINT16:
   128                *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
   129                break;
   130  
   131              case FFI_TYPE_UINT16:
   132                *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
   133                break;
   134  
   135              case FFI_TYPE_SINT32:
   136                *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
   137                break;
   138  
   139              case FFI_TYPE_UINT32:
   140                *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
   141                break;
   142  
   143              case FFI_TYPE_STRUCT:
   144                *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
   145                break;
   146  
   147              default:
   148                FFI_ASSERT(0);
   149              }
   150          }
   151        else
   152          {
   153            memcpy(argp, *p_argv, z);
   154          }
   155  
   156  #ifdef X86_WIN32
   157      /* For thiscall/fastcall convention register-passed arguments
   158         are the first two none-floating-point arguments with a size
   159         smaller or equal to sizeof (void*).  */
   160      if ((cabi == FFI_THISCALL && stack_args_count < 1)
   161          || (cabi == FFI_FASTCALL && stack_args_count < 2))
   162        {
   163  	if (z <= 4
   164  	    && ((*p_arg)->type != FFI_TYPE_FLOAT
   165  	        && (*p_arg)->type != FFI_TYPE_STRUCT))
   166  	  {
   167  	    p_stack_args[stack_args_count] = z;
   168  	    p_stack_data[stack_args_count] = argp;
   169  	    ++stack_args_count;
   170  	  }
   171        }
   172  #endif
   173        p_argv++;
   174  #ifdef X86_WIN64
   175        argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
   176  #else
   177        argp += z;
   178  #endif
   179      }
   180  
   181  #ifdef X86_WIN32
   182    /* We need to move the register-passed arguments for thiscall/fastcall
   183       on top of stack, so that those can be moved to registers ecx/edx by
   184       call-handler.  */
   185    if (stack_args_count > 0)
   186      {
   187        size_t zz = (p_stack_args[0] + 3) & ~3;
   188        char *h;
   189  
   190        /* Move first argument to top-stack position.  */
   191        if (p_stack_data[0] != argp2)
   192  	{
   193  	  h = alloca (zz + 1);
   194  	  memcpy (h, p_stack_data[0], zz);
   195  	  memmove (argp2 + zz, argp2,
   196  	           (size_t) ((char *) p_stack_data[0] - (char*)argp2));
   197  	  memcpy (argp2, h, zz);
   198  	}
   199  
   200        argp2 += zz;
   201        --stack_args_count;
   202        if (zz > 4)
   203  	stack_args_count = 0;
   204  
   205        /* If we have a second argument, then move it on top
   206           after the first one.  */
   207        if (stack_args_count > 0 && p_stack_data[1] != argp2)
   208  	{
   209  	  zz = p_stack_args[1];
   210  	  zz = (zz + 3) & ~3;
   211  	  h = alloca (zz + 1);
   212  	  h = alloca (zz + 1);
   213  	  memcpy (h, p_stack_data[1], zz);
   214  	  memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
   215  	  memcpy (argp2, h, zz);
   216  	}
   217      }
   218  #endif
   219    return;
   220  }
   221  
   222  /* Perform machine dependent cif processing */
   223  ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
   224  {
   225    unsigned int i;
   226    ffi_type **ptr;
   227  
   228    /* Set the return type flag */
   229    switch (cif->rtype->type)
   230      {
   231      case FFI_TYPE_VOID:
   232      case FFI_TYPE_UINT8:
   233      case FFI_TYPE_UINT16:
   234      case FFI_TYPE_SINT8:
   235      case FFI_TYPE_SINT16:
   236  #ifdef X86_WIN64
   237      case FFI_TYPE_UINT32:
   238      case FFI_TYPE_SINT32:
   239  #endif
   240      case FFI_TYPE_SINT64:
   241      case FFI_TYPE_FLOAT:
   242      case FFI_TYPE_DOUBLE:
   243  #ifndef X86_WIN64
   244  #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
   245      case FFI_TYPE_LONGDOUBLE:
   246  #endif
   247  #endif
   248        cif->flags = (unsigned) cif->rtype->type;
   249        break;
   250  
   251      case FFI_TYPE_UINT64:
   252  #ifdef X86_WIN64
   253      case FFI_TYPE_POINTER:
   254  #endif
   255        cif->flags = FFI_TYPE_SINT64;
   256        break;
   257  
   258      case FFI_TYPE_STRUCT:
   259  #ifndef X86
   260        if (cif->rtype->size == 1)
   261          {
   262            cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
   263          }
   264        else if (cif->rtype->size == 2)
   265          {
   266            cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
   267          }
   268        else if (cif->rtype->size == 4)
   269          {
   270  #ifdef X86_WIN64
   271            cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
   272  #else
   273            cif->flags = FFI_TYPE_INT; /* same as int type */
   274  #endif
   275          }
   276        else if (cif->rtype->size == 8)
   277          {
   278            cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
   279          }
   280        else
   281  #endif
   282          {
   283  #ifdef X86_WIN32
   284            if (cif->abi == FFI_MS_CDECL)
   285              cif->flags = FFI_TYPE_MS_STRUCT;
   286            else
   287  #endif
   288              cif->flags = FFI_TYPE_STRUCT;
   289            /* allocate space for return value pointer */
   290            cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
   291          }
   292        break;
   293  
   294      default:
   295  #ifdef X86_WIN64
   296        cif->flags = FFI_TYPE_SINT64;
   297        break;
   298      case FFI_TYPE_INT:
   299        cif->flags = FFI_TYPE_SINT32;
   300  #else
   301        cif->flags = FFI_TYPE_INT;
   302  #endif
   303        break;
   304      }
   305  
   306    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
   307      {
   308        if (((*ptr)->alignment - 1) & cif->bytes)
   309          cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
   310        cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
   311      }
   312  
   313  #ifdef X86_WIN64
   314    /* ensure space for storing four registers */
   315    cif->bytes += 4 * sizeof(ffi_arg);
   316  #endif
   317  
   318  #ifdef X86_DARWIN
   319    cif->bytes = (cif->bytes + 15) & ~0xF;
   320  #endif
   321  
   322    return FFI_OK;
   323  }
   324  
   325  #ifdef X86_WIN64
   326  extern int
   327  ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
   328                 unsigned, unsigned, unsigned *, void (*fn)(void));
   329  #elif defined(X86_WIN32)
   330  extern void
   331  ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
   332                 unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
   333  #else
   334  extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
   335                            unsigned, unsigned, unsigned *, void (*fn)(void));
   336  #endif
   337  
   338  void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
   339  {
   340    extended_cif ecif;
   341  
   342    ecif.cif = cif;
   343    ecif.avalue = avalue;
   344    
   345    /* If the return value is a struct and we don't have a return */
   346    /* value address then we need to make one                     */
   347  
   348  #ifdef X86_WIN64
   349    if (rvalue == NULL
   350        && cif->flags == FFI_TYPE_STRUCT
   351        && cif->rtype->size != 1 && cif->rtype->size != 2
   352        && cif->rtype->size != 4 && cif->rtype->size != 8)
   353      {
   354        ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
   355      }
   356  #else
   357    if (rvalue == NULL
   358        && (cif->flags == FFI_TYPE_STRUCT
   359            || cif->flags == FFI_TYPE_MS_STRUCT))
   360      {
   361        ecif.rvalue = alloca(cif->rtype->size);
   362      }
   363  #endif
   364    else
   365      ecif.rvalue = rvalue;
   366      
   367    
   368    switch (cif->abi) 
   369      {
   370  #ifdef X86_WIN64
   371      case FFI_WIN64:
   372        ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
   373                       cif->flags, ecif.rvalue, fn);
   374        break;
   375  #elif defined(X86_WIN32)
   376      case FFI_SYSV:
   377      case FFI_STDCALL:
   378      case FFI_MS_CDECL:
   379        ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
   380  		     ecif.rvalue, fn);
   381        break;
   382      case FFI_THISCALL:
   383      case FFI_FASTCALL:
   384        {
   385  	unsigned int abi = cif->abi;
   386  	unsigned int i, passed_regs = 0;
   387  
   388  	if (cif->flags == FFI_TYPE_STRUCT)
   389  	  ++passed_regs;
   390  
   391  	for (i=0; i < cif->nargs && passed_regs < 2;i++)
   392  	  {
   393  	    size_t sz;
   394  
   395  	    if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
   396  	        || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
   397  	      continue;
   398  	    sz = (cif->arg_types[i]->size + 3) & ~3;
   399  	    if (sz == 0 || sz > 4)
   400  	      continue;
   401  	    ++passed_regs;
   402  	  }
   403  	if (passed_regs < 2 && abi == FFI_FASTCALL)
   404  	  abi = FFI_THISCALL;
   405  	if (passed_regs < 1 && abi == FFI_THISCALL)
   406  	  abi = FFI_STDCALL;
   407          ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
   408                         ecif.rvalue, fn);
   409        }
   410        break;
   411  #else
   412      case FFI_SYSV:
   413        ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
   414                      fn);
   415        break;
   416  #endif
   417      default:
   418        FFI_ASSERT(0);
   419        break;
   420      }
   421  }
   422  
   423  
   424  /** private members **/
   425  
   426  /* The following __attribute__((regparm(1))) decorations will have no effect
   427     on MSVC - standard cdecl convention applies. */
   428  static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
   429                                           void** args, ffi_cif* cif);
   430  void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
   431       __attribute__ ((regparm(1)));
   432  unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
   433       __attribute__ ((regparm(1)));
   434  void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
   435       __attribute__ ((regparm(1)));
   436  #ifdef X86_WIN32
   437  void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
   438       __attribute__ ((regparm(1)));
   439  void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
   440       __attribute__ ((regparm(1)));
   441  void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
   442       __attribute__ ((regparm(1)));
   443  #endif
   444  #ifdef X86_WIN64
   445  void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
   446  #endif
   447  
   448  /* This function is jumped to by the trampoline */
   449  
   450  #ifdef X86_WIN64
   451  void * FFI_HIDDEN
   452  ffi_closure_win64_inner (ffi_closure *closure, void *args) {
   453    ffi_cif       *cif;
   454    void         **arg_area;
   455    void          *result;
   456    void          *resp = &result;
   457  
   458    cif         = closure->cif;
   459    arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
   460  
   461    /* this call will initialize ARG_AREA, such that each
   462     * element in that array points to the corresponding 
   463     * value on the stack; and if the function returns
   464     * a structure, it will change RESP to point to the
   465     * structure return address.  */
   466  
   467    ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
   468    
   469    (closure->fun) (cif, resp, arg_area, closure->user_data);
   470  
   471    /* The result is returned in rax.  This does the right thing for
   472       result types except for floats; we have to 'mov xmm0, rax' in the
   473       caller to correct this.
   474       TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
   475    */
   476    return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
   477  }
   478  
   479  #else
   480  unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
   481  ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
   482  {
   483    /* our various things...  */
   484    ffi_cif       *cif;
   485    void         **arg_area;
   486  
   487    cif         = closure->cif;
   488    arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
   489  
   490    /* this call will initialize ARG_AREA, such that each
   491     * element in that array points to the corresponding 
   492     * value on the stack; and if the function returns
   493     * a structure, it will change RESP to point to the
   494     * structure return address.  */
   495  
   496    ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
   497  
   498    (closure->fun) (cif, *respp, arg_area, closure->user_data);
   499  
   500    return cif->flags;
   501  }
   502  #endif /* !X86_WIN64 */
   503  
   504  static void
   505  ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
   506                              ffi_cif *cif)
   507  {
   508    register unsigned int i;
   509    register void **p_argv;
   510    register char *argp;
   511    register ffi_type **p_arg;
   512  
   513    argp = stack;
   514  
   515  #ifdef X86_WIN64
   516    if (cif->rtype->size > sizeof(ffi_arg)
   517        || (cif->flags == FFI_TYPE_STRUCT
   518            && (cif->rtype->size != 1 && cif->rtype->size != 2
   519                && cif->rtype->size != 4 && cif->rtype->size != 8))) {
   520      *rvalue = *(void **) argp;
   521      argp += sizeof(void *);
   522    }
   523  #else
   524    if ( cif->flags == FFI_TYPE_STRUCT
   525         || cif->flags == FFI_TYPE_MS_STRUCT ) {
   526      *rvalue = *(void **) argp;
   527      argp += sizeof(void *);
   528    }
   529  #endif
   530  
   531    p_argv = avalue;
   532  
   533    for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
   534      {
   535        size_t z;
   536  
   537        /* Align if necessary */
   538        if ((sizeof(void*) - 1) & (size_t) argp) {
   539          argp = (char *) ALIGN(argp, sizeof(void*));
   540        }
   541  
   542  #ifdef X86_WIN64
   543        if ((*p_arg)->size > sizeof(ffi_arg)
   544            || ((*p_arg)->type == FFI_TYPE_STRUCT
   545                && ((*p_arg)->size != 1 && (*p_arg)->size != 2
   546                    && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
   547          {
   548            z = sizeof(void *);
   549            *p_argv = *(void **)argp;
   550          }
   551        else
   552  #endif
   553          {
   554            z = (*p_arg)->size;
   555            
   556            /* because we're little endian, this is what it turns into.   */
   557            
   558            *p_argv = (void*) argp;
   559          }
   560            
   561        p_argv++;
   562  #ifdef X86_WIN64
   563        argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
   564  #else
   565        argp += z;
   566  #endif
   567      }
   568    
   569    return;
   570  }
   571  
   572  #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
   573  { unsigned char *__tramp = (unsigned char*)(TRAMP); \
   574     void*  __fun = (void*)(FUN); \
   575     void*  __ctx = (void*)(CTX); \
   576     *(unsigned char*) &__tramp[0] = 0x41; \
   577     *(unsigned char*) &__tramp[1] = 0xbb; \
   578     *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
   579     *(unsigned char*) &__tramp[6] = 0x48; \
   580     *(unsigned char*) &__tramp[7] = 0xb8; \
   581     *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
   582     *(unsigned char *)  &__tramp[16] = 0x49; \
   583     *(unsigned char *)  &__tramp[17] = 0xba; \
   584     *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
   585     *(unsigned char *)  &__tramp[26] = 0x41; \
   586     *(unsigned char *)  &__tramp[27] = 0xff; \
   587     *(unsigned char *)  &__tramp[28] = 0xe2; /* jmp %r10 */ \
   588   }
   589  
   590  /* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
   591  
   592  #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
   593  { unsigned char *__tramp = (unsigned char*)(TRAMP); \
   594     unsigned int  __fun = (unsigned int)(FUN); \
   595     unsigned int  __ctx = (unsigned int)(CTX); \
   596     unsigned int  __dis = __fun - (__ctx + 10);  \
   597     *(unsigned char*) &__tramp[0] = 0xb8; \
   598     *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
   599     *(unsigned char *)  &__tramp[5] = 0xe9; \
   600     *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
   601   }
   602  
   603  #define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
   604  { unsigned char *__tramp = (unsigned char*)(TRAMP); \
   605     unsigned int  __fun = (unsigned int)(FUN); \
   606     unsigned int  __ctx = (unsigned int)(CTX); \
   607     unsigned int  __dis = __fun - (__ctx + 49);  \
   608     unsigned short __size = (unsigned short)(SIZE); \
   609     *(unsigned int *) &__tramp[0] = 0x8324048b;	/* mov (%esp), %eax */ \
   610     *(unsigned int *) &__tramp[4] = 0x4c890cec;	/* sub $12, %esp */ \
   611     *(unsigned int *) &__tramp[8] = 0x04890424;	/* mov %ecx, 4(%esp) */ \
   612     *(unsigned char*) &__tramp[12] = 0x24;	/* mov %eax, (%esp) */ \
   613     *(unsigned char*) &__tramp[13] = 0xb8; \
   614     *(unsigned int *) &__tramp[14] = __size;	/* mov __size, %eax */ \
   615     *(unsigned int *) &__tramp[18] = 0x08244c8d;	/* lea 8(%esp), %ecx */ \
   616     *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
   617     *(unsigned short*) &__tramp[26] = 0x0b74;	/* jz 1f */ \
   618     *(unsigned int *) &__tramp[28] = 0x8908518b;	/* 2b: mov 8(%ecx), %edx */ \
   619     *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
   620     *(unsigned char*) &__tramp[36] = 0x48;	/* dec %eax */ \
   621     *(unsigned short*) &__tramp[37] = 0xf575;	/* jnz 2b ; 1f: */ \
   622     *(unsigned char*) &__tramp[39] = 0xb8; \
   623     *(unsigned int*)  &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
   624     *(unsigned char *)  &__tramp[44] = 0xe8; \
   625     *(unsigned int*)  &__tramp[45] = __dis; /* call __fun  */ \
   626     *(unsigned char*)  &__tramp[49] = 0xc2; /* ret  */ \
   627     *(unsigned short*)  &__tramp[50] = (__size + 8); /* ret (__size + 8)  */ \
   628   }
   629  
   630  #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
   631  { unsigned char *__tramp = (unsigned char*)(TRAMP); \
   632     unsigned int  __fun = (unsigned int)(FUN); \
   633     unsigned int  __ctx = (unsigned int)(CTX); \
   634     unsigned int  __dis = __fun - (__ctx + 10); \
   635     unsigned short __size = (unsigned short)(SIZE); \
   636     *(unsigned char*) &__tramp[0] = 0xb8; \
   637     *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
   638     *(unsigned char *)  &__tramp[5] = 0xe8; \
   639     *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
   640     *(unsigned char *)  &__tramp[10] = 0xc2; \
   641     *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
   642   }
   643  
   644  /* the cif must already be prep'ed */
   645  
   646  ffi_status
   647  ffi_prep_closure_loc (ffi_closure* closure,
   648                        ffi_cif* cif,
   649                        void (*fun)(ffi_cif*,void*,void**,void*),
   650                        void *user_data,
   651                        void *codeloc)
   652  {
   653  #ifdef X86_WIN64
   654  #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
   655  #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
   656    if (cif->abi == FFI_WIN64) 
   657      {
   658        int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
   659        FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
   660                                   &ffi_closure_win64,
   661                                   codeloc, mask);
   662        /* make sure we can execute here */
   663      }
   664  #else
   665    if (cif->abi == FFI_SYSV)
   666      {
   667        FFI_INIT_TRAMPOLINE (&closure->tramp[0],
   668                             &ffi_closure_SYSV,
   669                             (void*)codeloc);
   670      }
   671  #ifdef X86_WIN32
   672    else if (cif->abi == FFI_THISCALL)
   673      {
   674        FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
   675  				    &ffi_closure_THISCALL,
   676  				    (void*)codeloc,
   677  				    cif->bytes);
   678      }
   679    else if (cif->abi == FFI_STDCALL)
   680      {
   681        FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
   682                                     &ffi_closure_STDCALL,
   683                                     (void*)codeloc, cif->bytes);
   684      }
   685    else if (cif->abi == FFI_MS_CDECL)
   686      {
   687        FFI_INIT_TRAMPOLINE (&closure->tramp[0],
   688                             &ffi_closure_SYSV,
   689                             (void*)codeloc);
   690      }
   691  #endif /* X86_WIN32 */
   692  #endif /* !X86_WIN64 */
   693    else
   694      {
   695        return FFI_BAD_ABI;
   696      }
   697      
   698    closure->cif  = cif;
   699    closure->user_data = user_data;
   700    closure->fun  = fun;
   701  
   702    return FFI_OK;
   703  }
   704  
   705  /* ------- Native raw API support -------------------------------- */
   706  
   707  #if !FFI_NO_RAW_API
   708  
   709  ffi_status
   710  ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
   711                            ffi_cif* cif,
   712                            void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
   713                            void *user_data,
   714                            void *codeloc)
   715  {
   716    int i;
   717  
   718    if (cif->abi != FFI_SYSV) {
   719  #ifdef X86_WIN32
   720      if (cif->abi != FFI_THISCALL)
   721  #endif
   722      return FFI_BAD_ABI;
   723    }
   724  
   725    /* we currently don't support certain kinds of arguments for raw
   726       closures.  This should be implemented by a separate assembly
   727       language routine, since it would require argument processing,
   728       something we don't do now for performance.  */
   729  
   730    for (i = cif->nargs-1; i >= 0; i--)
   731      {
   732        FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
   733        FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
   734      }
   735    
   736  #ifdef X86_WIN32
   737    if (cif->abi == FFI_SYSV)
   738      {
   739  #endif
   740    FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
   741                         codeloc);
   742  #ifdef X86_WIN32
   743      }
   744    else if (cif->abi == FFI_THISCALL)
   745      {
   746        FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
   747  				    codeloc, cif->bytes);
   748      }
   749  #endif
   750    closure->cif  = cif;
   751    closure->user_data = user_data;
   752    closure->fun  = fun;
   753  
   754    return FFI_OK;
   755  }
   756  
   757  static void 
   758  ffi_prep_args_raw(char *stack, extended_cif *ecif)
   759  {
   760    memcpy (stack, ecif->avalue, ecif->cif->bytes);
   761  }
   762  
   763  /* we borrow this routine from libffi (it must be changed, though, to
   764   * actually call the function passed in the first argument.  as of
   765   * libffi-1.20, this is not the case.)
   766   */
   767  
   768  void
   769  ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
   770  {
   771    extended_cif ecif;
   772    void **avalue = (void **)fake_avalue;
   773  
   774    ecif.cif = cif;
   775    ecif.avalue = avalue;
   776    
   777    /* If the return value is a struct and we don't have a return */
   778    /* value address then we need to make one                     */
   779  
   780    if (rvalue == NULL
   781        && (cif->flags == FFI_TYPE_STRUCT
   782            || cif->flags == FFI_TYPE_MS_STRUCT))
   783      {
   784        ecif.rvalue = alloca(cif->rtype->size);
   785      }
   786    else
   787      ecif.rvalue = rvalue;
   788      
   789    
   790    switch (cif->abi) 
   791      {
   792  #ifdef X86_WIN32
   793      case FFI_SYSV:
   794      case FFI_STDCALL:
   795      case FFI_MS_CDECL:
   796        ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
   797  		     ecif.rvalue, fn);
   798        break;
   799      case FFI_THISCALL:
   800      case FFI_FASTCALL:
   801        {
   802  	unsigned int abi = cif->abi;
   803  	unsigned int i, passed_regs = 0;
   804  
   805  	if (cif->flags == FFI_TYPE_STRUCT)
   806  	  ++passed_regs;
   807  
   808  	for (i=0; i < cif->nargs && passed_regs < 2;i++)
   809  	  {
   810  	    size_t sz;
   811  
   812  	    if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
   813  	        || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
   814  	      continue;
   815  	    sz = (cif->arg_types[i]->size + 3) & ~3;
   816  	    if (sz == 0 || sz > 4)
   817  	      continue;
   818  	    ++passed_regs;
   819  	  }
   820  	if (passed_regs < 2 && abi == FFI_FASTCALL)
   821  	  cif->abi = abi = FFI_THISCALL;
   822  	if (passed_regs < 1 && abi == FFI_THISCALL)
   823  	  cif->abi = abi = FFI_STDCALL;
   824          ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
   825                         ecif.rvalue, fn);
   826        }
   827        break;
   828  #else
   829      case FFI_SYSV:
   830        ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
   831                      ecif.rvalue, fn);
   832        break;
   833  #endif
   834      default:
   835        FFI_ASSERT(0);
   836        break;
   837      }
   838  }
   839  
   840  #endif
   841  
   842  #endif /* !__x86_64__  || X86_WIN64 */
   843