Boehm GC support for ObjC from Ovidiu Predescu.

From-SVN: r22199
This commit is contained in:
Ovidiu Predescu 1998-09-02 23:48:01 +00:00 committed by Jeff Law
parent d636ae0b80
commit d8bb17c8e3
16 changed files with 1744 additions and 171 deletions

View File

@ -1,3 +1,48 @@
Thu Sep 3 00:37:55 1998 Ovidiu Predescu <ovidiu@aracnet.com>
Added support for the Boehm's garbage collector.
* configure.in: Handle --enable-objc-gc.
* configure: Rebuilt.
* Makefile.in (CHECK_TARGETS): Add check-objc.
(check-objc): New rule.
* objc/Make-lang.in: Build a different Objective-C library that
runs with the Boehm's collector.
* objc/encoding.c (objc_round_acc_size_for_types): New function.
* objc/encoding.c: Correctly compute the size of compound types in
the presence of bitfields. Skip the variable name of the type if
any. Added support for long long.
* objc/encoding.h (_C_GCINVISIBLE): New specifier.
(_F_GCINVISIBLE): New mask.
* objc/gc.c: New file. Compute the type memory mask associated with
a class based on the runtime information.
* objc/misc.c: Added the hooks that use the Boehm's collector
allocation functions.
* objc/objc-act.c (build_class_template): Generate a new class
member (gc_object_type) to hold the class' type memory mask.
(build_shared_structure_initializer): Initialize the new member to
NULL.
(encode_complete_bitfield): New function. Generate the new
encoding.
(encode_field_decl): Generate the new encoding only for the GNU
runtime.
* objc/objc-api.h (_C_LNG_LNG, _C_ULNG_LNG): New specifiers for the
long long types.
(class_get_gc_object_type): New function to mark a pointer instance
variable as a weak pointer.
* objc/objc-features.texi: New file.
* objc/objc.h (gc_object_type): New class member.
* objc/objects.c (class_create_instance): Create a typed memory
object when compiled with Boehm's collector support.
* objc/sendmsg.c (__objc_init_install_dtable): Call
__objc_send_initialize instead of setting the initialize flag.
(__objc_send_initialize): Call __objc_generate_gc_type_description
to generate the class type memory mask. Rewrite the code that
sends the +initialize so that it is called only once (bug report
and fix from Ronald Pijnacker <Ronald.Pijnacker@best.ms.philips.com>).
* testsuite/objc: New testsuite for Objective-C type encoding.
* testsuite/lib/objc-torture.exp: New file.
* testsuite/lib/objc.exp: New file.
Wed Sep 2 14:47:36 1998 Jim Wilson <wilson@cygnus.com>
* jump.c (jump_optimize): In if/then/else transformations, add

View File

@ -246,6 +246,7 @@ lang_specs_files=@lang_specs_files@
lang_options_files=@lang_options_files@
lang_tree_files=@lang_tree_files@
GCC_THREAD_FILE=@thread_file@
OBJC_BOEHM_GC=@objc_boehm_gc@
GTHREAD_FLAGS=@gthread_flags@
# Be prepared for gcc2 merges.
gcc_version=@gcc_version@
@ -2574,7 +2575,7 @@ site.exp: ./config.status Makefile
-e '1,/^## All variables above are.*##/ d' >> site.exp
-@rm -f ./tmp?
CHECK_TARGETS = check-gcc check-g++ check-g77
CHECK_TARGETS = check-gcc check-g++ check-g77 check-objc
check: $(CHECK_TARGETS)
@ -2617,6 +2618,16 @@ check-g77: testsuite/site.exp
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool g77 $(RUNTESTFLAGS)
check-objc: testsuite/site.exp
-rootme=`pwd`; export rootme; \
srcdir=`cd ${srcdir}; pwd` ; export srcdir ; \
cd testsuite; \
EXPECT=${EXPECT} ; export EXPECT ; \
if [ -f $${rootme}/../expect/expect ] ; then \
TCL_LIBRARY=$${srcdir}/../tcl/library ; \
export TCL_LIBRARY ; fi ; \
$(RUNTEST) --tool objc $(RUNTESTFLAGS)
# These exist for maintenance purposes.
# Update the tags table.

176
gcc/configure vendored
View File

@ -44,6 +44,9 @@ ac_help="$ac_help
ac_help="$ac_help
--enable-threads enable thread usage for target GCC.
--enable-threads=LIB use LIB thread package for target GCC."
ac_help="$ac_help
--enable-objc-gc enable the use of Boehm's garbage collector with
the GNU Objective-C runtime."
# Initialize some variables set by options.
# The variables have the same names as the options, with
@ -745,6 +748,19 @@ case x${enable_threads_flag} in
;;
esac
# Check whether --enable-objc-gc or --disable-objc-gc was given.
if test "${enable_objc_gc+set}" = set; then
enableval="$enable_objc_gc"
if [ x$enable_objc_gc = xno ]; then
objc_boehm_gc=''
else
objc_boehm_gc=1
fi
else
objc_boehm_gc=''
fi
# Determine the host, build, and target systems
ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
@ -793,7 +809,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
echo "configure:797: checking host system type" >&5
echo "configure:813: checking host system type" >&5
host_alias=$host
case "$host_alias" in
@ -814,7 +830,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$host" 1>&6
echo $ac_n "checking target system type""... $ac_c" 1>&6
echo "configure:818: checking target system type" >&5
echo "configure:834: checking target system type" >&5
target_alias=$target
case "$target_alias" in
@ -832,7 +848,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
echo "$ac_t""$target" 1>&6
echo $ac_n "checking build system type""... $ac_c" 1>&6
echo "configure:836: checking build system type" >&5
echo "configure:852: checking build system type" >&5
build_alias=$build
case "$build_alias" in
@ -859,7 +875,7 @@ test "$host_alias" != "$target_alias" &&
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:863: checking for $ac_word" >&5
echo "configure:879: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -888,7 +904,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:892: checking for $ac_word" >&5
echo "configure:908: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -936,7 +952,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:940: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
echo "configure:956: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@ -946,11 +962,11 @@ ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS
cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext <<EOF
#line 950 "configure"
#line 966 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
if { (eval echo configure:954: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:970: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@ -970,12 +986,12 @@ if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:974: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "configure:990: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:979: checking whether we are using GNU C" >&5
echo "configure:995: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -984,7 +1000,7 @@ else
yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:988: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1004: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@ -999,7 +1015,7 @@ if test $ac_cv_prog_gcc = yes; then
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:1003: checking whether ${CC-cc} accepts -g" >&5
echo "configure:1019: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1038,7 +1054,7 @@ fi
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
echo "configure:1042: checking whether ${MAKE-make} sets \${MAKE}" >&5
echo "configure:1058: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -1071,7 +1087,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1075: checking for $ac_word" >&5
echo "configure:1091: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1102,7 +1118,7 @@ done
# Extract the first word of "flex", so it can be a program name with args.
set dummy flex; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1106: checking for $ac_word" >&5
echo "configure:1122: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1135,7 +1151,7 @@ then
*) ac_lib=l ;;
esac
echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
echo "configure:1139: checking for yywrap in -l$ac_lib" >&5
echo "configure:1155: checking for yywrap in -l$ac_lib" >&5
ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -1143,7 +1159,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-l$ac_lib $LIBS"
cat > conftest.$ac_ext <<EOF
#line 1147 "configure"
#line 1163 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@ -1154,7 +1170,7 @@ int main() {
yywrap()
; return 0; }
EOF
if { (eval echo configure:1158: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1174: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@ -1177,7 +1193,7 @@ fi
fi
echo $ac_n "checking whether ln works""... $ac_c" 1>&6
echo "configure:1181: checking whether ln works" >&5
echo "configure:1197: checking whether ln works" >&5
if eval "test \"`echo '$''{'gcc_cv_prog_LN'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1209,7 +1225,7 @@ else
fi
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
echo "configure:1213: checking whether ln -s works" >&5
echo "configure:1229: checking whether ln -s works" >&5
if eval "test \"`echo '$''{'gcc_cv_prog_LN_S'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1241,19 +1257,19 @@ else
fi
echo $ac_n "checking for volatile""... $ac_c" 1>&6
echo "configure:1245: checking for volatile" >&5
echo "configure:1261: checking for volatile" >&5
if eval "test \"`echo '$''{'gcc_cv_c_volatile'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1250 "configure"
#line 1266 "configure"
#include "confdefs.h"
int main() {
volatile int foo;
; return 0; }
EOF
if { (eval echo configure:1257: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1273: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_c_volatile=yes
else
@ -1276,7 +1292,7 @@ fi
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1280: checking for $ac_word" >&5
echo "configure:1296: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1307,7 +1323,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1311: checking for $ac_word" >&5
echo "configure:1327: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1347,7 +1363,7 @@ test -n "$YACC" || YACC="yacc"
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:1351: checking for a BSD compatible install" >&5
echo "configure:1367: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -1398,7 +1414,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:1402: checking how to run the C preprocessor" >&5
echo "configure:1418: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@ -1413,13 +1429,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
#line 1417 "configure"
#line 1433 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1423: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1439: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
@ -1430,13 +1446,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
#line 1434 "configure"
#line 1450 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1440: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1456: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
@ -1459,12 +1475,12 @@ fi
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
echo "configure:1463: checking for ANSI C header files" >&5
echo "configure:1479: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1468 "configure"
#line 1484 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@ -1472,7 +1488,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1476: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1492: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@ -1489,7 +1505,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1493 "configure"
#line 1509 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@ -1507,7 +1523,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 1511 "configure"
#line 1527 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@ -1528,7 +1544,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
#line 1532 "configure"
#line 1548 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@ -1539,7 +1555,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
if { (eval echo configure:1543: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:1559: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
:
else
@ -1563,12 +1579,12 @@ EOF
fi
echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
echo "configure:1567: checking whether time.h and sys/time.h may both be included" >&5
echo "configure:1583: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1572 "configure"
#line 1588 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
@ -1577,7 +1593,7 @@ int main() {
struct tm *tp;
; return 0; }
EOF
if { (eval echo configure:1581: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1597: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_time=yes
else
@ -1601,17 +1617,17 @@ for ac_hdr in limits.h stddef.h string.h strings.h stdlib.h time.h fcntl.h unist
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1605: checking for $ac_hdr" >&5
echo "configure:1621: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1610 "configure"
#line 1626 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1615: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1631: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@ -1641,17 +1657,17 @@ done
# Check for thread headers.
ac_safe=`echo "thread.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for thread.h""... $ac_c" 1>&6
echo "configure:1645: checking for thread.h" >&5
echo "configure:1661: checking for thread.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1650 "configure"
#line 1666 "configure"
#include "confdefs.h"
#include <thread.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1655: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1671: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@ -1675,17 +1691,17 @@ fi
ac_safe=`echo "pthread.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for pthread.h""... $ac_c" 1>&6
echo "configure:1679: checking for pthread.h" >&5
echo "configure:1695: checking for pthread.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1684 "configure"
#line 1700 "configure"
#include "confdefs.h"
#include <pthread.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1689: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1705: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@ -1711,12 +1727,12 @@ fi
# See if the system preprocessor understands the ANSI C preprocessor
# stringification operator.
echo $ac_n "checking whether cpp understands the stringify operator""... $ac_c" 1>&6
echo "configure:1715: checking whether cpp understands the stringify operator" >&5
echo "configure:1731: checking whether cpp understands the stringify operator" >&5
if eval "test \"`echo '$''{'gcc_cv_c_have_stringify'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1720 "configure"
#line 1736 "configure"
#include "confdefs.h"
int main() {
@ -1724,7 +1740,7 @@ int main() {
char *test = S(foo);
; return 0; }
EOF
if { (eval echo configure:1728: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1744: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
gcc_cv_c_have_stringify=yes
else
@ -1747,12 +1763,12 @@ fi
# Use <inttypes.h> only if it exists,
# doesn't clash with <sys/types.h>, and declares intmax_t.
echo $ac_n "checking for inttypes.h""... $ac_c" 1>&6
echo "configure:1751: checking for inttypes.h" >&5
echo "configure:1767: checking for inttypes.h" >&5
if eval "test \"`echo '$''{'gcc_cv_header_inttypes_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1756 "configure"
#line 1772 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <inttypes.h>
@ -1760,7 +1776,7 @@ int main() {
intmax_t i = -1;
; return 0; }
EOF
if { (eval echo configure:1764: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1780: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
cat >> confdefs.h <<EOF
#define HAVE_INTTYPES_H 1
@ -1783,12 +1799,12 @@ for ac_func in strtoul bsearch strerror putenv popen bcopy bzero bcmp \
sysconf isascii gettimeofday
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:1787: checking for $ac_func" >&5
echo "configure:1803: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1792 "configure"
#line 1808 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@ -1811,7 +1827,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:1815: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@ -1840,12 +1856,12 @@ done
#AC_CHECK_TYPE(wchar_t, unsigned int)
echo $ac_n "checking for vprintf""... $ac_c" 1>&6
echo "configure:1844: checking for vprintf" >&5
echo "configure:1860: checking for vprintf" >&5
if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1849 "configure"
#line 1865 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vprintf(); below. */
@ -1868,7 +1884,7 @@ vprintf();
; return 0; }
EOF
if { (eval echo configure:1872: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1888: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_vprintf=yes"
else
@ -1892,12 +1908,12 @@ fi
if test "$ac_cv_func_vprintf" != yes; then
echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
echo "configure:1896: checking for _doprnt" >&5
echo "configure:1912: checking for _doprnt" >&5
if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1901 "configure"
#line 1917 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char _doprnt(); below. */
@ -1920,7 +1936,7 @@ _doprnt();
; return 0; }
EOF
if { (eval echo configure:1924: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
if { (eval echo configure:1940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func__doprnt=yes"
else
@ -1956,7 +1972,7 @@ fi
echo $ac_n "checking whether the printf functions support %p""... $ac_c" 1>&6
echo "configure:1960: checking whether the printf functions support %p" >&5
echo "configure:1976: checking whether the printf functions support %p" >&5
if eval "test \"`echo '$''{'gcc_cv_func_printf_ptr'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1964,7 +1980,7 @@ else
gcc_cv_func_printf_ptr=no
else
cat > conftest.$ac_ext <<EOF
#line 1968 "configure"
#line 1984 "configure"
#include "confdefs.h"
#include <stdio.h>
@ -1977,7 +1993,7 @@ main()
exit (p != q);
}
EOF
if { (eval echo configure:1981: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
if { (eval echo configure:1997: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
gcc_cv_func_printf_ptr=yes
else
@ -2005,12 +2021,12 @@ for ac_func in malloc realloc calloc free bcopy bzero bcmp \
index rindex getenv atol sbrk abort atof strerror getcwd getwd
do
echo $ac_n "checking whether $ac_func must be declared""... $ac_c" 1>&6
echo "configure:2009: checking whether $ac_func must be declared" >&5
echo "configure:2025: checking whether $ac_func must be declared" >&5
if eval "test \"`echo '$''{'gcc_cv_decl_needed_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2014 "configure"
#line 2030 "configure"
#include "confdefs.h"
#include <stdio.h>
@ -2038,7 +2054,7 @@ int main() {
char *(*pfn) = (char *(*)) $ac_func
; return 0; }
EOF
if { (eval echo configure:2042: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:2058: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "gcc_cv_decl_needed_$ac_func=no"
else
@ -2067,12 +2083,12 @@ done
for ac_func in getrlimit setrlimit
do
echo $ac_n "checking whether $ac_func must be declared""... $ac_c" 1>&6
echo "configure:2071: checking whether $ac_func must be declared" >&5
echo "configure:2087: checking whether $ac_func must be declared" >&5
if eval "test \"`echo '$''{'gcc_cv_decl_needed_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2076 "configure"
#line 2092 "configure"
#include "confdefs.h"
#include <stdio.h>
@ -2104,7 +2120,7 @@ int main() {
char *(*pfn) = (char *(*)) $ac_func
; return 0; }
EOF
if { (eval echo configure:2108: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:2124: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "gcc_cv_decl_needed_$ac_func=no"
else
@ -2131,12 +2147,12 @@ done
echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6
echo "configure:2135: checking for sys_siglist declaration in signal.h or unistd.h" >&5
echo "configure:2151: checking for sys_siglist declaration in signal.h or unistd.h" >&5
if eval "test \"`echo '$''{'ac_cv_decl_sys_siglist'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2140 "configure"
#line 2156 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
@ -2148,7 +2164,7 @@ int main() {
char *msg = *(sys_siglist + 1);
; return 0; }
EOF
if { (eval echo configure:2152: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:2168: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_decl_sys_siglist=yes
else
@ -5306,7 +5322,7 @@ fi
# Figure out what assembler alignment features are present.
echo $ac_n "checking assembler alignment features""... $ac_c" 1>&6
echo "configure:5310: checking assembler alignment features" >&5
echo "configure:5326: checking assembler alignment features" >&5
gcc_cv_as=
gcc_cv_as_alignment_features=
gcc_cv_as_gas_srcdir=`echo $srcdir | sed -e 's,gcc$,gas,'`
@ -5566,7 +5582,7 @@ fi
# Warn if using init_priority.
echo $ac_n "checking whether to enable init_priority by default""... $ac_c" 1>&6
echo "configure:5570: checking whether to enable init_priority by default" >&5
echo "configure:5586: checking whether to enable init_priority by default" >&5
if test x$enable_init_priority != xyes; then
enable_init_priority=no
fi
@ -5634,6 +5650,7 @@ ${CONFIG_SHELL-/bin/sh} $srcdir/configure.frag $srcdir "$subdirs" "$dep_host_xma
# Echo that links are built
@ -5876,6 +5893,7 @@ s%@lang_specs_files@%$lang_specs_files%g
s%@lang_options_files@%$lang_options_files%g
s%@lang_tree_files@%$lang_tree_files%g
s%@thread_file@%$thread_file%g
s%@objc_boehm_gc@%$objc_boehm_gc%g
s%@gcc_version@%$gcc_version%g
s%@gcc_version_trigger@%$gcc_version_trigger%g
s%@local_prefix@%$local_prefix%g

View File

@ -173,6 +173,16 @@ case x${enable_threads_flag} in
;;
esac
AC_ARG_ENABLE(objc-gc,
[ --enable-objc-gc enable the use of Boehm's garbage collector with
the GNU Objective-C runtime.],
if [[[ x$enable_objc_gc = xno ]]]; then
objc_boehm_gc=''
else
objc_boehm_gc=1
fi,
objc_boehm_gc='')
# Determine the host, build, and target systems
AC_CANONICAL_SYSTEM
@ -3822,6 +3832,7 @@ AC_SUBST(lang_specs_files)
AC_SUBST(lang_options_files)
AC_SUBST(lang_tree_files)
AC_SUBST(thread_file)
AC_SUBST(objc_boehm_gc)
AC_SUBST(gcc_version)
AC_SUBST(gcc_version_trigger)
AC_SUBST(local_prefix)

View File

@ -119,6 +119,7 @@ OBJC_O = objc/hash.o objc/sarray.o \
objc/NXConstStr.o objc/Object.o \
objc/Protocol.o objc/nil_method.o \
objc/thr.o objc/linking.o \
objc/gc.o \
objc/$(OBJC_THREAD_FILE).o
objc/hash.o: $(srcdir)/objc/hash.c $(GCC_PASSES)
@ -172,11 +173,74 @@ objc/nil_method.o: $(srcdir)/objc/nil_method.c $(GCC_PASSES)
objc/linking.o: $(srcdir)/objc/linking.m $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-fgnu-runtime -c $(srcdir)/objc/linking.m -o $@
objc/gc.o: $(srcdir)/objc/gc.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-fgnu-runtime -c $(srcdir)/objc/gc.c -o $@
objc/libobjc_entry.o: $(srcdir)/objc/libobjc_entry.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/libobjc_entry.c -o $@
objc/hash_gc.o: $(srcdir)/objc/hash.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/hash.c -o $@
objc/sarray_gc.o: $(srcdir)/objc/sarray.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/sarray.c -o $@
objc/class_gc.o: $(srcdir)/objc/class.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/class.c -o $@
objc/sendmsg_gc.o: $(srcdir)/objc/sendmsg.c $(GCC_PASSES) objc/runtime-info.h
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) -Iobjc \
-c $(srcdir)/objc/sendmsg.c -o $@
objc/init_gc.o: $(srcdir)/objc/init.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/init.c -o $@
objc/archive_gc.o: $(srcdir)/objc/archive.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/archive.c -o $@
objc/encoding_gc.o: $(srcdir)/objc/encoding.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/encoding.c -o $@
objc/selector_gc.o: $(srcdir)/objc/selector.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/selector.c -o $@
objc/objects_gc.o: $(srcdir)/objc/objects.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/objects.c -o $@
objc/misc_gc.o: $(srcdir)/objc/misc.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/misc.c -o $@
objc/NXConstStr_gc.o: $(srcdir)/objc/NXConstStr.m $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-fgnu-runtime -c $(srcdir)/objc/NXConstStr.m -o $@
objc/Object_gc.o: $(srcdir)/objc/Object.m $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-fgnu-runtime -c $(srcdir)/objc/Object.m -o $@
objc/Protocol_gc.o: $(srcdir)/objc/Protocol.m $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-fgnu-runtime -c $(srcdir)/objc/Protocol.m -o $@
objc/thr_gc.o: $(srcdir)/objc/thr.h $(srcdir)/objc/thr.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/thr.c -o $@
objc/$(OBJC_THREAD_FILE)_gc.o: $(srcdir)/objc/$(OBJC_THREAD_FILE).c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/$(OBJC_THREAD_FILE).c -o $@
objc/nil_method_gc.o: $(srcdir)/objc/nil_method.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/nil_method.c -o $@
objc/linking_gc.o: $(srcdir)/objc/linking.m $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-fgnu-runtime -c $(srcdir)/objc/linking.m -o $@
objc/gc_gc.o: $(srcdir)/objc/gc.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-fgnu-runtime -c $(srcdir)/objc/gc.c -o $@
objc/libobjc_entry_gc.o: $(srcdir)/objc/libobjc_entry.c $(GCC_PASSES)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
-c $(srcdir)/objc/libobjc_entry.c -o $@
$(OBJC_O): $(GCC_PASSES) cc1obj$(exeext)
# Build the Objective C runtime library.
@ -185,6 +249,17 @@ libobjc.a: cc1obj$(exeext) specs stmp-int-hdrs libgcc2.ready \
-rm -f libobjc.a
$(AR) $(AR_FLAGS) libobjc.a $(OBJC_O)
-if $(RANLIB_TEST) ; then $(RANLIB) libobjc.a; else true; fi
-if [ "$(OBJC_BOEHM_GC)" != "" ]; then \
make libobjc_gc.a GCC_CFLAGS="$(GCC_CFLAGS) -DOBJC_WITH_GC=1" \
OBJC_O=`echo $(OBJC_O) | sed 's/.o /_gc.o /g'`; \
fi
# Build the garbage collected Objective C runtime library.
libobjc_gc.a: cc1obj specs stmp-int-hdrs libgcc2.ready \
$(USE_COLLECT2) $(EXTRA_PARTS) $(OBJC_O)
-rm -f libobjc_gc.a
$(AR) $(AR_FLAGS) libobjc_gc.a $(OBJC_O)
-if $(RANLIB_TEST) ; then $(RANLIB) libobjc_gc.a; else true; fi
libobjc_s.a: libobjc.a
mv libobjc.a libobjc_s.a
@ -236,6 +311,13 @@ objc.install-normal: installdirs
(cd $(libsubdir); $(RANLIB) libobjc.a); else true; fi; \
chmod a-x $(libsubdir)/libobjc.a; \
else true; fi
-if [ -f libobjc_gc.a ] ; then \
rm -f $(libsubdir)/libobjc_gc.a; \
$(INSTALL_DATA) libobjc_gc.a $(libsubdir)/libobjc_gc.a; \
if $(RANLIB_TEST) ; then \
(cd $(libsubdir); $(RANLIB) libobjc_gc.a); else true; fi; \
chmod a-x $(libsubdir)/libobjc_gc.a; \
else true; fi
-if [ -f libobjc_s.a ] ; then \
rm -f $(libsubdir)/libobjc_s.a; \
$(INSTALL_DATA) libobjc_s.a $(libsubdir)/libobjc_s.a; \
@ -263,7 +345,7 @@ objc.mostlyclean:
-rm -f tmp-objc-prs.y
-rm -f objc/*$(objext) objc/xforward objc/fflags
-rm -f objc/runtime-info.h
-rm -f libobjc.a libobjc_s.a libobjc.dll
-rm -f libobjc.a libobjc_gc.a libobjc_s.a libobjc.dll
-rm -f libobjc.base libobjc.exp
objc.clean: objc.mostlyclean
-rm -rf objc-headers
@ -282,19 +364,19 @@ objc.maintainer-clean:
objc.stage1: stage1-start
-mv objc/*$(objext) stage1/objc
-mv cc1obj$(exeext) stage1
-mv libobjc.a stage1
-mv libobjc.a libobjc_gc.a stage1
objc.stage2: stage2-start
-mv objc/*$(objext) stage2/objc
-mv cc1obj$(exeext) stage2
-mv libobjc.a stage2
-mv libobjc.a libobjc_gc.a stage2
objc.stage3: stage3-start
-mv objc/*$(objext) stage3/objc
-mv cc1obj$(exeext) stage3
-mv libobjc.a stage3
-mv libobjc.a libobjc_gc.a stage3
objc.stage4: stage4-start
-mv objc/*$(objext) stage4/objc
-mv cc1obj$(exeext) stage4
-mv libobjc.a stage4
-mv libobjc.a libobjc_gc.a stage4
#
# Maintenance hooks:

View File

@ -81,8 +81,23 @@ copy-headers:
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
cd ..; $(SHELL) config.status
doc: info dvi html
info: objc-features.info
dvi: objc-features.dvi
html: objc-features_toc.html
objc-features.info: $(srcdir)/objc-features.texi
makeinfo $(srcdir)/objc-features.texi
objc-features.dvi: $(srcdir)/objc-features.texi
texi2dvi $(srcdir)/objc-features.texi
objc-features_toc.html: objc-features.texi
texi2html -split_node $(srcdir)/objc-features.texi
mostlyclean:
-rm -f *.o libobjc.a xforward fflags
-rm -f *.o libobjc* xforward fflags *.aux *.cp *.dvi *.fn *.info \
*.ky *.log *.pg *.toc *.tp *.vr *.html
clean: mostlyclean
distclean: mostlyclean
extraclean: mostlyclean

View File

@ -1,6 +1,7 @@
/* Encoding of types for Objective C.
Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
Bitfield support by Ovidiu Predescu
This file is part of GNU CC.
@ -25,6 +26,8 @@ Boston, MA 02111-1307, USA. */
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
#include "tconfig.h"
#include "objc-api.h"
#include "encoding.h"
#define MAX(X, Y) \
@ -40,6 +43,22 @@ Boston, MA 02111-1307, USA. */
__a*((__v+__a-1)/__a); })
/* Various hacks for objc_layout_record. These are used by the target
macros. */
#define TREE_CODE(TYPE) *TYPE
#define RECORD_TYPE _C_STRUCT_B
#define UNION_TYPE _C_UNION_B
#define QUAL_UNION_TYPE _C_UNION_B
#define TYPE_FIELDS(TYPE) objc_skip_typespec (TYPE)
#define DECL_MODE(TYPE) *(TYPE)
#define DFmode _C_DBL
static inline int
atoi (const char* str)
{
@ -56,8 +75,15 @@ atoi (const char* str)
*/
int
objc_sizeof_type(const char* type)
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);
@ -103,6 +129,14 @@ objc_sizeof_type(const char* type)
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;
@ -111,6 +145,9 @@ objc_sizeof_type(const char* type)
return sizeof(double);
break;
case _C_VOID:
return sizeof(void);
break;
case _C_PTR:
case _C_ATOM:
case _C_CHARPTR:
@ -125,19 +162,32 @@ objc_sizeof_type(const char* 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:
{
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 */
acc_size = ROUND (acc_size, align);
acc_size += objc_sizeof_type (type); /* add component size */
type = objc_skip_typespec (type); /* skip component */
}
return acc_size;
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:
@ -146,6 +196,12 @@ objc_sizeof_type(const char* type)
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);
}
@ -153,7 +209,10 @@ objc_sizeof_type(const char* type)
}
default:
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
{
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
return 0;
}
}
}
@ -165,6 +224,12 @@ objc_sizeof_type(const char* type)
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);
@ -210,6 +275,14 @@ objc_alignof_type(const char* type)
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;
@ -227,15 +300,18 @@ objc_alignof_type(const char* type)
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);
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:
@ -244,14 +320,23 @@ objc_alignof_type(const char* type)
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);
{
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
return 0;
}
}
}
@ -262,8 +347,18 @@ objc_alignof_type(const char* type)
int
objc_aligned_size (const char* type)
{
int size = objc_sizeof_type (type);
int align = objc_alignof_type (type);
int size, align;
/* Skip the variable name */
if (*type == '"')
{
for (type++; *type++ != '"';)
/* do nothing */;
}
size = objc_sizeof_type (type);
align = objc_alignof_type (type);
return ROUND (size, align);
}
@ -275,8 +370,17 @@ objc_aligned_size (const char* type)
int
objc_promoted_size (const char* type)
{
int size = objc_sizeof_type (type);
int wordsize = sizeof (void*);
int size, wordsize;
/* Skip the variable name */
if (*type == '"')
{
for (type++; *type++ != '"';)
/* do nothing */;
}
size = objc_sizeof_type (type);
wordsize = sizeof (void*);
return ROUND (size, wordsize);
}
@ -294,7 +398,8 @@ objc_skip_type_qualifiers (const char* type)
|| *type == _C_INOUT
|| *type == _C_OUT
|| *type == _C_BYCOPY
|| *type == _C_ONEWAY)
|| *type == _C_ONEWAY
|| *type == _C_GCINVISIBLE)
{
type += 1;
}
@ -310,6 +415,13 @@ objc_skip_type_qualifiers (const char* type)
const char*
objc_skip_typespec (const char* type)
{
/* Skip the variable name if any */
if (*type == '"')
{
for (type++; *type++ != '"';)
/* do nothing */;
}
type = objc_skip_type_qualifiers (type);
switch (*type) {
@ -339,6 +451,8 @@ objc_skip_typespec (const char* type)
case _C_UINT:
case _C_LNG:
case _C_ULNG:
case _C_LNG_LNG:
case _C_ULNG_LNG:
case _C_FLT:
case _C_DBL:
case _C_VOID:
@ -354,7 +468,16 @@ objc_skip_typespec (const char* type)
if (*type == _C_ARY_E)
return ++type;
else
objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
{
objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
return 0;
}
case _C_BFLD:
/* The new encoding of bitfields is: b 'position' 'type' 'size' */
while (isdigit (*++type)); /* skip position */
while (isdigit (*++type)); /* skip type and size */
return type;
case _C_STRUCT_B:
/* skip name, and elements until closing '}' */
@ -376,7 +499,10 @@ objc_skip_typespec (const char* type)
return objc_skip_typespec (++type);
default:
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
{
objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
return 0;
}
}
}
@ -526,14 +652,261 @@ objc_get_type_qualifiers (const char* type)
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;
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;
case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break;
default: flag = NO;
}
return res;
}
/* 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, particulary 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_STRUCT_B)
{
objc_error(nil, OBJC_ERR_BAD_TYPE,
"record type expected in objc_layout_structure, got %s\n",
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;
#ifdef STRUCTURE_SIZE_BOUNDARY
layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY);
#endif
}
BOOL
objc_layout_structure_next_member (struct objc_struct_layout *layout)
{
register int known_align = layout->record_size;
register int desired_align = 0;
/* The following are used only if the field is a bitfield */
register const char *bfld_type;
register int bfld_type_size, bfld_type_align, bfld_field_size;
/* The current type without the type qualifiers */
const char *type;
#if 1
if (layout->prev_type == NULL)
{
layout->prev_type = layout->type;
layout->type = objc_skip_typespec (layout->prev_type);
return YES;
}
#endif
/* Add the size of the previous field to the size of the record. */
if (layout->prev_type)
{
type = objc_skip_type_qualifiers (layout->prev_type);
if (*type != _C_BFLD)
layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
else {
desired_align = 1;
/* Get the bitfield's type */
for (bfld_type = type + 1;
isdigit(*bfld_type);
bfld_type++)
/* do nothing */;
bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
bfld_field_size = atoi (objc_skip_typespec (bfld_type));
layout->record_size += bfld_field_size;
}
}
if (*layout->type == _C_STRUCT_E)
return NO;
/* Skip the variable name if any */
if (*layout->type == '"')
{
for (layout->type++; *layout->type++ != '"';)
/* do nothing */;
}
type = objc_skip_type_qualifiers (layout->type);
if (*type != _C_BFLD)
desired_align = objc_alignof_type(type) * BITS_PER_UNIT;
else
{
desired_align = 1;
/* Skip the bitfield's offset */
for (bfld_type = type + 1; isdigit(*bfld_type); bfld_type++)
/* do nothing */;
bfld_type_size = objc_sizeof_type (bfld_type) * BITS_PER_UNIT;
bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
bfld_field_size = atoi (objc_skip_typespec (bfld_type));
}
#ifdef BIGGEST_FIELD_ALIGNMENT
desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);
#endif
#ifdef ADJUST_FIELD_ALIGN
desired_align = ADJUST_FIELD_ALIGN (type, desired_align);
#endif
/* Record must have at least as much alignment as any field.
Otherwise, the alignment of the field within the record
is meaningless. */
#ifndef PCC_BITFIELD_TYPE_MATTERS
layout->record_align = MAX (layout->record_align, desired_align);
#else
if (*type == _C_BFLD)
{
/* For these machines, a zero-length field does not
affect the alignment of the structure as a whole.
It does, however, affect the alignment of the next field
within the structure. */
if (bfld_field_size)
layout->record_align = MAX (layout->record_align, desired_align);
else
desired_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
/* A named bit field of declared type `int'
forces the entire structure to have `int' alignment.
Q1: How is encoded this thing and how to check for it?
Q2: How to determine maximum_field_alignment at runtime? */
/* if (DECL_NAME (field) != 0) */
{
int type_align = bfld_type_align;
#if 0
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
else if (DECL_PACKED (field))
type_align = MIN (type_align, BITS_PER_UNIT);
#endif
layout->record_align = MAX (layout->record_align, type_align);
}
}
else
layout->record_align = MAX (layout->record_align, desired_align);
#endif
/* Does this field automatically have alignment it needs
by virtue of the fields that precede it and the record's
own alignment? */
if (*type == _C_BFLD)
layout->record_size = atoi (type + 1);
else if (layout->record_size % desired_align != 0)
{
/* No, we need to skip space before this field.
Bump the cumulative size to multiple of field alignment. */
layout->record_size = ROUND (layout->record_size, desired_align);
}
/* Jump to the next field in record. */
layout->prev_type = layout->type;
layout->type = objc_skip_typespec (layout->type); /* skip component */
return YES;
}
void objc_layout_finish_structure (struct objc_struct_layout *layout,
unsigned int *size,
unsigned int *align)
{
if (layout->type && *layout->type == _C_STRUCT_E)
{
/* Work out the alignment of the record as one expression and store
in the record type. Round it up to a multiple of the record's
alignment. */
#ifdef ROUND_TYPE_ALIGN
layout->record_align = ROUND_TYPE_ALIGN (layout->original_type,
1,
layout->record_align);
#else
layout->record_align = MAX (1, layout->record_align);
#endif
#ifdef ROUND_TYPE_SIZE
layout->record_size = ROUND_TYPE_SIZE (layout->original_type,
layout->record_size,
layout->record_align);
#else
/* Round the size up to be a multiple of the required alignment */
layout->record_size = ROUND (layout->record_size, layout->record_align);
#endif
layout->type = NULL;
}
if (size)
*size = layout->record_size / BITS_PER_UNIT;
if (align)
*align = layout->record_align / BITS_PER_UNIT;
}
void objc_layout_structure_get_info (struct objc_struct_layout *layout,
unsigned int *offset,
unsigned int *align,
const char **type)
{
if (offset)
*offset = layout->record_size / BITS_PER_UNIT;
if (align)
*align = layout->record_align / BITS_PER_UNIT;
if (type)
*type = layout->prev_type;
}

View File

@ -32,26 +32,28 @@ Boston, MA 02111-1307, USA. */
#include <ctype.h>
#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
#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 _C_GCINVISIBLE '!'
#define _F_CONST 0x01
#define _F_IN 0x01
#define _F_OUT 0x02
#define _F_INOUT 0x03
#define _F_BYCOPY 0x04
#define _F_ONEWAY 0x08
#define _F_GCINVISIBLE 0x10
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);
@ -72,4 +74,24 @@ char* method_get_nth_argument (struct objc_method* m,
unsigned objc_get_type_qualifiers (const char* type);
struct objc_struct_layout
{
const char *original_type;
const char *type;
const char *prev_type;
unsigned int record_size;
unsigned int record_align;
};
void objc_layout_structure (const char *type,
struct objc_struct_layout *layout);
BOOL objc_layout_structure_next_member (struct objc_struct_layout *layout);
void objc_layout_finish_structure (struct objc_struct_layout *layout,
unsigned int *size,
unsigned int *align);
void objc_layout_structure_get_info (struct objc_struct_layout *layout,
unsigned int *offset,
unsigned int *align,
const char **type);
#endif /* __encoding_INCLUDE_GNU */

458
gcc/objc/gc.c Normal file
View File

@ -0,0 +1,458 @@
/* Basic data types for Objective C.
Copyright (C) 1998 Free Software Foundation, Inc.
Contributed by Ovidiu Predescu.
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, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, 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 "../tconfig.h"
#include "objc.h"
#include "encoding.h"
#include <assert.h>
#include <string.h>
#if OBJC_WITH_GC
#include <gc.h>
/* gc_typed.h uses the following but doesn't declare them */
typedef GC_word word;
typedef GC_signed_word signed_word;
#if BITS_PER_WORD == 32
# define LOGWL 5
# define modWORDSZ(n) ((n) & 0x1f) /* n mod size of word */
#endif
#if BITS_PER_WORD == 64
# define LOGWL 6
# define modWORDSZ(n) ((n) & 0x3f) /* n mod size of word */
#endif
#define divWORDSZ(n) ((n) >> LOGWL) /* divide n by size of word */
#include <gc_typed.h>
/* The following functions set up in `mask` the corresponding pointers.
The offset is incremented with the size of the type. */
#define ROUND(V, A) \
({ typeof(V) __v=(V); typeof(A) __a=(A); \
__a*((__v+__a-1)/__a); })
#define SET_BIT_FOR_OFFSET(mask, offset) \
GC_set_bit(mask, offset / sizeof (void*))
/* Some prototypes */
static void
__objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset);
static void
__objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
static void
__objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
{
int i, len = atoi(type + 1);
while (isdigit(*++type))
/* do nothing */; /* skip the size of the array */
switch (*type) {
case _C_ARY_B:
for (i = 0; i < len; i++)
__objc_gc_setup_array (mask, type, offset);
break;
case _C_STRUCT_B:
for (i = 0; i < len; i++)
__objc_gc_setup_struct (mask, type, offset);
break;
case _C_UNION_B:
for (i = 0; i < len; i++)
__objc_gc_setup_union (mask, type, offset);
break;
default:
break;
}
}
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;
}
}
}
static void
__objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
{
/* Sub-optimal, quick implementation: assume the union is made of
pointers, set up the mask accordingly. */
int i, size, align;
/* Skip the variable name */
if (*type == '"')
{
for (type++; *type++ != '"';)
/* do nothing */;
}
size = objc_sizeof_type (type);
align = objc_alignof_type (type);
offset = ROUND(offset, align);
for (i = 0; i < size; i += sizeof (void*))
{
SET_BIT_FOR_OFFSET(mask, offset);
offset += sizeof (void*);
}
}
/* 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;
}
}
}
/* Computes in *type the full type encoding of this class including
its super classes. '*size' gives the total number of bytes allocated
into *type, '*current' the number of bytes used so far by the
encoding. */
static void
__objc_class_structure_encoding (Class class, char **type, int *size,
int *current)
{
int i, ivar_count;
struct objc_ivar_list* ivars;
if (!class)
{
strcat (*type, "{");
*current++;
return;
}
/* Add the type encodings of the super classes */
__objc_class_structure_encoding (class->super_class, type, size, current);
ivars = class->ivars;
if (!ivars)
return;
ivar_count = ivars->ivar_count;
for (i = 0; i < ivar_count; i++)
{
struct objc_ivar *ivar = &(ivars->ivar_list[i]);
const char *ivar_type = ivar->ivar_type;
int len = strlen (ivar_type);
if (*current + len + 1 >= *size)
{
/* Increase the size of the encoding string so that it
contains this ivar's type. */
*size = ROUND(*current + len + 1, 10);
*type = objc_realloc (*type, *size);
}
strcat (*type + *current, ivar_type);
*current += len;
}
}
/* Allocates the memory that will hold the type description for class
and calls the __objc_class_structure_encoding that generates this
value. */
void
__objc_generate_gc_type_description (Class class)
{
GC_bitmap mask;
int bits_no, size;
int type_size = 10, current;
char *class_structure_type;
if (!CLS_ISCLASS(class))
return;
/* We have to create a mask in which each bit counts for a pointer member.
We take into consideration all the non-pointer instance variables and we
round them up to the alignment. */
/* The number of bits in the mask is the size of an instance in bytes divided
by the size of a pointer. */
bits_no = (ROUND(class_get_instance_size (class), sizeof(void*))
/ sizeof (void*));
size = ROUND(bits_no, BITS_PER_WORD) / BITS_PER_WORD;
mask = objc_atomic_malloc (size * sizeof (int));
memset (mask, 0, size * sizeof (int));
class_structure_type = objc_atomic_malloc (type_size);
*class_structure_type = current = 0;
__objc_class_structure_encoding (class, &class_structure_type,
&type_size, &current);
if (current + 1 == type_size)
class_structure_type = objc_realloc (class_structure_type, ++type_size);
strcat (class_structure_type + current, "}");
// printf ("type description for '%s' is %s\n", class->name, class_structure_type);
__objc_gc_type_description_from_type (mask, class_structure_type);
objc_free (class_structure_type);
#define DEBUG 1
#ifdef DEBUG
printf (" mask for '%s', type '%s' (bits %d, mask size %d) is:",
class_structure_type, class->name, bits_no, size);
{
int i;
for (i = 0; i < size; i++)
printf (" %lx", mask[i]);
}
puts ("");
#endif
class->gc_object_type = (void*)GC_make_descriptor (mask, bits_no);
}
/* Returns YES if type denotes a pointer type, NO otherwise */
static inline BOOL
__objc_ivar_pointer (const char *type)
{
type = objc_skip_type_qualifiers (type);
return (*type == _C_ID
|| *type == _C_CLASS
|| *type == _C_SEL
|| *type == _C_PTR
|| *type == _C_CHARPTR
|| *type == _C_ATOM);
}
/* Mark the instance variable whose name is given by ivarname as a
weak pointer (a pointer hidden to the garbage collector) if
gc_invisible is true. If gc_invisible is false it unmarks the
instance variable and makes it a normal pointer, visible to the
garbage collector.
This operation only makes sense on instance variables that are
pointers. */
void
class_ivar_set_gcinvisible (Class class, const char* ivarname,
BOOL gc_invisible)
{
int i, ivar_count;
struct objc_ivar_list* ivars;
if (!class || !ivarname)
return;
ivars = class->ivars;
if (!ivars)
return;
ivar_count = ivars->ivar_count;
for (i = 0; i < ivar_count; i++)
{
struct objc_ivar *ivar = &(ivars->ivar_list[i]);
const char *type;
if (!ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
continue;
assert (ivar->ivar_type);
type = ivar->ivar_type;
/* Skip the variable name */
if (*type == '"')
{
for (type++; *type++ != '"';)
/* do nothing */;
}
if (*type == _C_GCINVISIBLE)
{
char *new_type;
if (gc_invisible || !__objc_ivar_pointer (type))
return; /* The type of the variable already matches the
requested gc_invisible type */
/* The variable is gc_invisible and we have to reverse it */
new_type = objc_atomic_malloc (strlen (ivar->ivar_type));
strncpy (new_type, ivar->ivar_type,
(size_t)(type - ivar->ivar_type));
strcat (new_type, type + 1);
ivar->ivar_type = new_type;
}
else
{
char *new_type;
if (!gc_invisible || !__objc_ivar_pointer (type))
return; /* The type of the variable already matches the
requested gc_invisible type */
/* The variable is gc visible and we have to make it gc_invisible */
new_type = objc_malloc (strlen (ivar->ivar_type) + 2);
strncpy (new_type, ivar->ivar_type,
(size_t)(type - ivar->ivar_type));
strcat (new_type, "!");
strcat (new_type, type);
ivar->ivar_type = new_type;
}
__objc_generate_gc_type_description (class);
return;
}
/* Search the instance variable in the superclasses */
class_ivar_set_gcinvisible (class->super_class, ivarname, gc_invisible);
}
#else /* !OBJC_WITH_GC */
void
__objc_generate_gc_type_description (Class class)
{
}
void class_ivar_set_gcinvisible (Class class,
const char* ivarname,
BOOL gc_invisible)
{
}
#endif /* OBJC_WITH_GC */

View File

@ -1,6 +1,6 @@
/* GNU Objective C Runtime Miscellaneous
Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contrbuted by Kresten Krab Thorup
Contributed by Kresten Krab Thorup
This file is part of GNU CC.
@ -144,9 +144,37 @@ objc_free(void *mem)
** Users should call the normal objc routines above for
** memory allocation and disposal within their programs.
*/
#if OBJC_WITH_GC
#include <gc.h>
static void *GC_calloc (size_t nelem, size_t size)
{
void* p = GC_malloc (nelem * size);
if (!p)
objc_error (nil, OBJC_ERR_MEMORY, "Virtual memory exhausted!\n");
memset (p, 0, nelem * size);
return p;
}
static void noFree (void* p) {}
void *(*_objc_malloc)(size_t) = GC_malloc;
void *(*_objc_atomic_malloc)(size_t) = GC_malloc_atomic;
void *(*_objc_valloc)(size_t) = GC_malloc;
void *(*_objc_realloc)(void *, size_t) = GC_realloc;
void *(*_objc_calloc)(size_t, size_t) = GC_calloc;
void (*_objc_free)(void *) = noFree;
#else
void *(*_objc_malloc)(size_t) = malloc;
void *(*_objc_atomic_malloc)(size_t) = malloc;
void *(*_objc_valloc)(size_t) = malloc;
void *(*_objc_realloc)(void *, size_t) = realloc;
void *(*_objc_calloc)(size_t, size_t) = calloc;
void (*_objc_free)(void *) = free;
#endif

View File

@ -3380,6 +3380,7 @@ build_selector_template ()
struct objc_class *sibling_class;
}
struct objc_protocol_list *protocols;
void *gc_object_type;
}; */
static void
@ -3515,6 +3516,21 @@ build_class_template ()
decl_specs, NULL_TREE);
chainon (field_decl_chain, field_decl);
/* void *sel_id; */
decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("sel_id"));
field_decl
= grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
chainon (field_decl_chain, field_decl);
/* void *gc_object_type; */
decl_specs = build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]);
field_decl = build1 (INDIRECT_REF, NULL_TREE, get_identifier ("gc_object_type"));
field_decl
= grokfield (input_filename, lineno, field_decl, decl_specs, NULL_TREE);
chainon (field_decl_chain, field_decl);
finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
}
@ -4287,6 +4303,7 @@ build_category_initializer (type, cat_name, class_name,
struct objc_class *sibling_class;
}
struct objc_protocol_list *protocols;
void *gc_object_type;
}; */
static tree
@ -4377,6 +4394,9 @@ build_shared_structure_initializer (type, isa, super, name, size, status,
initlist = tree_cons (NULL_TREE, expr, initlist);
}
/* gc_object_type = NULL */
initlist = tree_cons (NULL_TREE, build_int_2 (0, 0), initlist);
return build_constructor (type, nreverse (initlist));
}
@ -6818,6 +6838,62 @@ encode_type (type, curtype, format)
obstack_1grow (&util_obstack, '?');
}
static void
encode_complete_bitfield (int position, tree type, int size)
{
enum tree_code code = TREE_CODE (type);
char buffer[40];
char charType = '?';
if (code == INTEGER_TYPE)
{
if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
&& TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) == 0)
{
/* Unsigned integer types. */
if (TYPE_MODE (type) == QImode)
charType = 'C';
else if (TYPE_MODE (type) == HImode)
charType = 'S';
else if (TYPE_MODE (type) == SImode)
{
if (type == long_unsigned_type_node)
charType = 'L';
else
charType = 'I';
}
else if (TYPE_MODE (type) == DImode)
charType = 'Q';
}
else
/* Signed integer types. */
{
if (TYPE_MODE (type) == QImode)
charType = 'c';
else if (TYPE_MODE (type) == HImode)
charType = 's';
else if (TYPE_MODE (type) == SImode)
{
if (type == long_integer_type_node)
charType = 'l';
else
charType = 'i';
}
else if (TYPE_MODE (type) == DImode)
charType = 'q';
}
}
else
abort ();
sprintf (buffer, "b%d%c%d", position, charType, size);
obstack_grow (&util_obstack, buffer, strlen (buffer));
}
static void
encode_field_decl (field_decl, curtype, format)
tree field_decl;
@ -6826,18 +6902,36 @@ encode_field_decl (field_decl, curtype, format)
{
tree type;
/* If this field is obviously a bitfield, or is a bitfield that has been
type = TREE_TYPE (field_decl);
/* If this field is obviously a bitfield, or is a bitfield that has been
clobbered to look like a ordinary integer mode, go ahead and generate
the bitfield typing information. */
type = TREE_TYPE (field_decl);
if (DECL_BIT_FIELD (field_decl))
encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& DECL_FIELD_SIZE (field_decl)
&& TYPE_MODE (type) > DECL_MODE (field_decl))
encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
if (flag_next_runtime)
{
if (DECL_BIT_FIELD (field_decl))
encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& DECL_FIELD_SIZE (field_decl)
&& TYPE_MODE (type) > DECL_MODE (field_decl))
encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
else
encode_type (TREE_TYPE (field_decl), curtype, format);
}
else
encode_type (TREE_TYPE (field_decl), curtype, format);
{
if (DECL_BIT_FIELD (field_decl)
|| (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& DECL_FIELD_SIZE (field_decl)
&& TYPE_MODE (type) > DECL_MODE (field_decl)))
{
encode_complete_bitfield (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)),
DECL_BIT_FIELD_TYPE (field_decl),
DECL_FIELD_SIZE (field_decl));
}
else
encode_type (TREE_TYPE (field_decl), curtype, format);
}
}
static tree

View File

@ -59,6 +59,8 @@ struct objc_method_description
#define _C_UINT 'I'
#define _C_LNG 'l'
#define _C_ULNG 'L'
#define _C_LNG_LNG 'q'
#define _C_ULNG_LNG 'Q'
#define _C_FLT 'f'
#define _C_DBL 'd'
#define _C_BFLD 'b'
@ -495,6 +497,17 @@ class_set_version(Class class, long version)
class->version = version;
}
static inline void *
class_get_gc_object_type (Class class)
{
return CLS_ISCLASS(class) ? class->gc_object_type : NULL;
}
/* Mark the instance variable as innaccessible to the garbage collector */
extern void class_ivar_set_gcinvisible (Class class,
const char* ivarname,
BOOL gcInvisible);
static inline IMP
method_get_imp(Method_t method)
{

392
gcc/objc/objc-features.texi Normal file
View File

@ -0,0 +1,392 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename objc-features.info
@settitle GNU Objective-C runtime features
@setchapternewpage odd
@c %**end of header
@node Top, Executing code before main, , (dir), (dir)
@comment node-name, next, previous, up
@chapter GNU Objective-C runtime features
This document is meant to describe some of the GNU Objective-C runtime
features. It is not intended to teach you Objective-C, there are several
resources on the Internet that present the language. Questions and
comments about this document to Ovidiu Predescu
@code{<ovidiu@@aracnet.com>}.
@menu
* Executing code before main::
* Type encoding::
* Garbage Collection::
@end menu
@node Executing code before main, What you can and what you cannot do in +load, Top, Top
@section @code{+load}: Executing code before main
The GNU Objective-C runtime provides a way that allows you to execute
code before the execution of the program enters the @code{main}
function. The code is executed on a per-class and a per-category basis,
through a special class method @code{+load}.
This facility is very useful if you want to initialize global variables
which can be accessed by the program directly, without sending a message
to the class first. The usual way to initialize global variables, in the
@code{+initialize} method, might not be useful because
@code{+initialize} is only called when the first message is sent to a
class object, which in some cases could be too late.
Suppose for example you have a @code{FileStream} class that declares
@code{Stdin}, @code{Stdout} and @code{Stderr} as global variables, like
below:
@example
FileStream *Stdin = nil;
FileStream *Stdout = nil;
FileStream *Stderr = nil;
@@implementation FileStream
+ (void)initialize
@{
Stdin = [[FileStream new] initWithFd:0];
Stdout = [[FileStream new] initWithFd:1];
Stderr = [[FileStream new] initWithFd:2];
@}
/* Other methods here */
@@end
@end example
In this example, the initialization of @code{Stdin}, @code{Stdout} and
@code{Stderr} in @code{+initialize} occurs too late. The programmer can
send a message to one of these objects before the variables are actually
initialized, thus sending messages to the @code{nil} object. The
@code{+initialize} method which actually initializes the global
variables is not invoked until the first message is sent to the class
object. The solution would require these variables to be initialized
just before entering @code{main}.
The correct solution of the above problem is to use the @code{+load}
method instead of @code{+initialize}:
@example
@@implementation FileStream
+ (void)load
@{
Stdin = [[FileStream new] initWithFd:0];
Stdout = [[FileStream new] initWithFd:1];
Stderr = [[FileStream new] initWithFd:2];
@}
/* Other methods here */
@@end
@end example
The @code{+load} is a method that is not overridden by categories. If a
class and a category of it both implement @code{+load}, both methods are
invoked. This allows some additional initializations to be performed in
a category.
This mechanism is not intended to be a replacement for @code{+initialize}.
You should be aware of its limitations when you decide to use it
instead of @code{+initialize}.
@menu
* What you can and what you cannot do in +load::
@end menu
@node What you can and what you cannot do in +load, Type encoding, Executing code before main, Executing code before main
@subsection What you can and what you cannot do in @code{+load}
The +load implementation in the GNU runtime guarantees you the following
things:
@itemize @bullet
@item
you can write whatever C code you like;
@item
you can send messages to Objective-C constant strings (@@"this is a
constant string");
@item
you can allocate and send messages to objects whose class is implemented
in the same file;
@item
the @code{+load} implementation of all super classes of a class are executed before the @code{+load} of that class is executed;
@item
the @code{+load} implementation of a class is executed before the
@code{+load} implementation of any category.
@end itemize
In particular, the following things, even if they can work in a
particular case, are not guaranteed:
@itemize @bullet
@item
allocation of or sending messages to arbitrary objects;
@item
allocation of or sending messages to objects whose classes have a
category implemented in the same file;
@end itemize
You should make no assumptions about receiving @code{+load} in sibling
classes when you write @code{+load} of a class. The order in which
sibling classes receive @code{+load} is not guaranteed.
The order in which @code{+load} and @code{+initialize} are called could
be problematic if this matters. If you don't allocate objects inside
@code{+load}, it is guaranteed that @code{+load} is called before
@code{+initialize}. If you create an object inside @code{+load} the
@code{+initialize} method of object's class is invoked even if
@code{+load} was not invoked. Note if you explicitly call @code{+load}
on a class, @code{+initialize} will be called first. To avoid possible
problems try to implement only one of these methods.
The @code{+load} method is also invoked when a bundle is dynamically
loaded into your running program. This happens automatically without any
intervening operation from you. When you write bundles and you need to
write @code{+load} you can safely create and send messages to objects whose
classes already exist in the running program. The same restrictions as
above apply to classes defined in bundle.
@node Type encoding, Garbage Collection, What you can and what you cannot do in +load, Top
@section Type encoding
The Objective-C compiler generates type encodings for all the
types. These type encodings are used at runtime to find out information
about selectors and methods and about objects and classes.
The types are encoded in the following way:
@c @sp 1
@multitable @columnfractions .25 .75
@item @code{char}
@tab @code{c}
@item @code{unsigned char}
@tab @code{C}
@item @code{short}
@tab @code{s}
@item @code{unsigned short}
@tab @code{S}
@item @code{int}
@tab @code{i}
@item @code{unsigned int}
@tab @code{I}
@item @code{long}
@tab @code{l}
@item @code{unsigned long}
@tab @code{L}
@item @code{long long}
@tab @code{q}
@item @code{unsigned long long}
@tab @code{Q}
@item @code{float}
@tab @code{f}
@item @code{double}
@tab @code{d}
@item @code{void}
@tab @code{v}
@item @code{id}
@tab @code{@@}
@item @code{Class}
@tab @code{#}
@item @code{SEL}
@tab @code{:}
@item @code{char*}
@tab @code{*}
@item unknown type
@tab @code{?}
@item bitfields
@tab @code{b} followed by the starting position of the bitfield, the type of the bitfield and the size of the bitfield (the bitfields encoding was changed from the NeXT's compiler encoding, see below)
@end multitable
@c @sp 1
The encoding of bitfields has changed to allow bitfields to be properly
handled by the runtime functions that compute sizes and alignments of
types that contain bitfields. The previous encoding contained only the
size of the bitfield. Using only this information it is not possible to
reliably compute the size occupied by the bitfield. This is very
important in the presence of the Boehm's garbage collector because the
objects are allocated using the typed memory facility available in this
collector. The typed memory allocation requires information about where
the pointers are located inside the object.
The position in the bitfield is the position, counting in bits, of the
bit closest to the beginning of the structure.
The non-atomic types are encoded as follows:
@c @sp 1
@multitable @columnfractions .2 .8
@item pointers
@tab @code{'^'} followed by the pointed type.
@item arrays
@tab @code{'['} followed by the number of elements in the array followed by the type of the elements followed by @code{']'}
@item structures
@tab @code{'@{'} followed by the name of the structure (or '?' if the structure is unnamed), the '=' sign, the type of the members and by @code{'@}'}
@item unions
@tab @code{'('} followed by the name of the structure (or '?' if the union is unnamed), the '=' sign, the type of the members followed by @code{')'}
@end multitable
Here are some types and their encodings, as they are generated by the
compiler on a i386 machine:
@sp 1
@multitable @columnfractions .25 .75
@item Objective-C type
@tab Compiler encoding
@item
@example
int a[10];
@end example
@tab @code{[10i]}
@item
@example
struct @{
int i;
float f[3];
int a:3;
int b:2;
char c;
@}
@end example
@tab @code{@{?=i[3f]b128i3b131i2c@}}
@end multitable
@sp 1
In addition to the types the compiler also encodes the type
specifiers. The table below describes the encoding of the current
Objective-C type specifiers:
@sp 1
@multitable @columnfractions .25 .75
@item Specifier
@tab Encoding
@item @code{const}
@tab @code{r}
@item @code{in}
@tab @code{n}
@item @code{inout}
@tab @code{N}
@item @code{out}
@tab @code{o}
@item @code{bycopy}
@tab @code{O}
@item @code{oneway}
@tab @code{V}
@end multitable
@sp 1
The type specifiers are encoded just before the type. Unlike types
however, the type specifiers are only encoded when they appear in method
argument types.
@node Garbage Collection, , Type encoding, Top
@page
@section Garbage Collection
Support for a new memory management policy has been added by using a
powerful conservative garbage collector, known as the
Boehm-Demers-Weiser conservative garbage collector. It is available from
@w{@url{http://reality.sgi.com/employees/boehm_mti/gc.html}}.
To enable the support for it you have to configure the compiler using an
additional argument, @w{@kbd{--enable-objc-gc}}. You need to have
garbage collector installed before building the compiler. This will
build an additional runtime library which has several enhancements to
support the garbage collector. The new library has a new name,
@kbd{libobjc_gc.a} to not conflict with the non-garbage-collected
library.
When the garbage collector is used, the objects are allocated using the
so-called typed memory allocation mechanism available in the
Boehm-Demers-Weiser collector. This mode requires precise information on
where pointers are located inside objects. This information is computed
once per class, immediately after the class has been initialized.
There is a new runtime function @code{class_ivar_set_gcinvisible()}
which can be used to declare a so-called @strong{weak pointer}
reference. Such a pointer is basically hidden for the garbage collector;
this can be useful in certain situations, especially when you want to
keep track of the allocated objects, yet allow them to be
collected. This kind of pointers can only be members of objects, you
cannot declare a global pointer as a weak reference. Every type which is
a pointer type can be declared a weak pointer, including @code{id},
@code{Class} and @code{SEL}.
Here is an example of how to use this feature. Suppose you want to
implement a class whose instances hold a weak pointer reference; the
following class does this:
@example
@@interface WeakPointer : Object
@{
const void* weakPointer;
@}
- initWithPointer:(const void*)p;
- (const void*)weakPointer;
@@end
@@implementation WeakPointer
+ (void)initialize
@{
class_ivar_set_gcinvisible (self, "weakPointer", YES);
@}
- initWithPointer:(const void*)p
@{
weakPointer = p;
return self;
@}
- (const void*)weakPointer
@{
return weakPointer;
@}
@@end
@end example
Weak pointers are supported through a new type character specifier
represented by the @code{'!'} character. The
@code{class_ivar_set_gcinvisible()} function adds or removes this
specifier to the string type description of the instance variable named
as argument.
@bye

View File

@ -126,6 +126,7 @@ struct objc_class {
struct objc_class* sibling_class;
struct objc_protocol_list *protocols; /* Protocols conformed to */
void* gc_object_type;
};
#ifndef __OBJC__

View File

@ -25,8 +25,13 @@ Boston, MA 02111-1307, USA. */
covered by the GNU General Public License. */
#include "../tconfig.h" /* include defs of bzero for target */
#include "objc.h"
#include "runtime.h" /* the kitchen sink */
#if OBJC_WITH_GC
# include <gc.h>
#endif
id __objc_object_alloc(Class);
id __objc_object_dispose(id);
id __objc_object_copy(id);
@ -39,8 +44,16 @@ id
class_create_instance(Class class)
{
id new = nil;
#if OBJC_WITH_GC
if (CLS_ISCLASS(class))
new = (id)GC_malloc_explicitly_typed (class->instance_size,
class->gc_object_type);
#else
if (CLS_ISCLASS(class))
new = (*_objc_object_alloc)(class);
#endif
if (new!=nil)
{
memset (new, 0, class->instance_size);

View File

@ -244,10 +244,7 @@ __objc_init_install_dtable(id receiver, SEL op)
/* Install real dtable for factory methods */
__objc_install_dispatch_table_for_class (receiver->class_pointer);
if (strcmp (sel_get_name (op), "initialize"))
__objc_send_initialize((Class)receiver);
else
CLS_SETINITIALIZED((Class)receiver);
__objc_send_initialize((Class)receiver);
}
objc_mutex_unlock(__objc_runtime_mutex);
}
@ -273,36 +270,36 @@ __objc_send_initialize(Class class)
{
CLS_SETINITIALIZED(class);
CLS_SETINITIALIZED(class->class_pointer);
/* Create the garbage collector type memory description */
__objc_generate_gc_type_description (class);
if(class->super_class)
__objc_send_initialize(class->super_class);
{
SEL op = sel_register_name ("initialize");
Class tmpclass = class;
IMP imp = 0;
SEL op = sel_register_name ("initialize");
IMP imp = 0;
MethodList_t method_list = class->class_pointer->methods;
while (!imp && tmpclass) {
MethodList_t method_list = tmpclass->class_pointer->methods;
while (method_list) {
int i;
Method_t method;
while(!imp && method_list) {
int i;
Method_t method;
for (i = 0; i< method_list->method_count; i++) {
method = &(method_list->method_list[i]);
if (method->method_name
&& method->method_name->sel_id == op->sel_id) {
imp = method->method_imp;
break;
}
}
for (i=0;i<method_list->method_count;i++) {
method = &(method_list->method_list[i]);
if (method->method_name
&& method->method_name->sel_id == op->sel_id) {
imp = method->method_imp;
break;
}
}
if (imp)
break;
method_list = method_list->method_next;
method_list = method_list->method_next;
}
tmpclass = tmpclass->super_class;
}
if (imp)
(*imp)((id)class, op);