aboutsummaryrefslogtreecommitdiff
path: root/gcc/objc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1995-04-26 19:18:37 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1995-04-26 19:18:37 -0400
commit4cb8c14b60e9026068bafe4f4f9c95da525684e7 (patch)
tree6dd2c1cbffba6a2658331cdbb6c07c006948a87e /gcc/objc
parent0df0f84cb57740b5a068f15175f05116a3cf0f04 (diff)
downloadgcc-4cb8c14b60e9026068bafe4f4f9c95da525684e7.zip
gcc-4cb8c14b60e9026068bafe4f4f9c95da525684e7.tar.gz
gcc-4cb8c14b60e9026068bafe4f4f9c95da525684e7.tar.bz2
(OBJC_VERSION): Version 7.
(build_objc_string_object): Build a full declaration if not using the next runtime. (objc_add_static_instance): New function. (init_module_descriptor): Add reference to static instances table. (build_module_descriptor): Add field for static instances table. (get_objc_string_decl): New function. (generate_static_references): New function. (finish_objc): Call generate_static_references if needed. From-SVN: r9500
Diffstat (limited to 'gcc/objc')
-rw-r--r--gcc/objc/objc-act.c202
1 files changed, 193 insertions, 9 deletions
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 7dae06f..0569c0c 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -1,6 +1,6 @@
/* Implement classes and message passing for Objective C.
Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
- Author: Steve Naroff.
+ Contributed by Steve Naroff.
This file is part of GNU CC.
@@ -124,11 +124,17 @@ static struct obstack util_obstack;
so we can free the whole contents. */
char *util_firstobj;
+/* List of classes with list of their static instances. */
+static tree objc_static_instances;
+
+/* The declaration of the array administrating the static instances. */
+static tree static_instances_decl;
+
/* for encode_method_def */
#include "rtl.h"
#include "c-parse.h"
-#define OBJC_VERSION (flag_next_runtime ? 5 : 6)
+#define OBJC_VERSION (flag_next_runtime ? 5 : 7)
#define PROTOCOL_VERSION 2
#define NULLT (tree) 0
@@ -155,6 +161,8 @@ static tree get_proto_encoding PROTO((tree));
static void build_selector_translation_table PROTO((void));
static tree build_ivar_chain PROTO((tree, int));
+static tree objc_add_static_instance PROTO((tree, tree));
+
static tree build_ivar_template PROTO((void));
static tree build_method_template PROTO((void));
static tree build_private_template PROTO((tree));
@@ -321,6 +329,7 @@ static void handle_class_ref PROTO((tree));
#define UTAG_METHOD_LIST "_objc_method_list"
#define UTAG_CATEGORY "_objc_category"
#define UTAG_MODULE "_objc_module"
+#define UTAG_STATICS "_objc_statics"
#define UTAG_SYMTAB "_objc_symtab"
#define UTAG_SUPER "_objc_super"
#define UTAG_SELECTOR "_objc_selector"
@@ -1122,8 +1131,10 @@ synth_module_prologue ()
UOBJC_SELECTOR_TABLE_decl
= create_builtin_decl (VAR_DECL, temp_type,
"_OBJC_SELECTOR_TABLE");
- }
+ /* Avoid warning when not sending messages. */
+ TREE_USED (UOBJC_SELECTOR_TABLE_decl) = 1;
+ }
generate_forward_declaration_to_string_table ();
@@ -1204,13 +1215,59 @@ build_objc_string_object (strings)
/* & ((NXConstantString) {0, string, length}) */
initlist = build_tree_list (NULLT, build_int_2 (0, 0));
- initlist = tree_cons (NULLT, build_unary_op (ADDR_EXPR, string, 1),
- initlist);
- initlist = tree_cons (NULLT, build_int_2 (length, 0), initlist);
+ initlist = perm_tree_cons (NULLT,
+ copy_node (build_unary_op (ADDR_EXPR, string, 1)),
+ initlist);
+ initlist = perm_tree_cons (NULLT, build_int_2 (length, 0), initlist);
constructor = build_constructor (constant_string_type,
nreverse (initlist));
- return build_unary_op (ADDR_EXPR, constructor, 1);
+ if (!flag_next_runtime)
+ constructor = objc_add_static_instance (constructor, constant_string_type);
+ return (build_unary_op (ADDR_EXPR, constructor, 1));
+}
+
+/* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
+static tree
+objc_add_static_instance (constructor, class_decl)
+ tree constructor, class_decl;
+{
+ static int num_static_inst;
+ struct obstack *save_current_obstack = current_obstack;
+ struct obstack *save_rtl_obstack = rtl_obstack;
+ tree *chain, decl, decl_spec, decl_expr;
+ char buf[256];
+
+ rtl_obstack = current_obstack = &permanent_obstack;
+
+ /* Find the list of static instances for the CLASS_DECL. Create one if
+ not found. */
+ for (chain = &objc_static_instances;
+ *chain && TREE_VALUE (*chain) != class_decl;
+ chain = &TREE_CHAIN (*chain));
+ if (!*chain)
+ {
+ *chain = perm_tree_cons (NULLT, class_decl, NULLT);
+ add_objc_string (TYPE_NAME (class_decl), class_names);
+ }
+
+ sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
+ decl_expr = get_identifier (buf);
+ decl_spec = tree_cons (NULLT, class_decl,
+ build_tree_list (NULLT,
+ ridpointers[(int) RID_STATIC]));
+ decl = start_decl (decl_expr, decl_spec, 1);
+ end_temporary_allocation ();
+
+ /* Barf! Make sure this decl will end up at the global binding level. */
+ finish_decl_top_level (decl, constructor, NULLT);
+
+ current_obstack = save_current_obstack;
+ rtl_obstack = save_rtl_obstack;
+
+ /* Add the DECL to the head of this CLASS' list. */
+ TREE_PURPOSE (*chain) = perm_tree_cons (NULLT, decl, TREE_PURPOSE (*chain));
+ return (decl);
}
/* Build a static constant CONSTRUCTOR
@@ -1440,6 +1497,18 @@ init_module_descriptor (type)
expr = add_objc_string (get_identifier (input_filename), class_names);
initlist = tree_cons (NULLT, expr, initlist);
+
+ if (!flag_next_runtime)
+ {
+ /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
+ if (static_instances_decl)
+ expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0);
+ else
+ expr = build_int_2 (0, 0);
+ initlist = tree_cons (NULLT, expr, initlist);
+ }
+
+
/* symtab = { ..., _OBJC_SYMBOLS, ... } */
if (UOBJC_SYMBOLS_decl)
@@ -1489,6 +1558,20 @@ build_module_descriptor ()
field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
chainon (field_decl_chain, field_decl);
+
+ if (!flag_next_runtime)
+ {
+ /* void *statics */
+
+ decl_specs = get_identifier (UTAG_STATICS);
+ decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
+ field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("statics"));
+ field_decl = grokfield (input_filename, lineno, field_decl,
+ decl_specs, NULLT);
+ chainon (field_decl_chain, field_decl);
+ }
+
+
/* struct objc_symtab *symtab; */
decl_specs = get_identifier (UTAG_SYMTAB);
@@ -1598,6 +1681,104 @@ generate_forward_declaration_to_string_table ()
UOBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
}
+/* Return the DECL of the string IDENT in the SECTION. */
+static tree
+get_objc_string_decl (ident, section)
+ tree ident;
+ enum string_section section;
+{
+ tree chain, decl;
+
+ if (section == class_names)
+ chain = class_names_chain;
+ else if (section == meth_var_names)
+ chain = meth_var_names_chain;
+ else if (section == meth_var_types)
+ chain = meth_var_types_chain;
+
+ while (chain)
+ {
+ if (TREE_VALUE (chain) == ident)
+ return (TREE_PURPOSE (chain));
+
+ chain = TREE_CHAIN (chain);
+ }
+
+ abort ();
+ return NULLT;
+}
+
+/* Output references to all statically allocated objects. Return the DECL
+ for the array built. */
+static tree
+generate_static_references ()
+{
+ tree decls = NULLT, ident, decl_spec, expr_decl, expr = NULLT;
+ tree class_name, class, decl, instance, idecl, initlist;
+ tree cl_chain, in_chain, type;
+ int num_inst, num_class;
+ char buf[256];
+
+ if (flag_next_runtime)
+ abort ();
+
+
+ for (cl_chain = objc_static_instances, num_class = 0;
+ cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
+ {
+ for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
+ in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
+
+ sprintf (buf, "_OBJC_STATIC_INSTANCES_%d", num_class);
+ ident = get_identifier (buf);
+
+ expr_decl = build_nt (ARRAY_REF, ident, NULLT);
+ decl_spec = tree_cons (NULLT, build_pointer_type (void_type_node),
+ build_tree_list (NULLT,
+ ridpointers[(int) RID_STATIC]));
+ decl = start_decl (expr_decl, decl_spec, 1);
+ end_temporary_allocation ();
+
+ /* Output {class_name, ...}. */
+ class = TREE_VALUE (cl_chain);
+ class_name = get_objc_string_decl (TYPE_NAME (class), class_names);
+ initlist = build_tree_list (NULLT,
+ build_unary_op (ADDR_EXPR, class_name, 1));
+
+ /* Output {..., instance, ...}. */
+ for (in_chain = TREE_PURPOSE (cl_chain);
+ in_chain; in_chain = TREE_CHAIN (in_chain))
+ {
+ expr = build_unary_op (ADDR_EXPR, TREE_VALUE (in_chain), 1);
+ initlist = tree_cons (NULLT, expr, initlist);
+ }
+
+ /* Output {..., NULL}. */
+ initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
+
+ expr = build_constructor (TREE_TYPE (decl), nreverse (initlist));
+ finish_decl (decl, expr, NULLT);
+ TREE_USED (decl) = 1;
+
+ type = build_array_type (build_pointer_type (void_type_node), 0);
+ decl = build_decl (VAR_DECL, ident, type);
+ make_decl_rtl (decl, 0, 1);
+ TREE_USED (decl) = 1;
+ decls = tree_cons (NULLT, build_unary_op (ADDR_EXPR, decl, 1), decls);
+ }
+ decls = tree_cons (NULLT, build_int_2 (0, 0), decls);
+ ident = get_identifier ("_OBJC_STATIC_INSTANCES");
+ expr_decl = build_nt (ARRAY_REF, ident, NULLT);
+ decl_spec = tree_cons (NULLT, build_pointer_type (void_type_node),
+ build_tree_list (NULLT,
+ ridpointers[(int) RID_STATIC]));
+ static_instances_decl = start_decl (expr_decl, decl_spec, 1);
+ end_temporary_allocation ();
+ expr = build_constructor (TREE_TYPE (static_instances_decl),
+ nreverse (decls));
+ finish_decl (static_instances_decl, expr, NULLT);
+}
+
/* Output all strings. */
static void
@@ -2049,7 +2230,7 @@ build_objc_string_decl (name, section)
TREE_USED (decl) = 1;
TREE_READONLY (decl) = 1;
TREE_CONSTANT (decl) = 1;
-
+
make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation */
pushdecl_top_level (decl); /* our `extended/custom' pushdecl in c-decl.c */
@@ -7531,7 +7712,10 @@ finish_objc ()
if (protocol_chain)
generate_protocols ();
- if (implementation_context || class_names_chain
+ if (objc_static_instances)
+ generate_static_references ();
+
+ if (implementation_context || class_names_chain || objc_static_instances
|| meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
{
/* Arrange for Objc data structures to be initialized at run time. */