Annotation of gcc/objc/encoding.c, revision 1.1.1.2

1.1       root        1: /* Encoding of types for Objective C.
                      2:    Copyright (C) 1993 Free Software Foundation, Inc.
                      3: 
                      4: Author: Kresten Krab Thorup
                      5: 
                      6: This file is part of GNU CC.
                      7: 
                      8: GNU CC is free software; you can redistribute it and/or modify
                      9: it under the terms of the GNU General Public License as published by
                     10: the Free Software Foundation; either version 2, or (at your option)
                     11: any later version.
                     12: 
                     13: GNU CC is distributed in the hope that it will be useful,
                     14: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16: GNU General Public License for more details.
                     17: 
                     18: You should have received a copy of the GNU General Public License
                     19: along with GNU CC; see the file COPYING.  If not, write to
                     20: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     21: 
                     22: /* As a special exception, if you link this library with files
                     23:    compiled with GCC to produce an executable, this does not cause
                     24:    the resulting executable to be covered by the GNU General Public License.
                     25:    This exception does not however invalidate any other reasons why
                     26:    the executable file might be covered by the GNU General Public License.  */
                     27: 
                     28: #include "encoding.h"
                     29: 
                     30: #define MAX(X, Y)                    \
                     31:   ({ typeof(X) __x = (X), __y = (Y); \
                     32:      (__x > __y ? __x : __y); })
                     33: 
                     34: #define MIN(X, Y)                    \
                     35:   ({ typeof(X) __x = (X), __y = (Y); \
                     36:      (__x < __y ? __x : __y); })
                     37: 
1.1.1.2 ! root       38: #define ROUND(V, A) \
        !            39:   ({ typeof(V) __v=(V); typeof(A) __a=(A); \
        !            40:      __a*((__v+__a-1)/__a); })
        !            41: 
1.1       root       42: 
                     43: static inline int
                     44: atoi (const char* str)
                     45: {
                     46:   int res = 0;
                     47:   
                     48:   while (isdigit (*str))
                     49:     res *= 10, res += (*str++ - '0');
                     50: 
                     51:   return res;
                     52: }
                     53: 
                     54: /*
                     55:   return the size of an object specified by type 
                     56: */
                     57: 
                     58: int
                     59: objc_sizeof_type(const char* type)
                     60: {
                     61:   switch(*type) {
                     62:   case _C_ID:
                     63:     return sizeof(id);
                     64:     break;
                     65: 
                     66:   case _C_CLASS:
                     67:     return sizeof(Class*);
                     68:     break;
                     69: 
                     70:   case _C_SEL:
                     71:     return sizeof(SEL);
                     72:     break;
                     73: 
                     74:   case _C_CHR:
                     75:     return sizeof(char);
                     76:     break;
                     77:     
                     78:   case _C_UCHR:
                     79:     return sizeof(unsigned char);
                     80:     break;
                     81: 
                     82:   case _C_SHT:
                     83:     return sizeof(short);
                     84:     break;
                     85: 
                     86:   case _C_USHT:
                     87:     return sizeof(unsigned short);
                     88:     break;
                     89: 
                     90:   case _C_INT:
                     91:     return sizeof(int);
                     92:     break;
                     93: 
                     94:   case _C_UINT:
                     95:     return sizeof(unsigned int);
                     96:     break;
                     97: 
                     98:   case _C_LNG:
                     99:     return sizeof(long);
                    100:     break;
                    101: 
                    102:   case _C_ULNG:
                    103:     return sizeof(unsigned long);
                    104:     break;
                    105: 
1.1.1.2 ! root      106:   case _C_FLT:
        !           107:     return sizeof(float);
        !           108:     break;
        !           109: 
        !           110:   case _C_DBL:
        !           111:     return sizeof(double);
        !           112:     break;
        !           113: 
1.1       root      114:   case _C_PTR:
                    115:   case _C_ATOM:
                    116:   case _C_CHARPTR:
                    117:     return sizeof(char*);
                    118:     break;
                    119: 
                    120:   case _C_ARY_B:
                    121:     {
                    122:       int len = atoi(type+1);
                    123:       while (isdigit(*++type));
                    124:       return len*objc_aligned_size (type);
                    125:     }
                    126:     break; 
                    127: 
                    128:   case _C_STRUCT_B:
                    129:     {
                    130:       int acc_size = 0;
                    131:       int align;
                    132:       while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
1.1.1.2 ! root      133:       while (*type != _C_STRUCT_E)
1.1       root      134:        {
                    135:          align = objc_alignof_type (type);       /* padd to alignment */
1.1.1.2 ! root      136:          acc_size = ROUND (acc_size, align);
1.1       root      137:          acc_size += objc_sizeof_type (type);   /* add component size */
                    138:          type = objc_skip_typespec (type);              /* skip component */
                    139:        }
                    140:       return acc_size;
                    141:     }
                    142: 
                    143:   case _C_UNION_B:
                    144:     {
                    145:       int max_size = 0;
                    146:       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
                    147:       while (*type != _C_UNION_E)
                    148:        {
                    149:          max_size = MAX (max_size, objc_sizeof_type (type));
                    150:          type = objc_skip_typespec (type);
                    151:        }
                    152:       return max_size;
                    153:     }
                    154:     
                    155:   default:
                    156:     abort();
                    157:   }
                    158: }
                    159: 
                    160: 
                    161: /*
                    162:   Return the alignment of an object specified by type 
                    163: */
                    164: 
                    165: int
                    166: objc_alignof_type(const char* type)
                    167: {
                    168:   switch(*type) {
                    169:   case _C_ID:
                    170:     return __alignof__(id);
                    171:     break;
                    172: 
                    173:   case _C_CLASS:
                    174:     return __alignof__(Class*);
                    175:     break;
                    176:     
                    177:   case _C_SEL:
                    178:     return __alignof__(SEL);
                    179:     break;
                    180: 
                    181:   case _C_CHR:
                    182:     return __alignof__(char);
                    183:     break;
                    184:     
                    185:   case _C_UCHR:
                    186:     return __alignof__(unsigned char);
                    187:     break;
                    188: 
                    189:   case _C_SHT:
                    190:     return __alignof__(short);
                    191:     break;
                    192: 
                    193:   case _C_USHT:
                    194:     return __alignof__(unsigned short);
                    195:     break;
                    196: 
                    197:   case _C_INT:
                    198:     return __alignof__(int);
                    199:     break;
                    200: 
                    201:   case _C_UINT:
                    202:     return __alignof__(unsigned int);
                    203:     break;
                    204: 
                    205:   case _C_LNG:
                    206:     return __alignof__(long);
                    207:     break;
                    208: 
                    209:   case _C_ULNG:
                    210:     return __alignof__(unsigned long);
                    211:     break;
                    212: 
1.1.1.2 ! root      213:   case _C_FLT:
        !           214:     return __alignof__(float);
        !           215:     break;
        !           216: 
        !           217:   case _C_DBL:
        !           218:     return __alignof__(double);
        !           219:     break;
        !           220: 
1.1       root      221:   case _C_ATOM:
                    222:   case _C_CHARPTR:
                    223:     return __alignof__(char*);
                    224:     break;
                    225: 
                    226:   case _C_ARY_B:
                    227:     while (isdigit(*++type)) /* do nothing */;
                    228:     return objc_alignof_type (type);
                    229:       
                    230:   case _C_STRUCT_B:
                    231:     {
                    232:       struct { int x; double y; } fooalign;
                    233:       while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
                    234:       if (*type != _C_STRUCT_E)
                    235:        return MAX (objc_alignof_type (type), __alignof__ (fooalign));
                    236:       else
                    237:        return __alignof__ (fooalign);
                    238:     }
                    239: 
                    240:   case _C_UNION_B:
                    241:     {
                    242:       int maxalign = 0;
                    243:       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
                    244:       while (*type != _C_UNION_E)
                    245:        {
                    246:          maxalign = MAX (maxalign, objc_alignof_type (type));
                    247:          type = objc_skip_typespec (type);
                    248:        }
                    249:       return maxalign;
                    250:     }
                    251:     
                    252:   default:
                    253:     abort();
                    254:   }
                    255: }
                    256: 
                    257: /*
                    258:   The aligned size if the size rounded up to the nearest alignment.
                    259: */
                    260: 
                    261: int
                    262: objc_aligned_size (const char* type)
                    263: {
                    264:   int size = objc_sizeof_type (type);
                    265:   int align = objc_alignof_type (type);
1.1.1.2 ! root      266:   return ROUND (size, align);
1.1       root      267: }
                    268: 
                    269: /*
                    270:   The size rounded up to the nearest integral of the wordsize, taken
                    271:   to be the size of a void*.
                    272: */
                    273: 
                    274: int 
                    275: objc_promoted_size (const char* type)
                    276: {
                    277:   int size = objc_sizeof_type (type);
                    278:   int wordsize = sizeof (void*);
                    279: 
1.1.1.2 ! root      280:   return ROUND (size, wordsize);
1.1       root      281: }
                    282: 
                    283: /*
                    284:   Skip type qualifiers.  These may eventually precede typespecs
                    285:   occuring in method prototype encodings.
                    286: */
                    287: 
                    288: inline const char*
                    289: objc_skip_type_qualifiers (const char* type)
                    290: {
                    291:   while (*type == _C_CONST
                    292:         || *type == _C_IN 
                    293:         || *type == _C_INOUT
                    294:         || *type == _C_OUT 
                    295:         || *type == _C_BYCOPY
                    296:         || *type == _C_ONEWAY)
                    297:     {
                    298:       type += 1;
                    299:     }
                    300:   return type;
                    301: }
                    302: 
                    303:   
                    304: /*
                    305:   Skip one typespec element.  If the typespec is prepended by type
                    306:   qualifiers, these are skipped as well.
                    307: */
                    308: 
                    309: const char* 
                    310: objc_skip_typespec (const char* type)
                    311: {
                    312:   type = objc_skip_type_qualifiers (type);
                    313:   
                    314:   switch (*type) {
                    315: 
                    316:   case _C_ID:
                    317:     /* An id may be annotated by the actual type if it is known
                    318:        with the @"ClassName" syntax */
                    319: 
                    320:     if (*++type != '"')
                    321:       return type;
                    322:     else
                    323:       {
                    324:        while (*++type != '"') /* do nothing */;
                    325:        return type + 1;
                    326:       }
                    327: 
                    328:     /* The following are one character type codes */
                    329:   case _C_CLASS:
                    330:   case _C_SEL:
                    331:   case _C_CHR:
                    332:   case _C_UCHR:
                    333:   case _C_CHARPTR:
                    334:   case _C_ATOM:
                    335:   case _C_SHT:
                    336:   case _C_USHT:
                    337:   case _C_INT:
                    338:   case _C_UINT:
                    339:   case _C_LNG:
                    340:   case _C_ULNG:
                    341:   case _C_FLT:
                    342:   case _C_DBL:
                    343:   case _C_VOID:
                    344:     return ++type;
                    345:     break;
                    346: 
                    347:   case _C_ARY_B:
                    348:     /* skip digits, typespec and closing ']' */
                    349:     
                    350:     while(isdigit(*++type));
                    351:     type = objc_skip_typespec(type);
                    352:     if (*type == _C_ARY_E)
                    353:       return ++type;
                    354:     else
                    355:       abort();
                    356: 
                    357:   case _C_STRUCT_B:
                    358:     /* skip name, and elements until closing '}'  */
                    359:     
                    360:     while (*type != _C_STRUCT_E && *type++ != '=');
                    361:     while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
                    362:     return ++type;
                    363: 
                    364:   case _C_UNION_B:
                    365:     /* skip name, and elements until closing ')'  */
                    366:     
                    367:     while (*type != _C_UNION_E && *type++ != '=');
                    368:     while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
                    369:     return ++type;
                    370: 
                    371:   case _C_PTR:
                    372:     /* Just skip the following typespec */
                    373:     
                    374:     return objc_skip_typespec (++type);
                    375:     
                    376:   default:
                    377:     abort();
                    378:   }
                    379: }
                    380: 
                    381: /*
                    382:   Skip an offset as part of a method encoding.  This is prepended by a
                    383:   '+' if the argument is passed in registers.
                    384: */
                    385: inline const char* 
                    386: objc_skip_offset (const char* type)
                    387: {
                    388:   if (*type == '+') type++;
                    389:   while(isdigit(*++type));
                    390:   return type;
                    391: }
                    392: 
                    393: /*
                    394:   Skip an argument specification of a method encoding.
                    395: */
                    396: const char*
                    397: objc_skip_argspec (const char* type)
                    398: {
                    399:   type = objc_skip_typespec (type);
                    400:   type = objc_skip_offset (type);
                    401:   return type;
                    402: }
                    403: 
                    404: /*
                    405:   Return the number of arguments that the method MTH expects.
                    406:   Note that all methods need two implicit arguments `self' and
                    407:   `_cmd'. 
                    408: */
                    409: int
                    410: method_get_number_of_arguments (struct objc_method* mth)
                    411: {
                    412:   int i = 0;
                    413:   const char* type = mth->method_types;
                    414:   while (*type)
                    415:     {
                    416:       type = objc_skip_argspec (type);
                    417:       i += 1;
                    418:     }
                    419:   return i - 1;
                    420: }
                    421: 
                    422: /*
                    423:   Return the size of the argument block needed on the stack to invoke
                    424:   the method MTH.  This may be zero, if all arguments are passed in
                    425:   registers.
                    426: */
                    427: 
                    428: int
                    429: method_get_sizeof_arguments (struct objc_method* mth)
                    430: {
                    431:   const char* type = objc_skip_typespec (mth->method_types);
                    432:   return atoi (type);
                    433: }
                    434: 
                    435: /*
                    436:   Return a pointer to the next argument of ARGFRAME.  type points to
                    437:   the last argument.  Typical use of this look like:
                    438: 
                    439:   {
                    440:     char *datum, *type; 
                    441:     for (datum = method_get_first_argument (method, argframe, &type);
                    442:          datum; datum = method_get_next_argument (argframe, &type))
                    443:       {
                    444:         unsigned flags = objc_get_type_qualifiers (type);
                    445:         type = objc_skip_type_qualifiers (type);
                    446:        if (*type != _C_PTR)
                    447:           [portal encodeData: datum ofType: type];
                    448:        else
                    449:          {
                    450:            if ((flags & _F_IN) == _F_IN)
                    451:               [portal encodeData: *(char**)datum ofType: ++type];
                    452:          }
                    453:       }
                    454:   }
                    455: */  
                    456: 
                    457: char*
                    458: method_get_next_argument (arglist_t argframe,
                    459:                          const char **type)
                    460: {
                    461:   const char *t = objc_skip_argspec (*type);
                    462: 
                    463:   if (*t == '\0')
                    464:     return 0;
                    465: 
                    466:   *type = t;
                    467:   t = objc_skip_typespec (t);
                    468: 
                    469:   if (*t == '+')
                    470:     return argframe->arg_regs + atoi (++t);
                    471:   else
                    472:     return argframe->arg_ptr + atoi (t);
                    473: }
                    474: 
                    475: /*
                    476:   Return a pointer to the value of the first argument of the method 
                    477:   described in M with the given argumentframe ARGFRAME.  The type
                    478:   is returned in TYPE.  type must be passed to successive calls of 
                    479:   method_get_next_argument.
                    480: */
                    481: char*
                    482: method_get_first_argument (struct objc_method* m,
                    483:                           arglist_t argframe, 
                    484:                           const char** type)
                    485: {
                    486:   *type = m->method_types;
                    487:   return method_get_next_argument (argframe, type);
                    488: }
                    489: 
                    490: /*
                    491:    Return a pointer to the ARGth argument of the method
                    492:    M from the frame ARGFRAME.  The type of the argument
                    493:    is returned in the value-result argument TYPE 
                    494: */
                    495: 
                    496: char*
                    497: method_get_nth_argument (struct objc_method* m,
                    498:                         arglist_t argframe, int arg, 
                    499:                         const char **type)
                    500: {
                    501:   const char* t = objc_skip_argspec (m->method_types);
                    502: 
                    503:   if (arg > method_get_number_of_arguments (m))
                    504:     return 0;
                    505: 
                    506:   while (arg--)
                    507:     t = objc_skip_argspec (t);
                    508:   
                    509:   *type = t;
                    510:   t = objc_skip_typespec (t);
                    511: 
                    512:   if (*t == '+')
                    513:     return argframe->arg_regs + atoi (++t);
                    514:   else
                    515:     return argframe->arg_ptr + atoi (t);
                    516: }
                    517: 
                    518: unsigned
                    519: objc_get_type_qualifiers (const char* type)
                    520: {
                    521:   unsigned res = 0;
                    522:   BOOL flag = YES;
                    523: 
                    524:   while (flag)
                    525:     switch (*type++)
                    526:       {
                    527:       case _C_CONST:  res |= _F_CONST; break;
                    528:       case _C_IN:     res |= _F_IN; break;
                    529:       case _C_INOUT:  res |= _F_INOUT; break;
                    530:       case _C_OUT:    res |= _F_OUT; break;
                    531:       case _C_BYCOPY: res |= _F_BYCOPY; break;
                    532:       case _C_ONEWAY: res |= _F_ONEWAY; break;
                    533:       default: flag = NO;
                    534:     }
                    535: 
                    536:   return res;
                    537: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.