(root)/
gcc-13.2.0/
gcc/
testsuite/
objc-obj-c++-shared/
objc-test-suite-next-encode-assist-impl.h
       1  #ifndef _OBJC_TEST_SUITE_NEXT_ENCODE_ASSIST_IMPL_H_
       2  #define _OBJC_TEST_SUITE_NEXT_ENCODE_ASSIST_IMPL_H_
       3  
       4  #ifdef __NEXT_RUNTIME__
       5  
       6  /* Determine which API to use.  */
       7  #include "next-abi.h"
       8  #ifdef NEXT_OBJC_USE_NEW_INTERFACE
       9  #include <objc/runtime.h>
      10  #else
      11  #include <objc/objc-runtime.h>
      12  #endif
      13  
      14  /* ---- */
      15  
      16  #undef  MAX
      17  #undef  MIN
      18  #undef  ROUND
      19  
      20  #ifdef __cplusplus
      21  #  define MAX(X, Y) ((X > Y) ? X : Y)
      22  #  define MIN(X, Y) ((X < Y) ? X : Y)
      23  #  define ROUND(V, A) (A * ((V + A - 1) / A))
      24  #else
      25  #  define MAX(X, Y)                    \
      26    ({ typeof (X) __x = (X), __y = (Y); \
      27       (__x > __y ? __x : __y); })
      28  #  define MIN(X, Y)                    \
      29    ({ typeof (X) __x = (X), __y = (Y); \
      30       (__x < __y ? __x : __y); })
      31  #  define ROUND(V, A) \
      32    ({ typeof (V) __v = (V); typeof (A) __a = (A); \
      33       __a * ((__v+__a - 1)/__a); })
      34  #endif
      35  
      36  #define BITS_PER_UNIT __CHAR_BIT__
      37  typedef struct{ char a; } __small_struct;
      38  #define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (__small_struct))
      39  
      40  /*
      41    return the size of an object specified by type
      42  */
      43  
      44  int
      45  objc_sizeof_type (const char *type)
      46  {
      47    /* Skip the variable name if any */
      48    if (*type == '"')
      49      {
      50        for (type++; *type++ != '"';)
      51  	/* do nothing */;
      52      }
      53  
      54    switch (*type) {
      55    case _C_ID:
      56      return sizeof (id);
      57      break;
      58  
      59    case _C_CLASS:
      60      return sizeof (Class);
      61      break;
      62  
      63    case _C_SEL:
      64      return sizeof (SEL);
      65      break;
      66  
      67    case _C_CHR:
      68      return sizeof (char);
      69      break;
      70  
      71    case _C_UCHR:
      72      return sizeof (unsigned char);
      73      break;
      74  
      75    case _C_SHT:
      76      return sizeof (short);
      77      break;
      78  
      79    case _C_USHT:
      80      return sizeof (unsigned short);
      81      break;
      82  
      83    case _C_INT:
      84      return sizeof (int);
      85      break;
      86  
      87    case _C_UINT:
      88      return sizeof (unsigned int);
      89      break;
      90  
      91    case _C_LNG:
      92      return sizeof (long);
      93      break;
      94  
      95    case _C_ULNG:
      96      return sizeof (unsigned long);
      97      break;
      98  
      99    case _C_LNG_LNG:
     100      return sizeof (long long);
     101      break;
     102  
     103    case _C_ULNG_LNG:
     104      return sizeof (unsigned long long);
     105      break;
     106  
     107    case _C_FLT:
     108      return sizeof (float);
     109      break;
     110  
     111    case _C_DBL:
     112      return sizeof (double);
     113      break;
     114  
     115    case _C_PTR:
     116    case _C_ATOM:
     117    case _C_CHARPTR:
     118      return sizeof (char *);
     119      break;
     120  
     121    case _C_ARY_B:
     122      {
     123        int len = atoi (type + 1);
     124        while (isdigit ((unsigned char)*++type))
     125  	;
     126        return len * objc_aligned_size (type);
     127      }
     128      break;
     129  
     130    case _C_BFLD:
     131      {
     132        /* The NeXT encoding of bitfields is _still_: b 'size' */
     133        int size = atoi (type + 1);
     134        /* Return an upper bound on byte size */
     135        return (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
     136      }
     137  
     138    case _C_STRUCT_B:
     139      {
     140        struct objc_struct_layout layout;
     141        unsigned int size;
     142  
     143        objc_layout_structure (type, &layout);
     144        while (objc_layout_structure_next_member (&layout))
     145          /* do nothing */ ;
     146        objc_layout_finish_structure (&layout, &size, NULL);
     147  
     148        return size;
     149      }
     150  
     151    case _C_UNION_B:
     152      {
     153        int max_size = 0;
     154        while (*type != _C_UNION_E && *type++ != '=')
     155  	/* do nothing */;
     156        while (*type != _C_UNION_E)
     157  	{
     158  	  /* Skip the variable name if any */
     159  	  if (*type == '"')
     160  	    {
     161  	      for (type++; *type++ != '"';)
     162  		/* do nothing */;
     163  	    }
     164  	  max_size = MAX (max_size, objc_sizeof_type (type));
     165  	  type = objc_skip_typespec (type);
     166  	}
     167        return max_size;
     168      }
     169    }
     170    return 0; /* error */
     171  }
     172  
     173  
     174  /*
     175    Return the alignment of an object specified by type
     176  */
     177  
     178  int
     179  objc_alignof_type (const char *type)
     180  {
     181    /* Skip the variable name if any */
     182    if (*type == '"')
     183      {
     184        for (type++; *type++ != '"';)
     185  	/* do nothing */;
     186      }
     187    switch (*type) {
     188    case _C_ID:
     189      return __alignof__ (id);
     190      break;
     191  
     192    case _C_CLASS:
     193      return __alignof__ (Class);
     194      break;
     195  
     196    case _C_SEL:
     197      return __alignof__ (SEL);
     198      break;
     199  
     200    case _C_CHR:
     201      return __alignof__ (char);
     202      break;
     203  
     204    case _C_UCHR:
     205      return __alignof__ (unsigned char);
     206      break;
     207  
     208    case _C_SHT:
     209      return __alignof__ (short);
     210      break;
     211  
     212    case _C_USHT:
     213      return __alignof__ (unsigned short);
     214      break;
     215  
     216    case _C_INT:
     217    case _C_BFLD: /* This is for the NeXT only */
     218      return __alignof__ (int);
     219      break;
     220  
     221    case _C_UINT:
     222      return __alignof__ (unsigned int);
     223      break;
     224  
     225    case _C_LNG:
     226      return __alignof__ (long);
     227      break;
     228  
     229    case _C_ULNG:
     230      return __alignof__ (unsigned long);
     231      break;
     232  
     233    case _C_LNG_LNG:
     234      return __alignof__ (long long);
     235      break;
     236  
     237    case _C_ULNG_LNG:
     238      return __alignof__ (unsigned long long);
     239      break;
     240  
     241    case _C_FLT:
     242      return __alignof__ (float);
     243      break;
     244  
     245    case _C_DBL:
     246      return __alignof__ (double);
     247      break;
     248  
     249    case _C_PTR:
     250    case _C_ATOM:
     251    case _C_CHARPTR:
     252      return __alignof__ (char *);
     253      break;
     254  
     255    case _C_ARY_B:
     256      while (isdigit ((unsigned char)*++type))
     257        /* do nothing */;
     258      return objc_alignof_type (type);
     259  
     260    case _C_STRUCT_B:
     261      {
     262        struct objc_struct_layout layout;
     263        unsigned int align;
     264  
     265        objc_layout_structure (type, &layout);
     266        while (objc_layout_structure_next_member (&layout))
     267          /* do nothing */;
     268        objc_layout_finish_structure (&layout, NULL, &align);
     269  
     270        return align;
     271      }
     272  
     273    case _C_UNION_B:
     274      {
     275        int maxalign = 0;
     276        while (*type != _C_UNION_E && *type++ != '=')
     277  	/* do nothing */;
     278        while (*type != _C_UNION_E)
     279  	{
     280  	  /* Skip the variable name if any */
     281  	  if (*type == '"')
     282  	    {
     283  	      for (type++; *type++ != '"';)
     284  		/* do nothing */;
     285  	    }
     286  	  maxalign = MAX (maxalign, objc_alignof_type (type));
     287  	  type = objc_skip_typespec (type);
     288  	}
     289        return maxalign;
     290      }
     291    }
     292    return 0; /* error */
     293  }
     294  
     295  /*
     296    The aligned size if the size rounded up to the nearest alignment.
     297  */
     298  
     299  int
     300  objc_aligned_size (const char *type)
     301  {
     302    int size, align;
     303  
     304    /* Skip the variable name */
     305    if (*type == '"')
     306      {
     307        for (type++; *type++ != '"';)
     308  	/* do nothing */;
     309      }
     310  
     311    size = objc_sizeof_type (type);
     312    align = objc_alignof_type (type);
     313  
     314    return ROUND (size, align);
     315  }
     316  
     317  /*
     318    The size rounded up to the nearest integral of the wordsize, taken
     319    to be the size of a void *.
     320  */
     321  
     322  int
     323  objc_promoted_size (const char *type)
     324  {
     325    int size, wordsize;
     326  
     327    /* Skip the variable name */
     328    if (*type == '"')
     329      {
     330        for (type++; *type++ != '"';)
     331  	/* do nothing */;
     332      }
     333  
     334    size = objc_sizeof_type (type);
     335    wordsize = sizeof (void *);
     336  
     337    return ROUND (size, wordsize);
     338  }
     339  
     340  /*
     341    Skip type qualifiers.  These may eventually precede typespecs
     342    occurring in method prototype encodings.
     343  */
     344  
     345  const char *
     346  objc_skip_type_qualifiers (const char *type)
     347  {
     348    while (*type == _C_CONST
     349  	 || *type == _C_IN
     350  	 || *type == _C_INOUT
     351  	 || *type == _C_OUT
     352  	 || *type == _C_BYCOPY
     353           || *type == _C_BYREF
     354  	 || *type == _C_ONEWAY
     355  	 || *type == _C_GCINVISIBLE)
     356      {
     357        type += 1;
     358      }
     359    return type;
     360  }
     361  
     362  /*
     363    Skip one typespec element.  If the typespec is prepended by type
     364    qualifiers, these are skipped as well.
     365  */
     366  
     367  const char *
     368  objc_skip_typespec (const char *type)
     369  {
     370    /* Skip the variable name if any */
     371    if (*type == '"')
     372      {
     373        for (type++; *type++ != '"';)
     374  	/* do nothing */;
     375      }
     376  
     377    type = objc_skip_type_qualifiers (type);
     378  
     379    switch (*type) {
     380  
     381    case _C_ID:
     382      /* An id may be annotated by the actual type if it is known
     383         with the @"ClassName" syntax */
     384  
     385      if (*++type != '"')
     386        return type;
     387      else
     388        {
     389  	while (*++type != '"')
     390  	  /* do nothing */;
     391  	return type + 1;
     392        }
     393  
     394      /* The following are one character type codes */
     395    case _C_CLASS:
     396    case _C_SEL:
     397    case _C_CHR:
     398    case _C_UCHR:
     399    case _C_CHARPTR:
     400    case _C_ATOM:
     401    case _C_SHT:
     402    case _C_USHT:
     403    case _C_INT:
     404    case _C_UINT:
     405    case _C_LNG:
     406    case _C_ULNG:
     407    case _C_LNG_LNG:
     408    case _C_ULNG_LNG:
     409    case _C_FLT:
     410    case _C_DBL:
     411    case _C_VOID:
     412    case _C_UNDEF:
     413      return ++type;
     414      break;
     415  
     416    case _C_ARY_B:
     417      /* skip digits, typespec and closing ']' */
     418  
     419      while (isdigit ((unsigned char)*++type))
     420        ;
     421      type = objc_skip_typespec (type);
     422      if (*type == _C_ARY_E)
     423        return ++type;
     424      else
     425        break; /* error */
     426  
     427    case _C_BFLD:
     428        /* The NeXT encoding for bitfields is _still_: b 'size' */
     429      while (isdigit ((unsigned char)*++type))
     430        ;	/* skip type and size */
     431      return type;
     432  
     433    case _C_STRUCT_B:
     434      /* skip name, and elements until closing '}'  */
     435  
     436      while (*type != _C_STRUCT_E && *type++ != '=')
     437        ;
     438      while (*type != _C_STRUCT_E)
     439        {
     440  	type = objc_skip_typespec (type);
     441        }
     442      return ++type;
     443  
     444    case _C_UNION_B:
     445      /* skip name, and elements until closing ')'  */
     446  
     447      while (*type != _C_UNION_E && *type++ != '=')
     448        ;
     449      while (*type != _C_UNION_E)
     450        {
     451  	type = objc_skip_typespec (type);
     452        }
     453      return ++type;
     454  
     455    case _C_PTR:
     456      /* Just skip the following typespec */
     457  
     458      return objc_skip_typespec (++type);
     459    }
     460    return 0; /* error */
     461  }
     462  
     463  /*
     464    Skip an offset as part of a method encoding.  This is prepended by a
     465    '+' if the argument is passed in registers.
     466  */
     467  const char *
     468  objc_skip_offset (const char *type)
     469  {
     470    if (*type == '+')
     471      type++;
     472    while (isdigit ((unsigned char) *++type))
     473      ;
     474    return type;
     475  }
     476  
     477  /*
     478    Skip an argument specification of a method encoding.
     479  */
     480  const char *
     481  objc_skip_argspec (const char *type)
     482  {
     483    type = objc_skip_typespec (type);
     484    type = objc_skip_offset (type);
     485    return type;
     486  }
     487  
     488  unsigned
     489  objc_get_type_qualifiers (const char *type)
     490  {
     491    unsigned res = 0;
     492    BOOL flag = YES;
     493  
     494    while (flag)
     495      switch (*type++)
     496        {
     497        case _C_CONST:	res |= _F_CONST; break;
     498        case _C_IN:	res |= _F_IN; break;
     499        case _C_INOUT:	res |= _F_INOUT; break;
     500        case _C_OUT:	res |= _F_OUT; break;
     501        case _C_BYCOPY:	res |= _F_BYCOPY; break;
     502        case _C_BYREF:  res |= _F_BYREF; break;
     503        case _C_ONEWAY:	res |= _F_ONEWAY; break;
     504        case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break;
     505        default: flag = NO;
     506      }
     507  
     508    return res;
     509  }
     510  
     511  
     512  /* The following three functions can be used to determine how a
     513     structure is laid out by the compiler. For example:
     514  
     515    struct objc_struct_layout layout;
     516    int i;
     517  
     518    objc_layout_structure (type, &layout);
     519    while (objc_layout_structure_next_member (&layout))
     520      {
     521        int position, align;
     522        const char *type;
     523  
     524        objc_layout_structure_get_info (&layout, &position, &align, &type);
     525        printf ("element %d has offset %d, alignment %d\n",
     526                i++, position, align);
     527      }
     528  
     529    These functions are used by objc_sizeof_type and objc_alignof_type
     530    functions to compute the size and alignment of structures. The
     531    previous method of computing the size and alignment of a structure
     532    was not working on some architectures, particularly on AIX, and in
     533    the presence of bitfields inside the structure. */
     534  void
     535  objc_layout_structure (const char *type,
     536                             struct objc_struct_layout *layout)
     537  {
     538    const char *ntype;
     539  
     540    layout->original_type = ++type;
     541  
     542    /* Skip "<name>=" if any. Avoid embedded structures and unions. */
     543    ntype = type;
     544    while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B
     545           && *ntype++ != '=')
     546      /* do nothing */;
     547  
     548    /* If there's a "<name>=", ntype - 1 points to '='; skip the name */
     549    if (*(ntype - 1) == '=')
     550      type = ntype;
     551  
     552    layout->type = type;
     553    layout->prev_type = NULL;
     554    layout->record_size = 0;
     555    layout->record_align = MAX (BITS_PER_UNIT, STRUCTURE_SIZE_BOUNDARY);
     556  }
     557  
     558  BOOL
     559  objc_layout_structure_next_member (struct objc_struct_layout *layout)
     560  {
     561    register int desired_align = 0;
     562  
     563    /* The current type without the type qualifiers */
     564    const char *type;
     565  
     566    /* Add the size of the previous field to the size of the record.  */
     567    if (layout->prev_type)
     568      {
     569        type = objc_skip_type_qualifiers (layout->prev_type);
     570  
     571        if (*type != _C_BFLD)
     572          layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
     573        else
     574  	layout->record_size += atoi (++type);
     575      }
     576  
     577    if (*layout->type == _C_STRUCT_E)
     578      return NO;
     579  
     580    /* Skip the variable name if any */
     581    if (*layout->type == '"')
     582      {
     583        for (layout->type++; *layout->type++ != '"';)
     584          /* do nothing */;
     585      }
     586  
     587    type = objc_skip_type_qualifiers (layout->type);
     588  
     589    desired_align = objc_alignof_type (type) * BITS_PER_UNIT;
     590  
     591    /* Record must have at least as much alignment as any field.
     592       Otherwise, the alignment of the field within the record
     593       is meaningless.  */
     594    layout->record_align = MAX (layout->record_align, desired_align);
     595  
     596    if (*type == _C_BFLD)
     597      {
     598        int bfld_size = atoi (++type);
     599        int int_align = __alignof__ (int) * BITS_PER_UNIT;
     600        /* If this bitfield would traverse a word alignment boundary, push it out 
     601  	 to that boundary instead.  */
     602        if (layout->record_size % int_align
     603  	  && (layout->record_size / int_align
     604  	      < (layout->record_size + bfld_size - 1) / int_align))
     605  	layout->record_size = ROUND (layout->record_size, int_align);
     606      }
     607    else if (layout->record_size % desired_align != 0)
     608      {
     609        /* We need to skip space before this field.
     610           Bump the cumulative size to multiple of field alignment.  */
     611        layout->record_size = ROUND (layout->record_size, desired_align);
     612      }
     613  
     614    /* Jump to the next field in record. */
     615  
     616    layout->prev_type = layout->type;
     617    layout->type = objc_skip_typespec (layout->type);      /* skip component */
     618  
     619    return YES;
     620  }
     621  
     622  
     623  void objc_layout_finish_structure (struct objc_struct_layout *layout,
     624                                     unsigned int *size,
     625                                     unsigned int *align)
     626  {
     627    if (layout->type && *layout->type == _C_STRUCT_E)
     628      {
     629        /* Round the size up to be a multiple of the required alignment */
     630        layout->record_size = ROUND (layout->record_size, layout->record_align);
     631        layout->type = NULL;
     632      }
     633    if (size)
     634      *size = layout->record_size / BITS_PER_UNIT;
     635    if (align)
     636      *align = layout->record_align / BITS_PER_UNIT;
     637  }
     638  
     639  
     640  void objc_layout_structure_get_info (struct objc_struct_layout *layout,
     641                                       unsigned int *offset,
     642                                       unsigned int *align,
     643                                       const char **type)
     644  {
     645    if (offset)
     646      *offset = layout->record_size / BITS_PER_UNIT;
     647    if (align)
     648      *align = layout->record_align / BITS_PER_UNIT;
     649    if (type)
     650      *type = layout->prev_type;
     651  }
     652  
     653  #endif /* __NEXT_RUNTIME__ */
     654  #endif /* _OBJC_TEST_SUITE_NEXT_ENCODE_ASSIST_IMPL_H_ */