⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ffi64.c

📁 this gcc-g++-3.3.1.tar.gz is a source file of gcc, you can learn more about gcc through this codes f
💻 C
📖 第 1 页 / 共 2 页
字号:
	  num = classify_argument (*p_arg, classes, &offset);	  for (j=0, a=*p_argv; j<num; j++, a+=8)	    {	      switch (classes[j])		{		case X86_64_INTEGER_CLASS:		case X86_64_INTEGERSI_CLASS:		  stack->gpr[gprcount++] = *(long long *)a;		  break;		case X86_64_SSE_CLASS:		  floatfloat2sse (a, &stack->sse[ssecount++]);		  break;		case X86_64_SSESF_CLASS:		  float2sse (*(float *)a, &stack->sse[ssecount++]);		  break;		case X86_64_SSEDF_CLASS:		  double2sse (*(double *)a, &stack->sse[ssecount++]);		  break;		default:		  abort();		}	    }	}    }}/* Perform machine dependent cif processing.  */ffi_statusffi_prep_cif_machdep (ffi_cif *cif){  int gprcount, ssecount, i, g, s;  gprcount = ssecount = 0;  /* Reset the byte count. We handle this size estimation here.  */  cif->bytes = 0;  /* If the return value should be passed in memory, pass the pointer     as the first argument. The actual memory isn't allocated here.  */  if (cif->rtype->type != FFI_TYPE_VOID       && examine_argument (cif->rtype, 1, &g, &s) == 0)    gprcount = 1;  /* Go over all arguments and determine the way they should be passed.     If it's in a register and there is space for it, let that be so. If     not, add it's size to the stack byte count.  */  for (i=0; i<cif->nargs; i++)    {      if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0	  || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)	{	  /* This is passed in memory. First align to the basic type.  */	  cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment);	  /* Stack arguments are *always* at least 8 byte aligned.  */	  cif->bytes = ALIGN(cif->bytes, 8);	  /* Now add the size of this argument.  */	  cif->bytes += cif->arg_types[i]->size;	}      else	{	  gprcount += g;	  ssecount += s;	}    }  /* Set the flag for the closures return.  */    switch (cif->rtype->type)    {    case FFI_TYPE_VOID:    case FFI_TYPE_STRUCT:    case FFI_TYPE_SINT64:    case FFI_TYPE_FLOAT:    case FFI_TYPE_DOUBLE:    case FFI_TYPE_LONGDOUBLE:      cif->flags = (unsigned) cif->rtype->type;      break;    case FFI_TYPE_UINT64:      cif->flags = FFI_TYPE_SINT64;      break;    default:      cif->flags = FFI_TYPE_INT;      break;    }  return FFI_OK;}typedef struct{  long gpr[2];  __int128_t sse[2];  long double st0;} return_value;voidffi_fill_return_value (return_value *rv, extended_cif *ecif){  enum x86_64_reg_class classes[MAX_CLASSES];  int i = 0, num;  long *gpr = rv->gpr;  __int128_t *sse = rv->sse;  signed char sc;  signed short ss;  /* This is needed because of the way x86-64 handles signed short     integers.  */  switch (ecif->cif->rtype->type)    {    case FFI_TYPE_SINT8:      sc = *(signed char *)gpr;      *(long long *)ecif->rvalue = (long long)sc;      return;    case FFI_TYPE_SINT16:      ss = *(signed short *)gpr;      *(long long *)ecif->rvalue = (long long)ss;      return;    default:      /* Just continue.  */      ;    }  num = classify_argument (ecif->cif->rtype, classes, &i);  if (num == 0)    /* Return in memory.  */    ecif->rvalue = (void *) rv->gpr[0];  else if (num == 2 && classes[0] == X86_64_X87_CLASS &&	classes[1] == X86_64_X87UP_CLASS)    /* This is a long double (this is easiest to handle this way instead       of an eightbyte at a time as in the loop below.  */    *((long double *)ecif->rvalue) = rv->st0;  else    {      void *a;      for (i=0, a=ecif->rvalue; i<num; i++, a+=8)	{	  switch (classes[i])	    {	    case X86_64_INTEGER_CLASS:	    case X86_64_INTEGERSI_CLASS:	      *(long long *)a = *gpr;	      gpr++;	      break;	    case X86_64_SSE_CLASS:	      sse2floatfloat (sse++, a);	      break;	    case X86_64_SSESF_CLASS:	      *(float *)a = sse2float (sse++);	      break;	    case X86_64_SSEDF_CLASS:	      *(double *)a = sse2double (sse++);	      break;	    default:	      abort();	    }	}    }}/*@-declundef@*//*@-exportheader@*/extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *),			    void (*) (return_value *, extended_cif *),			    /*@out@*/ extended_cif *, 			    unsigned, /*@out@*/ unsigned *, void (*fn)());/*@=declundef@*//*@=exportheader@*/void ffi_call(/*@dependent@*/ ffi_cif *cif, 	      void (*fn)(), 	      /*@out@*/ void *rvalue, 	      /*@dependent@*/ void **avalue){  extended_cif ecif;  int dummy;  ecif.cif = cif;  ecif.avalue = avalue;    /* 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) &&       (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0))    {      /*@-sysunrecog@*/      ecif.rvalue = alloca(cif->rtype->size);      /*@=sysunrecog@*/    }  else    ecif.rvalue = rvalue;      /* Stack must always be 16byte aligned. Make it so.  */  cif->bytes = ALIGN(cif->bytes, 16);    switch (cif->abi)     {    case FFI_SYSV:      /* Calling 32bit code from 64bit is not possible  */      FFI_ASSERT(0);      break;    case FFI_UNIX64:      /*@-usedef@*/      ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif,		       cif->bytes, ecif.rvalue, fn);      /*@=usedef@*/      break;    default:      FFI_ASSERT(0);      break;    }}extern void ffi_closure_UNIX64(void);ffi_statusffi_prep_closure (ffi_closure* closure,		  ffi_cif* cif,		  void (*fun)(ffi_cif*, void*, void**, void*),		  void *user_data){  volatile unsigned short *tramp;  /* FFI_ASSERT (cif->abi == FFI_OSF);  */  tramp = (volatile unsigned short *) &closure->tramp[0];  tramp[0] = 0xbb49;		/* mov <code>, %r11	*/  tramp[5] = 0xba49;		/* mov <data>, %r10	*/  tramp[10] = 0xff49;		/* jmp *%r11	*/  tramp[11] = 0x00e3;  *(void * volatile *) &tramp[1] = ffi_closure_UNIX64;  *(void * volatile *) &tramp[6] = closure;  closure->cif = cif;  closure->fun = fun;  closure->user_data = user_data;  return FFI_OK;}intffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp){  ffi_cif *cif;  void **avalue;  ffi_type **arg_types;  long i, avn, argn;  cif = closure->cif;  avalue = alloca(cif->nargs * sizeof(void *));  argn = 0;  i = 0;  avn = cif->nargs;  arg_types = cif->arg_types;    /* Grab the addresses of the arguments from the stack frame.  */  while (i < avn)    {      switch (arg_types[i]->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:	case FFI_TYPE_POINTER:	  {	    if (l->gp_offset > 48-8)	      {		avalue[i] = l->overflow_arg_area;		l->overflow_arg_area = (char *)l->overflow_arg_area + 8;	      }	    else	      {		avalue[i] = (char *)l->reg_save_area + l->gp_offset;		l->gp_offset += 8;	      }	  }	  break;	case FFI_TYPE_STRUCT:	  /* FIXME  */	  FFI_ASSERT(0);	  break;	case FFI_TYPE_DOUBLE:	  {	    if (l->fp_offset > 176-16)	      {		avalue[i] = l->overflow_arg_area;		l->overflow_arg_area = (char *)l->overflow_arg_area + 8;	      }	    else	      {		avalue[i] = (char *)l->reg_save_area + l->fp_offset;		l->fp_offset += 16;	      }	  }#if DEBUG_FFI	  fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]);#endif	  break;	  	case FFI_TYPE_FLOAT:	  {	    if (l->fp_offset > 176-16)	      {		avalue[i] = l->overflow_arg_area;		l->overflow_arg_area = (char *)l->overflow_arg_area + 8;	      }	    else	      {		avalue[i] = (char *)l->reg_save_area + l->fp_offset;		l->fp_offset += 16;	      }	  }#if DEBUG_FFI	  fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]);#endif	  break;	  	default:	  FFI_ASSERT(0);	}      argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;      i++;    }  /* Invoke the closure.  */  (closure->fun) (cif, rp, avalue, closure->user_data);  /* FIXME: Structs not supported.  */  FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT);  /* Tell ffi_closure_UNIX64 how to perform return type promotions.  */  return cif->rtype->type;}#endif /* ifndef __x86_64__ */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -