From b783df230b06493a57c0c66219fdd77db0bdb095 Mon Sep 17 00:00:00 2001 From: Kresten Krab Thorup Date: Tue, 24 Aug 1993 10:05:25 +0000 Subject: [PATCH] Initial revision From-SVN: r5206 --- gcc/objc/encoding.c | 525 ++++++++++++++++++++++++++++++++++++++++++++ gcc/objc/encoding.h | 73 ++++++ 2 files changed, 598 insertions(+) create mode 100644 gcc/objc/encoding.c create mode 100644 gcc/objc/encoding.h diff --git a/gcc/objc/encoding.c b/gcc/objc/encoding.c new file mode 100644 index 00000000000..075d2eee5cd --- /dev/null +++ b/gcc/objc/encoding.c @@ -0,0 +1,525 @@ +/* Encoding of types for Objective C. + Copyright (C) 1993 Free Software Foundation, Inc. + +Author: Kresten Krab Thorup + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +#include "encoding.h" + +#define MAX(X, Y) \ + ({ typeof(X) __x = (X), __y = (Y); \ + (__x > __y ? __x : __y); }) + +#define MIN(X, Y) \ + ({ typeof(X) __x = (X), __y = (Y); \ + (__x < __y ? __x : __y); }) + + +static inline int +atoi (const char* str) +{ + int res = 0; + + while (isdigit (*str)) + res *= 10, res += (*str++ - '0'); + + return res; +} + +/* + return the size of an object specified by type +*/ + +int +objc_sizeof_type(const char* type) +{ + 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_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_STRUCT_B: + { + int acc_size = 0; + int align; + while (*type != _C_STRUCT_E && *type++ != '='); /* skip "=" */ + while (*type != _C_STRUCT_E); + { + align = objc_alignof_type (type); /* padd to alignment */ + if ((acc_size % align) != 0) + acc_size += align - (acc_size % align); + acc_size += objc_sizeof_type (type); /* add component size */ + type = objc_skip_typespec (type); /* skip component */ + } + return acc_size; + } + + case _C_UNION_B: + { + int max_size = 0; + while (*type != _C_UNION_E && *type++ != '=') /* do nothing */; + while (*type != _C_UNION_E) + { + max_size = MAX (max_size, objc_sizeof_type (type)); + type = objc_skip_typespec (type); + } + return max_size; + } + + default: + abort(); + } +} + + +/* + Return the alignment of an object specified by type +*/ + +int +objc_alignof_type(const char* type) +{ + 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_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 { int x; double y; } fooalign; + while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */; + if (*type != _C_STRUCT_E) + return MAX (objc_alignof_type (type), __alignof__ (fooalign)); + else + return __alignof__ (fooalign); + } + + case _C_UNION_B: + { + int maxalign = 0; + while (*type != _C_UNION_E && *type++ != '=') /* do nothing */; + while (*type != _C_UNION_E) + { + maxalign = MAX (maxalign, objc_alignof_type (type)); + type = objc_skip_typespec (type); + } + return maxalign; + } + + default: + abort(); + } +} + +/* + The aligned size if the size rounded up to the nearest alignment. +*/ + +int +objc_aligned_size (const char* type) +{ + int size = objc_sizeof_type (type); + int align = objc_alignof_type (type); + + if ((size % align) != 0) + return size + align - (size % align); + else + return size; +} + +/* + The size rounded up to the nearest integral of the wordsize, taken + to be the size of a void*. +*/ + +int +objc_promoted_size (const char* type) +{ + int size = objc_sizeof_type (type); + int wordsize = sizeof (void*); + + if ((size % wordsize) != 0) + return size + wordsize - (size % wordsize); + else + return size; +} + +/* + Skip type qualifiers. These may eventually precede typespecs + occuring in method prototype encodings. +*/ + +inline const char* +objc_skip_type_qualifiers (const char* type) +{ + while (*type == _C_CONST + || *type == _C_IN + || *type == _C_INOUT + || *type == _C_OUT + || *type == _C_BYCOPY + || *type == _C_ONEWAY) + { + type += 1; + } + return type; +} + + +/* + Skip one typespec element. If the typespec is prepended by type + qualifiers, these are skipped as well. +*/ + +const char* +objc_skip_typespec (const char* 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_ULNG: + case _C_FLT: + case _C_DBL: + case _C_VOID: + return ++type; + break; + + case _C_ARY_B: + /* skip digits, typespec and closing ']' */ + + while(isdigit(*++type)); + type = objc_skip_typespec(type); + if (*type == _C_ARY_E) + return ++type; + else + abort(); + + 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: + abort(); + } +} + +/* + Skip an offset as part of a method encoding. This is prepended by a + '+' if the argument is passed in registers. +*/ +inline const char* +objc_skip_offset (const char* type) +{ + if (*type == '+') type++; + while(isdigit(*++type)); + return type; +} + +/* + Skip an argument specification of a method encoding. +*/ +const char* +objc_skip_argspec (const char* type) +{ + type = objc_skip_typespec (type); + type = objc_skip_offset (type); + return type; +} + +/* + Return the number of arguments that the method MTH expects. + Note that all methods need two implicit arguments `self' and + `_cmd'. +*/ +int +method_get_number_of_arguments (struct objc_method* mth) +{ + int i = 0; + const char* type = mth->method_types; + while (*type) + { + type = objc_skip_argspec (type); + i += 1; + } + return i - 1; +} + +/* + Return the size of the argument block needed on the stack to invoke + the method MTH. This may be zero, if all arguments are passed in + registers. +*/ + +int +method_get_sizeof_arguments (struct objc_method* mth) +{ + const char* type = objc_skip_typespec (mth->method_types); + return atoi (type); +} + +/* + Return a pointer to the next argument of ARGFRAME. type points to + the last argument. Typical use of this look like: + + { + char *datum, *type; + for (datum = method_get_first_argument (method, argframe, &type); + datum; datum = method_get_next_argument (argframe, &type)) + { + unsigned flags = objc_get_type_qualifiers (type); + type = objc_skip_type_qualifiers (type); + if (*type != _C_PTR) + [portal encodeData: datum ofType: type]; + else + { + if ((flags & _F_IN) == _F_IN) + [portal encodeData: *(char**)datum ofType: ++type]; + } + } + } +*/ + +char* +method_get_next_argument (arglist_t argframe, + const char **type) +{ + const char *t = objc_skip_argspec (*type); + + if (*t == '\0') + return 0; + + *type = t; + t = objc_skip_typespec (t); + + if (*t == '+') + return argframe->arg_regs + atoi (++t); + else + return argframe->arg_ptr + atoi (t); +} + +/* + Return a pointer to the value of the first argument of the method + described in M with the given argumentframe ARGFRAME. The type + is returned in TYPE. type must be passed to successive calls of + method_get_next_argument. +*/ +char* +method_get_first_argument (struct objc_method* m, + arglist_t argframe, + const char** type) +{ + *type = m->method_types; + return method_get_next_argument (argframe, type); +} + +/* + Return a pointer to the ARGth argument of the method + M from the frame ARGFRAME. The type of the argument + is returned in the value-result argument TYPE +*/ + +char* +method_get_nth_argument (struct objc_method* m, + arglist_t argframe, int arg, + const char **type) +{ + const char* t = objc_skip_argspec (m->method_types); + + if (arg > method_get_number_of_arguments (m)) + return 0; + + while (arg--) + t = objc_skip_argspec (t); + + *type = t; + t = objc_skip_typespec (t); + + if (*t == '+') + return argframe->arg_regs + atoi (++t); + else + return argframe->arg_ptr + atoi (t); +} + +unsigned +objc_get_type_qualifiers (const char* type) +{ + unsigned res = 0; + BOOL flag = YES; + + while (flag) + switch (*type++) + { + case _C_CONST: res |= _F_CONST; break; + case _C_IN: res |= _F_IN; break; + case _C_INOUT: res |= _F_INOUT; break; + case _C_OUT: res |= _F_OUT; break; + case _C_BYCOPY: res |= _F_BYCOPY; break; + case _C_ONEWAY: res |= _F_ONEWAY; break; + default: flag = NO; + } + + return res; +} diff --git a/gcc/objc/encoding.h b/gcc/objc/encoding.h new file mode 100644 index 00000000000..79fdc795ad9 --- /dev/null +++ b/gcc/objc/encoding.h @@ -0,0 +1,73 @@ +/* Encoding of types for Objective C. + Copyright (C) 1993 Free Software Foundation, Inc. + +Author: Kresten Krab Thorup + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +#ifndef __encoding_INCLUDE_GNU +#define __encoding_INCLUDE_GNU + +#include "objc/objc-api.h" + +#define _C_CONST 'r' +#define _C_IN 'n' +#define _C_INOUT 'N' +#define _C_OUT 'o' +#define _C_BYCOPY 'O' +#define _C_ONEWAY 'V' + +#define _F_CONST 0x01 +#define _F_IN 0x01 +#define _F_OUT 0x02 +#define _F_INOUT 0x03 +#define _F_BYCOPY 0x04 +#define _F_ONEWAY 0x08 + + +int objc_aligned_size (const char* type); +int objc_sizeof_type (const char* type); +int objc_alignof_type (const char* type); +int objc_aligned_size (const char* type); +int objc_promoted_size (const char* type); +const char* objc_skip_type_qualifiers (const char* type); +const char* objc_skip_typespec (const char* type); +const char* objc_skip_offset (const char* type); +const char* objc_skip_argspec (const char* type); +int method_get_number_of_arguments (struct objc_method*); +int method_get_size_of_arguments (struct objc_method*); + +char* method_get_first_argument (struct objc_method*, + arglist_t argframe, + const char** type); +char* method_get_next_argument (arglist_t argframe, + const char **type); +char* method_get_nth_argument (struct objc_method* m, + arglist_t argframe, + int arg, + const char **type); + +unsigned objc_get_type_qualifiers (const char* type); + + +#endif /* __encoding_INCLUDE_GNU */ -- 2.30.2