Initial revision
authorKresten Krab Thorup <krab@gcc.gnu.org>
Tue, 24 Aug 1993 10:05:25 +0000 (10:05 +0000)
committerKresten Krab Thorup <krab@gcc.gnu.org>
Tue, 24 Aug 1993 10:05:25 +0000 (10:05 +0000)
From-SVN: r5206

gcc/objc/encoding.c [new file with mode: 0644]
gcc/objc/encoding.h [new file with mode: 0644]

diff --git a/gcc/objc/encoding.c b/gcc/objc/encoding.c
new file mode 100644 (file)
index 0000000..075d2ee
--- /dev/null
@@ -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 "<name>=" */
+      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 (file)
index 0000000..79fdc79
--- /dev/null
@@ -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 */