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

     1  /* -----------------------------------------------------------------------
     2     ffi.c - Copyright (c) 2002-2008, 2012 Kaz Kojima
     3             Copyright (c) 2008 Red Hat, Inc.
     4     
     5     SuperH Foreign Function Interface 
     6  
     7     Permission is hereby granted, free of charge, to any person obtaining
     8     a copy of this software and associated documentation files (the
     9     ``Software''), to deal in the Software without restriction, including
    10     without limitation the rights to use, copy, modify, merge, publish,
    11     distribute, sublicense, and/or sell copies of the Software, and to
    12     permit persons to whom the Software is furnished to do so, subject to
    13     the following conditions:
    14  
    15     The above copyright notice and this permission notice shall be included
    16     in all copies or substantial portions of the Software.
    17  
    18     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
    19     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    20     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    21     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    22     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    23     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    24     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    25     DEALINGS IN THE SOFTWARE.
    26     ----------------------------------------------------------------------- */
    27  
    28  #include <ffi.h>
    29  #include <ffi_common.h>
    30  
    31  #include <stdlib.h>
    32  
    33  #define NGREGARG 4
    34  #if defined(__SH4__)
    35  #define NFREGARG 8
    36  #endif
    37  
    38  #if defined(__HITACHI__)
    39  #define STRUCT_VALUE_ADDRESS_WITH_ARG 1
    40  #else
    41  #define STRUCT_VALUE_ADDRESS_WITH_ARG 0
    42  #endif
    43  
    44  /* If the structure has essentially an unique element, return its type.  */
    45  static int
    46  simple_type (ffi_type *arg)
    47  {
    48    if (arg->type != FFI_TYPE_STRUCT)
    49      return arg->type;
    50    else if (arg->elements[1])
    51      return FFI_TYPE_STRUCT;
    52  
    53    return simple_type (arg->elements[0]);
    54  }
    55  
    56  static int
    57  return_type (ffi_type *arg)
    58  {
    59    unsigned short type;
    60  
    61    if (arg->type != FFI_TYPE_STRUCT)
    62      return arg->type;
    63  
    64    type = simple_type (arg->elements[0]);
    65    if (! arg->elements[1])
    66      {
    67        switch (type)
    68  	{
    69  	case FFI_TYPE_SINT8:
    70  	case FFI_TYPE_UINT8:
    71  	case FFI_TYPE_SINT16:
    72  	case FFI_TYPE_UINT16:
    73  	case FFI_TYPE_SINT32:
    74  	case FFI_TYPE_UINT32:
    75  	  return FFI_TYPE_INT;
    76  
    77  	default:
    78  	  return type;
    79  	}
    80      }
    81  
    82    /* gcc uses r0/r1 pair for some kind of structures.  */
    83    if (arg->size <= 2 * sizeof (int))
    84      {
    85        int i = 0;
    86        ffi_type *e;
    87  
    88        while ((e = arg->elements[i++]))
    89  	{
    90  	  type = simple_type (e);
    91  	  switch (type)
    92  	    {
    93  	    case FFI_TYPE_SINT32:
    94  	    case FFI_TYPE_UINT32:
    95  	    case FFI_TYPE_INT:
    96  	    case FFI_TYPE_FLOAT:
    97  	      return FFI_TYPE_UINT64;
    98  
    99  	    default:
   100  	      break;
   101  	    }
   102  	}
   103      }
   104  
   105    return FFI_TYPE_STRUCT;
   106  }
   107  
   108  /* ffi_prep_args is called by the assembly routine once stack space
   109     has been allocated for the function's arguments */
   110  
   111  void ffi_prep_args(char *stack, extended_cif *ecif)
   112  {
   113    register unsigned int i;
   114    register int tmp;
   115    register unsigned int avn;
   116    register void **p_argv;
   117    register char *argp;
   118    register ffi_type **p_arg;
   119    int greg, ireg;
   120  #if defined(__SH4__)
   121    int freg = 0;
   122  #endif
   123  
   124    tmp = 0;
   125    argp = stack;
   126  
   127    if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
   128      {
   129        *(void **) argp = ecif->rvalue;
   130        argp += 4;
   131        ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
   132      }
   133    else
   134      ireg = 0;
   135  
   136    /* Set arguments for registers.  */
   137    greg = ireg;
   138    avn = ecif->cif->nargs;
   139    p_argv = ecif->avalue;
   140  
   141    for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
   142      {
   143        size_t z;
   144  
   145        z = (*p_arg)->size;
   146        if (z < sizeof(int))
   147  	{
   148  	  if (greg++ >= NGREGARG)
   149  	    continue;
   150  
   151  	  z = sizeof(int);
   152  	  switch ((*p_arg)->type)
   153  	    {
   154  	    case FFI_TYPE_SINT8:
   155  	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
   156  	      break;
   157    
   158  	    case FFI_TYPE_UINT8:
   159  	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
   160  	      break;
   161    
   162  	    case FFI_TYPE_SINT16:
   163  	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
   164  	      break;
   165    
   166  	    case FFI_TYPE_UINT16:
   167  	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
   168  	      break;
   169    
   170  	    case FFI_TYPE_STRUCT:
   171  	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
   172  	      break;
   173  
   174  	    default:
   175  	      FFI_ASSERT(0);
   176  	    }
   177  	  argp += z;
   178  	}
   179        else if (z == sizeof(int))
   180  	{
   181  #if defined(__SH4__)
   182  	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
   183  	    {
   184  	      if (freg++ >= NFREGARG)
   185  		continue;
   186  	    }
   187  	  else
   188  #endif
   189  	    {
   190  	      if (greg++ >= NGREGARG)
   191  		continue;
   192  	    }
   193  	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
   194  	  argp += z;
   195  	}
   196  #if defined(__SH4__)
   197        else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
   198  	{
   199  	  if (freg + 1 >= NFREGARG)
   200  	    continue;
   201  	  freg = (freg + 1) & ~1;
   202  	  freg += 2;
   203  	  memcpy (argp, *p_argv, z);
   204  	  argp += z;
   205  	}
   206  #endif
   207        else
   208  	{
   209  	  int n = (z + sizeof (int) - 1) / sizeof (int);
   210  #if defined(__SH4__)
   211  	  if (greg + n - 1 >= NGREGARG)
   212  	    continue;
   213  #else
   214  	  if (greg >= NGREGARG)
   215  	    continue;
   216  #endif
   217  	  greg += n;
   218  	  memcpy (argp, *p_argv, z);
   219  	  argp += n * sizeof (int);
   220  	}
   221      }
   222  
   223    /* Set arguments on stack.  */
   224    greg = ireg;
   225  #if defined(__SH4__)
   226    freg = 0;
   227  #endif
   228    p_argv = ecif->avalue;
   229  
   230    for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
   231      {
   232        size_t z;
   233  
   234        z = (*p_arg)->size;
   235        if (z < sizeof(int))
   236  	{
   237  	  if (greg++ < NGREGARG)
   238  	    continue;
   239  
   240  	  z = sizeof(int);
   241  	  switch ((*p_arg)->type)
   242  	    {
   243  	    case FFI_TYPE_SINT8:
   244  	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
   245  	      break;
   246    
   247  	    case FFI_TYPE_UINT8:
   248  	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
   249  	      break;
   250    
   251  	    case FFI_TYPE_SINT16:
   252  	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
   253  	      break;
   254    
   255  	    case FFI_TYPE_UINT16:
   256  	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
   257  	      break;
   258    
   259  	    case FFI_TYPE_STRUCT:
   260  	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
   261  	      break;
   262  
   263  	    default:
   264  	      FFI_ASSERT(0);
   265  	    }
   266  	  argp += z;
   267  	}
   268        else if (z == sizeof(int))
   269  	{
   270  #if defined(__SH4__)
   271  	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
   272  	    {
   273  	      if (freg++ < NFREGARG)
   274  		continue;
   275  	    }
   276  	  else
   277  #endif
   278  	    {
   279  	      if (greg++ < NGREGARG)
   280  		continue;
   281  	    }
   282  	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
   283  	  argp += z;
   284  	}
   285  #if defined(__SH4__)
   286        else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
   287  	{
   288  	  if (freg + 1 < NFREGARG)
   289  	    {
   290  	      freg = (freg + 1) & ~1;
   291  	      freg += 2;
   292  	      continue;
   293  	    }
   294  	  memcpy (argp, *p_argv, z);
   295  	  argp += z;
   296  	}
   297  #endif
   298        else
   299  	{
   300  	  int n = (z + sizeof (int) - 1) / sizeof (int);
   301  	  if (greg + n - 1 < NGREGARG)
   302  	    {
   303  	      greg += n;
   304  	      continue;
   305  	    }
   306  #if (! defined(__SH4__))
   307  	  else if (greg < NGREGARG)
   308  	    {
   309  	      greg = NGREGARG;
   310  	      continue;
   311  	    }
   312  #endif
   313  	  memcpy (argp, *p_argv, z);
   314  	  argp += n * sizeof (int);
   315  	}
   316      }
   317  
   318    return;
   319  }
   320  
   321  /* Perform machine dependent cif processing */
   322  ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
   323  {
   324    int i, j;
   325    int size, type;
   326    int n, m;
   327    int greg;
   328  #if defined(__SH4__)
   329    int freg = 0;
   330  #endif
   331  
   332    cif->flags = 0;
   333  
   334    greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
   335  	  STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
   336  
   337  #if defined(__SH4__)
   338    for (i = j = 0; i < cif->nargs && j < 12; i++)
   339      {
   340        type = (cif->arg_types)[i]->type;
   341        switch (type)
   342  	{
   343  	case FFI_TYPE_FLOAT:
   344  	  if (freg >= NFREGARG)
   345  	    continue;
   346  	  freg++;
   347  	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
   348  	  j++;
   349  	  break;
   350  
   351  	case FFI_TYPE_DOUBLE:
   352  	  if ((freg + 1) >= NFREGARG)
   353  	    continue;
   354  	  freg = (freg + 1) & ~1;
   355  	  freg += 2;
   356  	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
   357  	  j++;
   358  	  break;
   359  	      
   360  	default:
   361  	  size = (cif->arg_types)[i]->size;
   362  	  n = (size + sizeof (int) - 1) / sizeof (int);
   363  	  if (greg + n - 1 >= NGREGARG)
   364  		continue;
   365  	  greg += n;
   366  	  for (m = 0; m < n; m++)
   367  	    cif->flags += FFI_TYPE_INT << (2 * j++);
   368  	  break;
   369  	}
   370      }
   371  #else
   372    for (i = j = 0; i < cif->nargs && j < 4; i++)
   373      {
   374        size = (cif->arg_types)[i]->size;
   375        n = (size + sizeof (int) - 1) / sizeof (int);
   376        if (greg >= NGREGARG)
   377  	continue;
   378        else if (greg + n - 1 >= NGREGARG)
   379  	n = NGREGARG - greg;
   380        greg += n;
   381        for (m = 0; m < n; m++)
   382          cif->flags += FFI_TYPE_INT << (2 * j++);
   383      }
   384  #endif
   385  
   386    /* Set the return type flag */
   387    switch (cif->rtype->type)
   388      {
   389      case FFI_TYPE_STRUCT:
   390        cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
   391        break;
   392  
   393      case FFI_TYPE_VOID:
   394      case FFI_TYPE_FLOAT:
   395      case FFI_TYPE_DOUBLE:
   396      case FFI_TYPE_SINT64:
   397      case FFI_TYPE_UINT64:
   398        cif->flags += (unsigned) cif->rtype->type << 24;
   399        break;
   400  
   401      default:
   402        cif->flags += FFI_TYPE_INT << 24;
   403        break;
   404      }
   405  
   406    return FFI_OK;
   407  }
   408  
   409  extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
   410  			  unsigned, unsigned, unsigned *, void (*fn)(void));
   411  
   412  void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
   413  {
   414    extended_cif ecif;
   415    UINT64 trvalue;
   416  
   417    ecif.cif = cif;
   418    ecif.avalue = avalue;
   419    
   420    /* If the return value is a struct and we don't have a return	*/
   421    /* value address then we need to make one		        */
   422  
   423    if (cif->rtype->type == FFI_TYPE_STRUCT
   424        && return_type (cif->rtype) != FFI_TYPE_STRUCT)
   425      ecif.rvalue = &trvalue;
   426    else if ((rvalue == NULL) && 
   427        (cif->rtype->type == FFI_TYPE_STRUCT))
   428      {
   429        ecif.rvalue = alloca(cif->rtype->size);
   430      }
   431    else
   432      ecif.rvalue = rvalue;
   433  
   434    switch (cif->abi) 
   435      {
   436      case FFI_SYSV:
   437        ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
   438  		    fn);
   439        break;
   440      default:
   441        FFI_ASSERT(0);
   442        break;
   443      }
   444  
   445    if (rvalue
   446        && cif->rtype->type == FFI_TYPE_STRUCT
   447        && return_type (cif->rtype) != FFI_TYPE_STRUCT)
   448      memcpy (rvalue, &trvalue, cif->rtype->size);
   449  }
   450  
   451  extern void ffi_closure_SYSV (void);
   452  #if defined(__SH4__)
   453  extern void __ic_invalidate (void *line);
   454  #endif
   455  
   456  ffi_status
   457  ffi_prep_closure_loc (ffi_closure* closure,
   458  		      ffi_cif* cif,
   459  		      void (*fun)(ffi_cif*, void*, void**, void*),
   460  		      void *user_data,
   461  		      void *codeloc)
   462  {
   463    unsigned int *tramp;
   464    unsigned int insn;
   465  
   466    if (cif->abi != FFI_SYSV)
   467      return FFI_BAD_ABI;
   468  
   469    tramp = (unsigned int *) &closure->tramp[0];
   470    /* Set T bit if the function returns a struct pointed with R2.  */
   471    insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
   472  	  ? 0x0018 /* sett */
   473  	  : 0x0008 /* clrt */);
   474  
   475  #ifdef __LITTLE_ENDIAN__
   476    tramp[0] = 0xd301d102;
   477    tramp[1] = 0x0000412b | (insn << 16);
   478  #else
   479    tramp[0] = 0xd102d301;
   480    tramp[1] = 0x412b0000 | insn;
   481  #endif
   482    *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
   483    *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
   484  
   485    closure->cif = cif;
   486    closure->fun = fun;
   487    closure->user_data = user_data;
   488  
   489  #if defined(__SH4__)
   490    /* Flush the icache.  */
   491    __ic_invalidate(codeloc);
   492  #endif
   493  
   494    return FFI_OK;
   495  }
   496  
   497  /* Basically the trampoline invokes ffi_closure_SYSV, and on 
   498   * entry, r3 holds the address of the closure.
   499   * After storing the registers that could possibly contain
   500   * parameters to be passed into the stack frame and setting
   501   * up space for a return value, ffi_closure_SYSV invokes the 
   502   * following helper function to do most of the work.
   503   */
   504  
   505  #ifdef __LITTLE_ENDIAN__
   506  #define OFS_INT8	0
   507  #define OFS_INT16	0
   508  #else
   509  #define OFS_INT8	3
   510  #define OFS_INT16	2
   511  #endif
   512  
   513  int
   514  ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, 
   515  			 unsigned long *pgr, unsigned long *pfr, 
   516  			 unsigned long *pst)
   517  {
   518    void **avalue;
   519    ffi_type **p_arg;
   520    int i, avn;
   521    int ireg, greg = 0;
   522  #if defined(__SH4__)
   523    int freg = 0;
   524  #endif
   525    ffi_cif *cif; 
   526  
   527    cif = closure->cif;
   528    avalue = alloca(cif->nargs * sizeof(void *));
   529  
   530    /* Copy the caller's structure return value address so that the closure
   531       returns the data directly to the caller.  */
   532    if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
   533      {
   534        rvalue = (void *) *pgr++;
   535        ireg = 1;
   536      }
   537    else
   538      ireg = 0;
   539  
   540    cif = closure->cif;
   541    greg = ireg;
   542    avn = cif->nargs;
   543  
   544    /* Grab the addresses of the arguments from the stack frame.  */
   545    for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
   546      {
   547        size_t z;
   548  
   549        z = (*p_arg)->size;
   550        if (z < sizeof(int))
   551  	{
   552  	  if (greg++ >= NGREGARG)
   553  	    continue;
   554  
   555  	  z = sizeof(int);
   556  	  switch ((*p_arg)->type)
   557  	    {
   558  	    case FFI_TYPE_SINT8:
   559  	    case FFI_TYPE_UINT8:
   560  	      avalue[i] = (((char *)pgr) + OFS_INT8);
   561  	      break;
   562    
   563  	    case FFI_TYPE_SINT16:
   564  	    case FFI_TYPE_UINT16:
   565  	      avalue[i] = (((char *)pgr) + OFS_INT16);
   566  	      break;
   567    
   568  	    case FFI_TYPE_STRUCT:
   569  	      avalue[i] = pgr;
   570  	      break;
   571  
   572  	    default:
   573  	      FFI_ASSERT(0);
   574  	    }
   575  	  pgr++;
   576  	}
   577        else if (z == sizeof(int))
   578  	{
   579  #if defined(__SH4__)
   580  	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
   581  	    {
   582  	      if (freg++ >= NFREGARG)
   583  		continue;
   584  	      avalue[i] = pfr;
   585  	      pfr++;
   586  	    }
   587  	  else
   588  #endif
   589  	    {
   590  	      if (greg++ >= NGREGARG)
   591  		continue;
   592  	      avalue[i] = pgr;
   593  	      pgr++;
   594  	    }
   595  	}
   596  #if defined(__SH4__)
   597        else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
   598  	{
   599  	  if (freg + 1 >= NFREGARG)
   600  	    continue;
   601  	  if (freg & 1)
   602  	    pfr++;
   603  	  freg = (freg + 1) & ~1;
   604  	  freg += 2;
   605  	  avalue[i] = pfr;
   606  	  pfr += 2;
   607  	}
   608  #endif
   609        else
   610  	{
   611  	  int n = (z + sizeof (int) - 1) / sizeof (int);
   612  #if defined(__SH4__)
   613  	  if (greg + n - 1 >= NGREGARG)
   614  	    continue;
   615  #else
   616  	  if (greg >= NGREGARG)
   617  	    continue;
   618  #endif
   619  	  greg += n;
   620  	  avalue[i] = pgr;
   621  	  pgr += n;
   622  	}
   623      }
   624  
   625    greg = ireg;
   626  #if defined(__SH4__)
   627    freg = 0;
   628  #endif
   629  
   630    for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
   631      {
   632        size_t z;
   633  
   634        z = (*p_arg)->size;
   635        if (z < sizeof(int))
   636  	{
   637  	  if (greg++ < NGREGARG)
   638  	    continue;
   639  
   640  	  z = sizeof(int);
   641  	  switch ((*p_arg)->type)
   642  	    {
   643  	    case FFI_TYPE_SINT8:
   644  	    case FFI_TYPE_UINT8:
   645  	      avalue[i] = (((char *)pst) + OFS_INT8);
   646  	      break;
   647    
   648  	    case FFI_TYPE_SINT16:
   649  	    case FFI_TYPE_UINT16:
   650  	      avalue[i] = (((char *)pst) + OFS_INT16);
   651  	      break;
   652    
   653  	    case FFI_TYPE_STRUCT:
   654  	      avalue[i] = pst;
   655  	      break;
   656  
   657  	    default:
   658  	      FFI_ASSERT(0);
   659  	    }
   660  	  pst++;
   661  	}
   662        else if (z == sizeof(int))
   663  	{
   664  #if defined(__SH4__)
   665  	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
   666  	    {
   667  	      if (freg++ < NFREGARG)
   668  		continue;
   669  	    }
   670  	  else
   671  #endif
   672  	    {
   673  	      if (greg++ < NGREGARG)
   674  		continue;
   675  	    }
   676  	  avalue[i] = pst;
   677  	  pst++;
   678  	}
   679  #if defined(__SH4__)
   680        else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
   681  	{
   682  	  if (freg + 1 < NFREGARG)
   683  	    {
   684  	      freg = (freg + 1) & ~1;
   685  	      freg += 2;
   686  	      continue;
   687  	    }
   688  	  avalue[i] = pst;
   689  	  pst += 2;
   690  	}
   691  #endif
   692        else
   693  	{
   694  	  int n = (z + sizeof (int) - 1) / sizeof (int);
   695  	  if (greg + n - 1 < NGREGARG)
   696  	    {
   697  	      greg += n;
   698  	      continue;
   699  	    }
   700  #if (! defined(__SH4__))
   701  	  else if (greg < NGREGARG)
   702  	    {
   703  	      greg += n;
   704  	      pst += greg - NGREGARG;
   705  	      continue;
   706  	    }
   707  #endif
   708  	  avalue[i] = pst;
   709  	  pst += n;
   710  	}
   711      }
   712  
   713    (closure->fun) (cif, rvalue, avalue, closure->user_data);
   714  
   715    /* Tell ffi_closure_SYSV how to perform return type promotions.  */
   716    return return_type (cif->rtype);
   717  }