Commit 5d0f30f7 by Kresten Krab Thorup

objc-act.c (get_proto_encoding, [...]): New fucnctions.

        * objc-act.c (get_proto_encoding, build_typed_selector_reference):
        New fucnctions. (UTAG_PROTOCOL): New define.
        (objc_selector_template, flag_typed_selectors): New variables.
        (objc_init): set flag_typed_selectors if -fgnu-runtime.
        (synth_module_prologue): Change declaration of
        _OBJC_SELECTOR_TABLE when flag_typed_selectors is non-null.
        (build_module_descriptor): Make sure the generated constructor
        function is declared public.
        (build_selector): Only cast to SEL when not doing typed selectors.
        (build_selector_translation_table): Rewrite initialization.
        (build_tmp_function_decl): Make up new name when called, since it
        may now be called multiple times.
        (hack_method_prototype): Use init_function_start to reinit args
        machinery.  Also set current_function_decl before calling
        assign_parms.
        (generate_protocols):  Don't generate encoding twice.
        (build_selector_template): New function.
        (build_method_list_template): Generate (void*)0 as first element,
        not (int)0.
        (build_message_expr): move the call to build_selector_reference
        towards the end, where we have determined the function prototype.

From-SVN: r7620
parent bd4d60ce
......@@ -47,6 +47,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "input.h"
#include "function.h"
/* This is the default way of generating a method name. */
/* I am not sure it is really correct.
Perhaps there's a danger that it will make name conflicts
......@@ -127,7 +128,7 @@ char *util_firstobj;
#include "rtl.h"
#include "c-parse.h"
#define OBJC_VERSION 5
#define OBJC_VERSION 6
#define PROTOCOL_VERSION 2
#define NULLT (tree) 0
......@@ -150,6 +151,7 @@ static char *build_module_descriptor PROTO((void));
static tree init_module_descriptor PROTO((tree));
static tree build_objc_method_call PROTO((int, tree, tree, tree, tree, tree));
static void generate_strings PROTO((void));
static tree get_proto_encoding PROTO((tree));
static void build_selector_translation_table PROTO((void));
static tree build_ivar_chain PROTO((tree, int));
......@@ -157,6 +159,7 @@ static tree build_ivar_template PROTO((void));
static tree build_method_template PROTO((void));
static tree build_private_template PROTO((tree));
static void build_class_template PROTO((void));
static void build_selector_template PROTO((void));
static void build_category_template PROTO((void));
static tree build_super_template PROTO((void));
static tree build_category_initializer PROTO((tree, tree, tree, tree, tree, tree));
......@@ -263,6 +266,7 @@ static void forward_declare_categories PROTO((void));
static void generate_objc_symtab_decl PROTO((void));
static tree build_selector PROTO((tree));
static tree build_msg_pool_reference PROTO((int));
static tree build_typed_selector_reference PROTO((tree, tree));
static tree build_selector_reference PROTO((tree));
static tree build_class_reference_decl PROTO((tree));
static void add_class_reference PROTO((tree));
......@@ -319,6 +323,7 @@ static void handle_class_ref PROTO((tree));
#define UTAG_MODULE "_objc_module"
#define UTAG_SYMTAB "_objc_symtab"
#define UTAG_SUPER "_objc_super"
#define UTAG_SELECTOR "_objc_selector"
#define UTAG_PROTOCOL "_objc_protocol"
#define UTAG_PROTOCOL_LIST "_objc_protocol_list"
......@@ -414,7 +419,7 @@ static int imp_count = 0; /* `@implementation' */
static int cat_count = 0; /* `@category' */
static tree objc_class_template, objc_category_template, uprivate_record;
static tree objc_protocol_template;
static tree objc_protocol_template, objc_selector_template;
static tree ucls_super_ref, uucls_super_ref;
static tree objc_method_template, objc_ivar_template;
......@@ -436,6 +441,7 @@ static char *errbuf; /* a buffer for error diagnostics */
/* data imported from tree.c */
extern struct obstack permanent_obstack, *current_obstack, *rtl_obstack;
extern enum debug_info_type write_symbols;
/* data imported from toplev.c */
......@@ -449,6 +455,8 @@ int flag_next_runtime = 1;
int flag_next_runtime = 0;
#endif
int flag_typed_selectors;
/* Open and close the file for outputting class declarations, if requested. */
int flag_gen_declaration = 0;
......@@ -509,6 +517,7 @@ lang_init ()
TAG_MSGSEND = "objc_msg_lookup";
TAG_MSGSENDSUPER = "objc_msg_lookup_super";
TAG_EXECCLASS = "__objc_exec_class";
flag_typed_selectors = 1;
}
if (doing_objc_thang)
......@@ -1086,12 +1095,29 @@ synth_module_prologue ()
/* static SEL _OBJC_SELECTOR_TABLE[]; */
if (! flag_next_runtime)
{
if (flag_typed_selectors)
{
/* supress outputting debug symbols, because
dbxout_init hasn'r been called yet... */
enum debug_info_type save_write_symbols = write_symbols;
write_symbols = NO_DEBUG;
build_selector_template ();
temp_type = build_array_type (objc_selector_template, NULLT);
write_symbols = save_write_symbols;
}
else
temp_type = build_array_type (selector_type, NULLT);
layout_type (temp_type);
if (! flag_next_runtime)
UOBJC_SELECTOR_TABLE_decl
= create_builtin_decl (VAR_DECL, temp_type,
"_OBJC_SELECTOR_TABLE");
}
generate_forward_declaration_to_string_table ();
......@@ -1510,6 +1536,7 @@ build_module_descriptor ()
function_type);
DECL_EXTERNAL (function_decl) = 1;
TREE_PUBLIC (function_decl) = 1;
pushdecl (function_decl);
rest_of_decl_compilation (function_decl, 0, 0, 0);
......@@ -1540,6 +1567,9 @@ build_module_descriptor ()
assemble_external (function_decl);
c_expand_expr_stmt (decelerator);
TREE_PUBLIC (current_function_decl) = 1;
DECL_EXTERNAL (current_function_decl) = 1;
finish_function (0);
/* Return the name of the constructor function. */
......@@ -1652,7 +1682,9 @@ build_selector (ident)
tree ident;
{
tree expr = add_objc_string (ident, meth_var_names);
if (flag_typed_selectors)
return expr;
else
return build_c_cast (selector_type, expr); /* cast! */
}
......@@ -1730,7 +1762,19 @@ build_selector_translation_table ()
finish_decl (decl, expr, NULLT);
}
else
{
if (flag_typed_selectors)
{
tree eltlist = NULLT;
tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
eltlist = tree_cons (NULLT, expr, NULLT);
eltlist = tree_cons (NULLT, encoding, eltlist);
expr = build_constructor (objc_selector_template,
nreverse (eltlist));
}
initlist = tree_cons (NULLT, expr, initlist);
}
}
if (! flag_next_runtime)
......@@ -1747,15 +1791,67 @@ build_selector_translation_table ()
}
}
static tree
get_proto_encoding (proto)
tree proto;
{
tree encoding;
if (proto)
{
tree tmp_decl;
if (! METHOD_ENCODING (proto))
{
tmp_decl = build_tmp_function_decl ();
hack_method_prototype (proto, tmp_decl);
encoding = encode_method_prototype (proto, tmp_decl);
METHOD_ENCODING (proto) = encoding;
}
else
encoding = METHOD_ENCODING (proto);
return add_objc_string (encoding, meth_var_types);
}
else
return build_int_2 (0, 0);
}
/* sel_ref_chain is a list whose "value" fields will be instances of
identifier_node that represent the selector. */
static tree
build_typed_selector_reference (ident, proto)
tree ident, proto;
{
tree *chain = &sel_ref_chain;
tree expr;
int index = 0;
while (*chain)
{
if (TREE_PURPOSE (*chain) == ident && TREE_VALUE (*chain) == proto)
goto return_at_index;
index++;
chain = &TREE_CHAIN (*chain);
}
*chain = perm_tree_cons (proto, ident, NULLT);
return_at_index:
expr = build_unary_op (ADDR_EXPR,
build_array_ref (UOBJC_SELECTOR_TABLE_decl,
build_int_2 (index, 0)),
1);
return build_c_cast (selector_type, expr);
}
static tree
build_selector_reference (ident)
tree ident;
{
tree *chain = &sel_ref_chain;
tree decl;
tree expr;
int index = 0;
while (*chain)
......@@ -1770,12 +1866,12 @@ build_selector_reference (ident)
chain = &TREE_CHAIN (*chain);
}
decl = build_selector_reference_decl (ident);
expr = build_selector_reference_decl (ident);
*chain = perm_tree_cons (decl, ident, NULLT);
*chain = perm_tree_cons (expr, ident, NULLT);
return (flag_next_runtime
? decl
? expr
: build_array_ref (UOBJC_SELECTOR_TABLE_decl,
build_int_2 (index, 0)));
}
......@@ -2531,6 +2627,8 @@ static tree
build_tmp_function_decl ()
{
tree decl_specs, expr_decl, parms;
static int xxx = 0;
char buffer[80];
/* struct objc_object *objc_xxx (id, SEL, ...); */
pushlevel (0);
......@@ -2547,7 +2645,8 @@ build_tmp_function_decl ()
poplevel (0, 0, 0);
decl_specs = build_tree_list (NULLT, objc_object_reference);
expr_decl = build_nt (CALL_EXPR, get_identifier ("objc_xxx"), parms, NULLT);
sprintf (buffer, "__objc_tmp_%x", xxx++);
expr_decl = build_nt (CALL_EXPR, get_identifier (buffer), parms, NULLT);
expr_decl = build1 (INDIRECT_REF, NULLT, expr_decl);
return define_decl (expr_decl, decl_specs);
......@@ -2574,9 +2673,8 @@ hack_method_prototype (nst_methods, tmp_decl)
/* Usually called from store_parm_decls -> init_function_start. */
init_emit (); /* needed to make assign_parms work (with -O). */
DECL_ARGUMENTS (tmp_decl) = TREE_PURPOSE (parms);
current_function_decl = tmp_decl;
{
/* Code taken from start_function. */
......@@ -2588,11 +2686,14 @@ hack_method_prototype (nst_methods, tmp_decl)
DECL_RESULT (tmp_decl) = build_decl (RESULT_DECL, 0, restype);
}
init_function_start (tmp_decl, "objc-act", 0);
/* Typically called from expand_function_start for function definitions. */
assign_parms (tmp_decl, 0);
/* install return type */
TREE_TYPE (TREE_TYPE (tmp_decl)) = groktypename (TREE_TYPE (nst_methods));
}
static void
......@@ -2650,18 +2751,23 @@ generate_protocols ()
while (nst_methods)
{
if (! METHOD_ENCODING (nst_methods))
{
hack_method_prototype (nst_methods, tmp_decl);
encoding = encode_method_prototype (nst_methods, tmp_decl);
METHOD_ENCODING (nst_methods) = encoding;
}
nst_methods = TREE_CHAIN (nst_methods);
}
while (cls_methods)
{
if (! METHOD_ENCODING (cls_methods))
{
hack_method_prototype (cls_methods, tmp_decl);
encoding = encode_method_prototype (cls_methods, tmp_decl);
METHOD_ENCODING (cls_methods) = encoding;
}
cls_methods = TREE_CHAIN (cls_methods);
}
......@@ -2815,6 +2921,37 @@ build_category_template ()
finish_struct (objc_category_template, field_decl_chain);
}
/* struct objc_selector {
void *sel_id;
char *sel_type;
}; */
static void
build_selector_template ()
{
tree decl_specs, field_decl, field_decl_chain;
objc_selector_template
= start_struct (RECORD_TYPE, get_identifier (UTAG_SELECTOR));
/* void *sel_id; */
decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_VOID]);
field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("sel_id"));
field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
field_decl_chain = field_decl;
/* char *sel_type; */
decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("sel_type"));
field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
chainon (field_decl_chain, field_decl);
finish_struct (objc_selector_template, field_decl_chain);
}
/* struct objc_class {
struct objc_class *isa;
struct objc_class *super_class;
......@@ -3193,9 +3330,10 @@ build_method_list_template (list_type, size)
/* int method_next; */
decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
field_decl = get_identifier ("method_next");
decl_specs = build_tree_list (NULLT,
xref_tag (RECORD_TYPE,
get_identifier (UTAG_METHOD_PROTOTYPE_LIST)));
field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_next"));
field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
field_decl_chain = field_decl;
......@@ -4343,11 +4481,6 @@ build_message_expr (mess)
else if (TREE_CODE (args) == TREE_LIST)
sel_name = build_keyword_selector (args);
/* Build the parameters list for looking up the method.
These are the object itself and the selector. */
selector = build_selector_reference (sel_name);
/* Build the parameter list to give to the method. */
method_params = NULLT;
......@@ -4544,6 +4677,14 @@ build_message_expr (mess)
/* Save the selector name for printing error messages. */
building_objc_message_expr = sel_name;
/* Build the parameters list for looking up the method.
These are the object itself and the selector. */
if (flag_typed_selectors)
selector = build_typed_selector_reference (sel_name, method_prototype);
else
selector = build_selector_reference (sel_name);
retval = build_objc_method_call (super, method_prototype,
receiver, self_object,
selector, method_params);
......@@ -4744,6 +4885,9 @@ build_selector_expr (selnamelist)
else if (TREE_CODE (selnamelist) == TREE_LIST)
selname = build_keyword_selector (selnamelist);
if (flag_typed_selectors)
return build_typed_selector_reference (selname, 0);
else
return build_selector_reference (selname);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment