static void __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset) { struct objc_struct_layout layout; unsigned int position; const char *mtype; objc_layout_structure (type, &layout); while (objc_layout_structure_next_member (&layout)) { BOOL gc_invisible = NO; objc_layout_structure_get_info (&layout, &position, NULL, &mtype); /* Skip the variable name */ if (*mtype == '"') { for (mtype++; *mtype++ != '"';) /* do nothing */; } if (*mtype == _C_GCINVISIBLE) { gc_invisible = YES; mtype++; } /* Add to position the offset of this structure */ position += offset; switch (*mtype) { case _C_ID: case _C_CLASS: case _C_SEL: case _C_PTR: case _C_CHARPTR: case _C_ATOM: if (! gc_invisible) SET_BIT_FOR_OFFSET (mask, position); break; case _C_ARY_B: __objc_gc_setup_array (mask, mtype, position); break; case _C_STRUCT_B: __objc_gc_setup_struct (mask, mtype, position); break; case _C_UNION_B: __objc_gc_setup_union (mask, mtype, position); break; default: break; } } }
/* Iterates over the types in the structure that represents the class encoding and sets the bits in mask according to each ivar type. */ static void __objc_gc_type_description_from_type (GC_bitmap mask, const char *type) { struct objc_struct_layout layout; unsigned int offset, align; const char *ivar_type; objc_layout_structure (type, &layout); while (objc_layout_structure_next_member (&layout)) { BOOL gc_invisible = NO; objc_layout_structure_get_info (&layout, &offset, &align, &ivar_type); /* Skip the variable name */ if (*ivar_type == '"') { for (ivar_type++; *ivar_type++ != '"';) /* do nothing */; } if (*ivar_type == _C_GCINVISIBLE) { gc_invisible = YES; ivar_type++; } switch (*ivar_type) { case _C_ID: case _C_CLASS: case _C_SEL: case _C_PTR: case _C_CHARPTR: if (! gc_invisible) SET_BIT_FOR_OFFSET (mask, offset); break; case _C_ARY_B: __objc_gc_setup_array (mask, ivar_type, offset); break; case _C_STRUCT_B: __objc_gc_setup_struct (mask, ivar_type, offset); break; case _C_UNION_B: __objc_gc_setup_union (mask, ivar_type, offset); break; default: break; } } }
int objc_alignof_type (const char *type) { type = objc_skip_variable_name (type); switch (*type) { case _C_BOOL: return __alignof__ (_Bool); break; case _C_ID: return __alignof__ (id); break; case _C_CLASS: return __alignof__ (Class); break; case _C_SEL: return __alignof__ (SEL); break; case _C_CHR: return __alignof__ (char); break; case _C_UCHR: return __alignof__ (unsigned char); break; case _C_SHT: return __alignof__ (short); break; case _C_USHT: return __alignof__ (unsigned short); break; case _C_INT: return __alignof__ (int); break; case _C_UINT: return __alignof__ (unsigned int); break; case _C_LNG: return __alignof__ (long); break; case _C_ULNG: return __alignof__ (unsigned long); break; case _C_LNG_LNG: return __alignof__ (long long); break; case _C_ULNG_LNG: return __alignof__ (unsigned long long); break; case _C_FLT: return __alignof__ (float); break; case _C_DBL: return __alignof__ (double); break; case _C_LNG_DBL: return __alignof__ (long double); break; case _C_PTR: case _C_ATOM: case _C_CHARPTR: return __alignof__ (char *); break; case _C_ARY_B: while (isdigit ((unsigned char)*++type)) /* do nothing */; return objc_alignof_type (type); case _C_VECTOR: { /* Skip the '!'. */ type++; /* Skip the '['. */ type++; /* Skip the size. */ while (isdigit ((unsigned char)*type)) type++; /* Skip the ','. */ type++; /* The alignment in bytes is the following number. */ return atoi (type); } case _C_STRUCT_B: case _C_UNION_B: { struct objc_struct_layout layout; unsigned int align; objc_layout_structure (type, &layout); while (objc_layout_structure_next_member (&layout)) /* do nothing */; objc_layout_finish_structure (&layout, NULL, &align); return align; } case _C_COMPLEX: { type++; /* Skip after the 'j'. */ switch (*type) { case _C_CHR: return __alignof__ (_Complex char); break; case _C_UCHR: return __alignof__ (_Complex unsigned char); break; case _C_SHT: return __alignof__ (_Complex short); break; case _C_USHT: return __alignof__ (_Complex unsigned short); break; case _C_INT: return __alignof__ (_Complex int); break; case _C_UINT: return __alignof__ (_Complex unsigned int); break; case _C_LNG: return __alignof__ (_Complex long); break; case _C_ULNG: return __alignof__ (_Complex unsigned long); break; case _C_LNG_LNG: return __alignof__ (_Complex long long); break; case _C_ULNG_LNG: return __alignof__ (_Complex unsigned long long); break; case _C_FLT: return __alignof__ (_Complex float); break; case _C_DBL: return __alignof__ (_Complex double); break; case _C_LNG_DBL: return __alignof__ (_Complex long double); break; default: { _objc_abort ("unknown complex type %s\n", type); return 0; } } } default: { _objc_abort ("unknown type %s\n", type); return 0; } } }
int objc_sizeof_type (const char *type) { type = objc_skip_variable_name (type); switch (*type) { case _C_BOOL: return sizeof (_Bool); break; case _C_ID: return sizeof (id); break; case _C_CLASS: return sizeof (Class); break; case _C_SEL: return sizeof (SEL); break; case _C_CHR: return sizeof (char); break; case _C_UCHR: return sizeof (unsigned char); break; case _C_SHT: return sizeof (short); break; case _C_USHT: return sizeof (unsigned short); break; case _C_INT: return sizeof (int); break; case _C_UINT: return sizeof (unsigned int); break; case _C_LNG: return sizeof (long); break; case _C_ULNG: return sizeof (unsigned long); break; case _C_LNG_LNG: return sizeof (long long); break; case _C_ULNG_LNG: return sizeof (unsigned long long); break; case _C_FLT: return sizeof (float); break; case _C_DBL: return sizeof (double); break; case _C_LNG_DBL: return sizeof (long double); break; case _C_VOID: return sizeof (void); break; case _C_PTR: case _C_ATOM: case _C_CHARPTR: return sizeof (char *); break; case _C_ARY_B: { int len = atoi (type + 1); while (isdigit ((unsigned char)*++type)) ; return len * objc_aligned_size (type); } break; case _C_VECTOR: { /* Skip the '!'. */ type++; /* Skip the '['. */ type++; /* The size in bytes is the following number. */ int size = atoi (type); return size; } break; case _C_BFLD: { /* The GNU encoding of bitfields is: b 'position' 'type' 'size'. */ int position, size; int startByte, endByte; position = atoi (type + 1); while (isdigit ((unsigned char)*++type)) ; size = atoi (type + 1); startByte = position / BITS_PER_UNIT; endByte = (position + size) / BITS_PER_UNIT; return endByte - startByte; } case _C_UNION_B: case _C_STRUCT_B: { struct objc_struct_layout layout; unsigned int size; objc_layout_structure (type, &layout); while (objc_layout_structure_next_member (&layout)) /* do nothing */ ; objc_layout_finish_structure (&layout, &size, NULL); return size; } case _C_COMPLEX: { type++; /* Skip after the 'j'. */ switch (*type) { case _C_CHR: return sizeof (_Complex char); break; case _C_UCHR: return sizeof (_Complex unsigned char); break; case _C_SHT: return sizeof (_Complex short); break; case _C_USHT: return sizeof (_Complex unsigned short); break; case _C_INT: return sizeof (_Complex int); break; case _C_UINT: return sizeof (_Complex unsigned int); break; case _C_LNG: return sizeof (_Complex long); break; case _C_ULNG: return sizeof (_Complex unsigned long); break; case _C_LNG_LNG: return sizeof (_Complex long long); break; case _C_ULNG_LNG: return sizeof (_Complex unsigned long long); break; case _C_FLT: return sizeof (_Complex float); break; case _C_DBL: return sizeof (_Complex double); break; case _C_LNG_DBL: return sizeof (_Complex long double); break; default: { /* FIXME: Is this so bad that we have to abort the entire program ? (it applies to all the other _objc_abort calls in this file). */ _objc_abort ("unknown complex type %s\n", type); return 0; } } } default: { _objc_abort ("unknown type %s\n", type); return 0; } } }
int objc_sizeof_type (const char* type) { /* Skip the variable name if any */ if (*type == '"') { for (type++; *type++ != '"';) /* do nothing */; } switch(*type) { case _C_ID: return sizeof(id); break; case _C_CLASS: return sizeof(Class); break; case _C_SEL: return sizeof(SEL); break; case _C_CHR: return sizeof(char); break; case _C_UCHR: return sizeof(unsigned char); break; case _C_SHT: return sizeof(short); break; case _C_USHT: return sizeof(unsigned short); break; case _C_INT: return sizeof(int); break; case _C_UINT: return sizeof(unsigned int); break; case _C_LNG: return sizeof(long); break; case _C_ULNG: return sizeof(unsigned long); break; case _C_LNG_LNG: return sizeof(long long); break; case _C_ULNG_LNG: return sizeof(unsigned long long); break; case _C_FLT: return sizeof(float); break; case _C_DBL: return sizeof(double); break; case _C_VOID: return sizeof(void); break; case _C_PTR: case _C_ATOM: case _C_CHARPTR: return sizeof(char*); break; case _C_ARY_B: { int len = atoi(type+1); while (isdigit(*++type)); return len*objc_aligned_size (type); } break; case _C_BFLD: { /* The new encoding of bitfields is: b 'position' 'type' 'size' */ int position, size; int startByte, endByte; position = atoi (type + 1); while (isdigit (*++type)); size = atoi (type + 1); startByte = position / BITS_PER_UNIT; endByte = (position + size) / BITS_PER_UNIT; return endByte - startByte; } case _C_STRUCT_B: { struct objc_struct_layout layout; unsigned int size; objc_layout_structure (type, &layout); while (objc_layout_structure_next_member (&layout)) /* do nothing */ ; objc_layout_finish_structure (&layout, &size, NULL); return size; } case _C_UNION_B: { int max_size = 0; while (*type != _C_UNION_E && *type++ != '=') /* do nothing */; while (*type != _C_UNION_E) { /* Skip the variable name if any */ if (*type == '"') { for (type++; *type++ != '"';) /* do nothing */; } max_size = MAX (max_size, objc_sizeof_type (type)); type = objc_skip_typespec (type); } return max_size; } default: { objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type); return 0; } } }
int objc_alignof_type(const char* type) { /* Skip the variable name if any */ if (*type == '"') { for (type++; *type++ != '"';) /* do nothing */; } switch(*type) { case _C_ID: return __alignof__(id); break; case _C_CLASS: return __alignof__(Class); break; case _C_SEL: return __alignof__(SEL); break; case _C_CHR: return __alignof__(char); break; case _C_UCHR: return __alignof__(unsigned char); break; case _C_SHT: return __alignof__(short); break; case _C_USHT: return __alignof__(unsigned short); break; case _C_INT: return __alignof__(int); break; case _C_UINT: return __alignof__(unsigned int); break; case _C_LNG: return __alignof__(long); break; case _C_ULNG: return __alignof__(unsigned long); break; case _C_LNG_LNG: return __alignof__(long long); break; case _C_ULNG_LNG: return __alignof__(unsigned long long); break; case _C_FLT: return __alignof__(float); break; case _C_DBL: return __alignof__(double); break; case _C_PTR: case _C_ATOM: case _C_CHARPTR: return __alignof__(char*); break; case _C_ARY_B: while (isdigit(*++type)) /* do nothing */; return objc_alignof_type (type); case _C_STRUCT_B: { struct objc_struct_layout layout; unsigned int align; objc_layout_structure (type, &layout); while (objc_layout_structure_next_member (&layout)) /* do nothing */; objc_layout_finish_structure (&layout, NULL, &align); return align; } case _C_UNION_B: { int maxalign = 0; while (*type != _C_UNION_E && *type++ != '=') /* do nothing */; while (*type != _C_UNION_E) { /* Skip the variable name if any */ if (*type == '"') { for (type++; *type++ != '"';) /* do nothing */; } maxalign = MAX (maxalign, objc_alignof_type (type)); type = objc_skip_typespec (type); } return maxalign; } default: { objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type); return 0; } } }