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

📄 ffi_darwin.c

📁 gcc的组建
💻 C
📖 第 1 页 / 共 2 页
字号:
			    unsigned, unsigned,			    /*@out@*/ unsigned *,			    void (*fn)(),			    void (*fn2)());/*@=declundef@*//*@=exportheader@*/void ffi_call(/*@dependent@*/ ffi_cif *cif,	      void (*fn)(),	      /*@out@*/ void *rvalue,	      /*@dependent@*/ void **avalue){  extended_cif ecif;  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) &&      (cif->rtype->type == FFI_TYPE_STRUCT))    {      /*@-sysunrecog@*/      ecif.rvalue = alloca(cif->rtype->size);      /*@=sysunrecog@*/    }  else    ecif.rvalue = rvalue;  switch (cif->abi)    {    case FFI_AIX:      /*@-usedef@*/      ffi_call_AIX(&ecif, -cif->bytes,		   cif->flags, ecif.rvalue, fn, ffi_prep_args);      /*@=usedef@*/      break;    case FFI_DARWIN:      /*@-usedef@*/      ffi_call_DARWIN(&ecif, -cif->bytes,		      cif->flags, ecif.rvalue, fn, ffi_prep_args);      /*@=usedef@*/      break;    default:      FFI_ASSERT(0);      break;    }}static void flush_icache(char *);static void flush_range(char *, int);/* The layout of a function descriptor.  A C function pointer really   points to one of these.  */typedef struct aix_fd_struct {  void *code_pointer;  void *toc;} aix_fd;/* here I'd like to add the stack frame layout we use in darwin_closure.S   and aix_clsoure.S   SP previous -> +---------------------------------------+ <--- child frame		  | back chain to caller 4                |		  +---------------------------------------+ 4		  | saved CR 4                            |		  +---------------------------------------+ 8		  | saved LR 4                            |		  +---------------------------------------+ 12		  | reserved for compilers 4              |		  +---------------------------------------+ 16		  | reserved for binders 4                |		  +---------------------------------------+ 20		  | saved TOC pointer 4                   |		  +---------------------------------------+ 24		  | always reserved 8*4=32 (previous GPRs)|		  | according to the linkage convention   |		  | from AIX                              |		  +---------------------------------------+ 56		  | our FPR area 13*8=104                 |		  | f1                                    |		  | .                                     |		  | f13                                   |		  +---------------------------------------+ 160		  | result area 8                         |		  +---------------------------------------+ 168		  | alignement to the next multiple of 16 |SP current -->    +---------------------------------------+ 176 <- parent frame		  | back chain to caller 4                |		  +---------------------------------------+ 180		  | saved CR 4                            |		  +---------------------------------------+ 184		  | saved LR 4                            |		  +---------------------------------------+ 188		  | reserved for compilers 4              |		  +---------------------------------------+ 192		  | reserved for binders 4                |		  +---------------------------------------+ 196		  | saved TOC pointer 4                   |		  +---------------------------------------+ 200		  | always reserved 8*4=32  we store our  |		  | GPRs here                             |		  | r3                                    |		  | .                                     |		  | r10                                   |		  +---------------------------------------+ 232		  | overflow part                         |		  +---------------------------------------+ xxx		  | ????                                  |		  +---------------------------------------+ xxx*/ffi_statusffi_prep_closure (ffi_closure* closure,		  ffi_cif* cif,		  void (*fun)(ffi_cif*, void*, void**, void*),		  void *user_data){  unsigned int *tramp;  struct ffi_aix_trampoline_struct *tramp_aix;  aix_fd *fd;  switch (cif->abi)    {    case FFI_DARWIN:      FFI_ASSERT (cif->abi == FFI_DARWIN);      tramp = (unsigned int *) &closure->tramp[0];      tramp[0] = 0x7c0802a6;  /*   mflr    r0  */      tramp[1] = 0x429f000d;  /*   bcl-    20,4*cr7+so,0x10  */      tramp[4] = 0x7d6802a6;  /*   mflr    r11  */      tramp[5] = 0x818b0000;  /*   lwz     r12,0(r11) function address  */      tramp[6] = 0x7c0803a6;  /*   mtlr    r0   */      tramp[7] = 0x7d8903a6;  /*   mtctr   r12  */      tramp[8] = 0x816b0004;  /*   lwz     r11,4(r11) static chain  */      tramp[9] = 0x4e800420;  /*   bctr  */      tramp[2] = (unsigned long) ffi_closure_ASM; /* function  */      tramp[3] = (unsigned long) closure; /* context  */      closure->cif = cif;      closure->fun = fun;      closure->user_data = user_data;      /* Flush the icache. Only necessary on Darwin.  */      flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);      break;    case FFI_AIX:      tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);      fd = (aix_fd *)(void *)ffi_closure_ASM;      FFI_ASSERT (cif->abi == FFI_AIX);      tramp_aix->code_pointer = fd->code_pointer;      tramp_aix->toc = fd->toc;      tramp_aix->static_chain = closure;      closure->cif = cif;      closure->fun = fun;      closure->user_data = user_data;    default:      FFI_ASSERT(0);      break;    }  return FFI_OK;}static voidflush_icache(char *addr){#ifndef _AIX  __asm__ volatile (		"dcbf 0,%0\n"		"\tsync\n"		"\ticbi 0,%0\n"		"\tsync\n"		"\tisync"		: : "r"(addr) : "memory");#endif}static voidflush_range(char * addr1, int size){#define MIN_LINE_SIZE 32  int i;  for (i = 0; i < size; i += MIN_LINE_SIZE)    flush_icache(addr1+i);  flush_icache(addr1+size-1);}typedef union{  float f;  double d;} ffi_dblfl;int ffi_closure_helper_DARWIN (ffi_closure*, void*,			       unsigned long*, ffi_dblfl*);/* Basically the trampoline invokes ffi_closure_ASM, and on   entry, r11 holds the address of the closure.   After storing the registers that could possibly contain   parameters to be passed into the stack frame and setting   up space for a return value, ffi_closure_ASM invokes the   following helper function to do most of the work.  */int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,			       unsigned long * pgr, ffi_dblfl * pfr){  /* rvalue is the pointer to space for return value in closure assembly     pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM     pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM.  */  typedef double ldbits[2];  union ldu  {    ldbits lb;    long double ld;  };  void **          avalue;  ffi_type **      arg_types;  long             i, avn;  long             nf;   /* number of floating registers already used.  */  long             ng;   /* number of general registers already used.  */  ffi_cif *        cif;  double           temp;  unsigned         size_al;  union ldu        temp_ld;  cif = closure->cif;  avalue = alloca(cif->nargs * sizeof(void *));  nf = 0;  ng = 0;  /* 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)    {      rvalue = (void *) *pgr;      pgr++;      ng++;    }  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:	  avalue[i] = (char *) pgr + 3;	  ng++;	  pgr++;	  break;	case FFI_TYPE_SINT16:	case FFI_TYPE_UINT16:	  avalue[i] = (char *) pgr + 2;	  ng++;	  pgr++;	  break;	case FFI_TYPE_SINT32:	case FFI_TYPE_UINT32:	case FFI_TYPE_POINTER:	  avalue[i] = pgr;	  ng++;	  pgr++;	  break;	case FFI_TYPE_STRUCT:	  /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,	     SI 4 bytes) are aligned as if they were those modes.  */	  size_al = arg_types[i]->size;	  /* If the first member of the struct is a double, then align	     the struct to double-word.	     Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3.  */	  if (arg_types[i]->elements[0]->type == 3)	    size_al = ALIGN(arg_types[i]->size, 8);	  if (size_al < 3 && cif->abi == FFI_DARWIN)	    avalue[i] = (void*) pgr + 4 - size_al;	  else	    avalue[i] = (void*) pgr;	  ng += (size_al + 3) / 4;	  pgr += (size_al + 3) / 4;	  break;	case FFI_TYPE_SINT64:	case FFI_TYPE_UINT64:	  /* Long long ints are passed in two gpr's.  */	  avalue[i] = pgr;	  ng += 2;	  pgr += 2;	  break;	case FFI_TYPE_FLOAT:	  /* A float value consumes a GPR.	     There are 13 64bit floating point registers.  */	  if (nf < NUM_FPR_ARG_REGISTERS)	    {	      temp = pfr->d;	      pfr->f = (float)temp;	      avalue[i] = pfr;	      pfr++;	    }	  else	    {	      avalue[i] = pgr;	    }	  nf++;	  ng++;	  pgr++;	  break;	case FFI_TYPE_DOUBLE:	  /* A double value consumes two GPRs.	     There are 13 64bit floating point registers.  */	  if (nf < NUM_FPR_ARG_REGISTERS)	    {	      avalue[i] = pfr;	      pfr++;	    }	  else	    {	      avalue[i] = pgr;	    }	  nf++;	  ng += 2;	  pgr += 2;	  break;#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE	case FFI_TYPE_LONGDOUBLE:	  /* A long double value consumes four GPRs and two FPRs.	     There are 13 64bit floating point registers.  */	  if (nf < NUM_FPR_ARG_REGISTERS - 1)	    {	      avalue[i] = pfr;	      pfr += 2;	    }	  /* Here we have the situation where one part of the long double	     is stored in fpr13 and the other part is already on the stack.	     We use a union to pass the long double to avalue[i].  */	  else if (nf == NUM_FPR_ARG_REGISTERS - 1)	    {	      memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));	      memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));	      avalue[i] = &temp_ld.ld;	    }	  else	    {	      avalue[i] = pgr;	    }	  nf += 2;	  ng += 4;	  pgr += 4;	  break;#endif	default:	  FFI_ASSERT(0);	}      i++;    }  (closure->fun) (cif, rvalue, avalue, closure->user_data);  /* Tell ffi_closure_ASM to perform return type promotions.  */  return cif->rtype->type;}

⌨️ 快捷键说明

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