/* The following three functions can be used to determine how a structure is laid out by the compiler. For example: struct objc_struct_layout layout; int i; objc_layout_structure (type, &layout); while (objc_layout_structure_next_member (&layout)) { int position, align; const char *type; objc_layout_structure_get_info (&layout, &position, &align, &type); printf ("element %d has offset %d, alignment %d\n", i++, position, align); } These functions are used by objc_sizeof_type and objc_alignof_type functions to compute the size and alignment of structures. The previous method of computing the size and alignment of a structure was not working on some architectures, particularly on AIX, and in the presence of bitfields inside the structure. */ void objc_layout_structure (const char *type, struct objc_struct_layout *layout) { const char *ntype; if (*type != _C_UNION_B && *type != _C_STRUCT_B) { _objc_abort ("record (or union) type expected in objc_layout_structure, got %s\n", type); } type ++; layout->original_type = type; /* Skip "<name>=" if any. Avoid embedded structures and unions. */ ntype = type; while (*ntype != _C_STRUCT_E && *ntype != _C_STRUCT_B && *ntype != _C_UNION_B && *ntype++ != '=') /* do nothing */; /* If there's a "<name>=", ntype - 1 points to '='; skip the the name */ if (*(ntype - 1) == '=') type = ntype; layout->type = type; layout->prev_type = NULL; layout->record_size = 0; layout->record_align = BITS_PER_UNIT; layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY); }
void * objc_realloc (void *mem, size_t size) { void *res = (void *)(GC_realloc (mem, size)); if (! res) _objc_abort ("Virtual memory exhausted\n"); return res; }
void * objc_atomic_malloc (size_t size) { void *res = (void *)(GC_malloc_atomic (size)); if (! res) _objc_abort ("Virtual memory exhausted\n"); return res; }
void * objc_calloc (size_t nelem, size_t size) { /* Note that GC_malloc returns cleared memory (see documentation) so there is no need to clear it. */ void *res = (void *)(GC_malloc (nelem * size)); if (! res) _objc_abort ("Virtual memory exhausted\n"); return res; }
inline const char * objc_skip_typespec (const char *type) { type = objc_skip_variable_name (type); type = objc_skip_type_qualifiers (type); switch (*type) { case _C_ID: /* An id may be annotated by the actual type if it is known with the @"ClassName" syntax */ if (*++type != '"') return type; else { while (*++type != '"') /* do nothing */; return type + 1; } /* The following are one character type codes */ case _C_CLASS: case _C_SEL: case _C_CHR: case _C_UCHR: case _C_CHARPTR: case _C_ATOM: case _C_SHT: case _C_USHT: case _C_INT: case _C_UINT: case _C_LNG: case _C_BOOL: case _C_ULNG: case _C_LNG_LNG: case _C_ULNG_LNG: case _C_FLT: case _C_DBL: case _C_LNG_DBL: case _C_VOID: case _C_UNDEF: return ++type; break; case _C_COMPLEX: return type + 2; break; case _C_ARY_B: /* skip digits, typespec and closing ']' */ while (isdigit ((unsigned char)*++type)) ; type = objc_skip_typespec (type); if (*type == _C_ARY_E) return ++type; else { _objc_abort ("bad array type %s\n", type); return 0; } case _C_VECTOR: /* Skip '!' */ type++; /* Skip '[' */ type++; /* Skip digits (size) */ while (isdigit ((unsigned char)*type)) type++; /* Skip ',' */ type++; /* Skip digits (alignment) */ while (isdigit ((unsigned char)*type)) type++; /* Skip typespec. */ type = objc_skip_typespec (type); /* Skip closing ']'. */ if (*type == _C_ARY_E) return ++type; else { _objc_abort ("bad vector type %s\n", type); return 0; } case _C_BFLD: /* The GNU encoding of bitfields is: b 'position' 'type' 'size'. */ while (isdigit ((unsigned char)*++type)) ; /* skip position */ while (isdigit ((unsigned char)*++type)) ; /* skip type and size */ return type; case _C_STRUCT_B: /* skip name, and elements until closing '}' */ while (*type != _C_STRUCT_E && *type++ != '=') ; while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); } return ++type; case _C_UNION_B: /* skip name, and elements until closing ')' */ while (*type != _C_UNION_E && *type++ != '=') ; while (*type != _C_UNION_E) { type = objc_skip_typespec (type); } return ++type; case _C_PTR: /* Just skip the following typespec */ return objc_skip_typespec (++type); default: { _objc_abort ("unknown type %s\n", type); return 0; } } }
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; } } }