diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-10-12 09:46:38 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-10-12 09:46:38 -0700 |
commit | 9cd320ea6572c577cdf17ce1f9ea5230b166af6d (patch) | |
tree | d1c8e7c2e09a91ed75f0e5476c648c2e745aa2de /gcc/objc | |
parent | 4854d721be78358e59367982bdd94461b4be3c5a (diff) | |
parent | 3175d40fc52fb8eb3c3b18cc343d773da24434fb (diff) | |
download | gcc-9cd320ea6572c577cdf17ce1f9ea5230b166af6d.zip gcc-9cd320ea6572c577cdf17ce1f9ea5230b166af6d.tar.gz gcc-9cd320ea6572c577cdf17ce1f9ea5230b166af6d.tar.bz2 |
Merge from trunk revision 3175d40fc52fb8eb3c3b18cc343d773da24434fb.
Diffstat (limited to 'gcc/objc')
-rw-r--r-- | gcc/objc/ChangeLog | 108 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 6 | ||||
-rw-r--r-- | gcc/objc/objc-gnu-runtime-abi-01.c | 36 | ||||
-rw-r--r-- | gcc/objc/objc-next-runtime-abi-01.c | 4 | ||||
-rw-r--r-- | gcc/objc/objc-next-runtime-abi-02.c | 474 | ||||
-rw-r--r-- | gcc/objc/objc-runtime-shared-support.c | 9 |
6 files changed, 476 insertions, 161 deletions
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 5d8500c..f69d2d7 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,111 @@ +2020-10-11 Iain Sandoe <iain@sandoe.co.uk> + + * objc-next-runtime-abi-02.c + (create_global_decl): Update to allow the caller to + specify declaration or definition. + (create_hidden_decl): Likewise. + (next_runtime_abi_02_protocol_decl): Make the symbol + weak and hidden for later OS runtime versions. + (build_v2_protocol_list_address_table): Likewise. + +2020-10-11 Iain Sandoe <iain@sandoe.co.uk> + + * objc-next-runtime-abi-02.c (objc_v2_build_ivar_ref): Test + DECL_C_BIT_FIELD to detect that an ivar is a bitfield. + +2020-10-11 Iain Sandoe <iain@sandoe.co.uk> + + * objc-next-runtime-abi-02.c (FIXUP_NEEDED): Rename ... + (USE_FIXUP_BEFORE): ... to this. + (next_runtime_02_initialize): Likewise. + (next_runtime_abi_02_get_arg_type_list_base): Likewise. + (next_runtime_abi_02_build_objc_method_call): Likewise. + +2020-10-11 Iain Sandoe <iain@sandoe.co.uk> + + * objc-next-runtime-abi-02.c (TAG_MSGSENDSUPER): Revised + spelling. + (TAG_MSGSENDID): Likewise. + (TAG_MSGSENDSUPER_STRET): Likewise. + (TAG_MSGSENDID_STRET): Likewise. + (FIXUP_NEEDED): Likewise. + (TAG_FIXUP): New. + (next_runtime_02_initialize): Adjust message calls to use + fixup variants only when required. + (next_runtime_abi_02_get_arg_type_list_base): Correct + indent. + (build_v2_build_objc_method_call): New. + (build_v2_objc_method_fixup_call): Split out from ... + (next_runtime_abi_02_build_objc_method_call): ... here. + Arrange to adjust the call on the basis of the target + runtime. + +2020-10-11 Iain Sandoe <iain@sandoe.co.uk> + + * objc-runtime-shared-support.c (start_var_decl): Make the + decl_assembler_name follow the metadata name for C++ on NeXT + runtime platforms. + +2020-10-11 Iain Sandoe <iain@sandoe.co.uk> + + * objc-next-runtime-abi-02.c + (next_runtime_abi_02_category_decl): Adjust category + superclass name ordering. + +2020-10-11 Iain Sandoe <iain@sandoe.co.uk> + + * objc-next-runtime-abi-02.c (build_v2_super_template): Add new + fields to the template. + (build_v2_protocol_template): Build new field entries. + (generate_v2_meth_descriptor_table): Adjust to allow recording all + method types. + (generate_v2_meth_type_list): New. + (build_v2_protocol_initializer): Initialize the additional fields. + (generate_v2_protocols): Record method types for all entries and + generate the additional method type table. + +2020-10-10 Iain Sandoe <iain@sandoe.co.uk> + + * objc-next-runtime-abi-02.c + (objc_get_superclass_ref_decl): Split this code out. + (next_runtime_abi_02_get_class_super_ref): Compute + super refs using the objc_get_superclass_ref_decl(). + (next_runtime_abi_02_get_category_super_ref): Likewise. + +2020-10-10 Iain Sandoe <iain@sandoe.co.uk> + + * objc-next-runtime-abi-02.c + (next_runtime_abi_02_init_metadata_attributes): Make protocol + refs a distinct section. + +2020-10-10 Iain Sandoe <iain@sandoe.co.uk> + + * objc-next-runtime-abi-02.c + (next_runtime_abi_02_init_metadata_attributes): Attach metadata + for the special string sections to class, method and method type + string sections. + +2020-10-10 Iain Sandoe <iain@sandoe.co.uk> + + * objc-gnu-runtime-abi-01.c + (build_shared_structure_initializer): Remove references to + the NeXT runtime. + (generate_static_references): Likewise. + +2020-09-19 Sandra Loosemore <sandra@codesourcery.com> + + * objc-act.c (objc_start_method_definition): Update to reflect + changes to break/continue state bookkeeping in C front end. + +2020-09-17 Patrick Palka <ppalka@redhat.com> + + PR c/80076 + * objc-gnu-runtime-abi-01.c + (gnu_runtime_abi_01_get_class_super_ref): Reduce indentation of + misleadingly indented return statements. + * objc-next-runtime-abi-01.c + (next_runtime_abi_01_get_class_super_ref): Likewise. + 2020-01-01 Jakub Jelinek <jakub@redhat.com> Update copyright years. diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 54af1cf..31a2cf3 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -2050,10 +2050,8 @@ objc_start_method_definition (bool is_class_method, tree decl, tree attributes, return false; #ifndef OBJCPLUS - /* Indicate no valid break/continue context by setting these variables - to some non-null, non-label value. We'll notice and emit the proper - error message in c_finish_bc_stmt. */ - c_break_label = c_cont_label = size_zero_node; + /* Indicate no valid break/continue context. */ + in_statement = 0; #endif if (attributes) diff --git a/gcc/objc/objc-gnu-runtime-abi-01.c b/gcc/objc/objc-gnu-runtime-abi-01.c index d586243..25c0e01 100644 --- a/gcc/objc/objc-gnu-runtime-abi-01.c +++ b/gcc/objc/objc-gnu-runtime-abi-01.c @@ -821,7 +821,7 @@ gnu_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, ucls_super_ref = objc_build_component_ref (imp->class_decl, get_identifier ("super_class")); - return ucls_super_ref; + return ucls_super_ref; } else { @@ -829,7 +829,7 @@ gnu_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, uucls_super_ref = objc_build_component_ref (imp->meta_decl, get_identifier ("super_class")); - return uucls_super_ref; + return uucls_super_ref; } } @@ -1540,25 +1540,14 @@ build_shared_structure_initializer (tree type, tree isa, tree super, CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); } - /* FIXME: Remove NeXT runtime code. */ - if (flag_next_runtime) - { - ltyp = build_pointer_type (xref_tag (RECORD_TYPE, - get_identifier ("objc_cache"))); - /* method_cache = */ - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node)); - } - else - { - /* dtable = */ - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); + /* dtable = */ + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); - /* subclass_list = */ - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); + /* subclass_list = */ + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); - /* sibling_class = */ - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); - } + /* sibling_class = */ + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); /* protocol_list = */ ltyp = build_pointer_type (build_pointer_type (objc_protocol_template)); @@ -1572,11 +1561,6 @@ build_shared_structure_initializer (tree type, tree isa, tree super, CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); } - /* FIXME: Remove NeXT runtime code. */ - if (flag_next_runtime) - /* sel_id = NULL */ - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); - /* gc_object_type = NULL */ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); @@ -1864,10 +1848,6 @@ generate_static_references (void) char buf[BUFSIZE]; vec<constructor_elt, va_gc> *decls = NULL; - /* FIXME: Remove NeXT runtime code. */ - if (flag_next_runtime) - gcc_unreachable (); - for (cl_chain = objc_static_instances, num_class = 0; cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++) { diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c index 5c34fcb..233d89e 100644 --- a/gcc/objc/objc-next-runtime-abi-01.c +++ b/gcc/objc/objc-next-runtime-abi-01.c @@ -938,7 +938,7 @@ next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, ucls_super_ref = objc_build_component_ref (imp->class_decl, get_identifier ("super_class")); - return ucls_super_ref; + return ucls_super_ref; } else { @@ -946,7 +946,7 @@ next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, uucls_super_ref = objc_build_component_ref (imp->meta_decl, get_identifier ("super_class")); - return uucls_super_ref; + return uucls_super_ref; } } diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c index e401906..d7812ff 100644 --- a/gcc/objc/objc-next-runtime-abi-02.c +++ b/gcc/objc/objc-next-runtime-abi-02.c @@ -63,9 +63,15 @@ along with GCC; see the file COPYING3. If not see #define TAG_GETMETACLASS "objc_getMetaClass" #define TAG_MSGSEND "objc_msgSend" -#define TAG_MSGSENDSUPER "objc_msgSendSuper" +#define TAG_MSGSENDID "objc_msgSendId" +#define TAG_MSGSENDSUPER "objc_msgSendSuper2" #define TAG_MSGSEND_STRET "objc_msgSend_stret" -#define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret" +#define TAG_MSGSENDID_STRET "objc_msgSendId_stret" +#define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper2_stret" + +#define USE_FIXUP_BEFORE 100600 +#define TAG_FIXUP "_fixup" + #define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable" #define TAG_V2_EH_TYPE "objc_ehtype_t" @@ -305,8 +311,8 @@ next_runtime_abi_02_init_metadata_attributes (void) meta_class = get_identifier ("G2_CLAS"); meta_metaclass = get_identifier ("G2_META"); - meta_category = - meta_protocol = meta_base; + meta_category = meta_base; + meta_protocol = get_identifier ("V2_PCOL"); meta_clac_vars = meta_clai_vars = meta_base; @@ -323,9 +329,10 @@ next_runtime_abi_02_init_metadata_attributes (void) meta_sel_refs = get_identifier ("V2_SRFS"); - meta_class_name = - meta_meth_name = - meta_meth_type = + meta_class_name = get_identifier ("V2_CNAM"); + meta_meth_name = get_identifier ("V2_MNAM"); + + meta_meth_type = get_identifier ("V2_MTYP"); meta_prop_name_attr = get_identifier ("V2_STRG"); meta_mref = get_identifier ("V2_MREF"); @@ -385,32 +392,43 @@ static void next_runtime_02_initialize (void) build_v2_protocol_template (); build_v2_category_template (); - /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */ - type = build_varargs_function_type_list (objc_object_type, - objc_object_type, - objc_v2_selector_type, - NULL_TREE); - umsg_fixup_decl = add_builtin_function ("objc_msgSend_fixup", - type, 0, NOT_BUILT_IN, + bool fixup_p = flag_next_runtime < USE_FIXUP_BEFORE; + if (fixup_p) + { + /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */ + type = build_varargs_function_type_list (objc_object_type, + objc_object_type, + objc_v2_selector_type, + NULL_TREE); + } + else + { + /* id objc_msgSendXXXX (id, SEL, ...); */ + type = build_varargs_function_type_list (objc_object_type, + objc_object_type, + objc_selector_type, + NULL_TREE); + } + const char *fnam = fixup_p ? TAG_MSGSEND TAG_FIXUP : TAG_MSGSEND; + umsg_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); TREE_NOTHROW (umsg_fixup_decl) = 0; /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */ - umsg_stret_fixup_decl = add_builtin_function ("objc_msgSend_stret_fixup", - type, 0, NOT_BUILT_IN, + fnam = fixup_p ? TAG_MSGSEND_STRET TAG_FIXUP : TAG_MSGSEND_STRET; + umsg_stret_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); TREE_NOTHROW (umsg_stret_fixup_decl) = 0; /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */ - umsg_id_fixup_decl = add_builtin_function ("objc_msgSendId_fixup", - type, 0, NOT_BUILT_IN, + fnam = fixup_p ? TAG_MSGSENDID TAG_FIXUP : TAG_MSGSENDID; + umsg_id_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); TREE_NOTHROW (umsg_id_fixup_decl) = 0; - /* id objc_msgSendId_stret_fixup_rtp - (id, struct message_ref_t*, ...); */ - umsg_id_stret_fixup_decl = add_builtin_function ("objc_msgSendId_stret_fixup", - type, 0, NOT_BUILT_IN, + /* id objc_msgSendId_stret_fixup_rtp (id, struct message_ref_t*, ...); */ + fnam = fixup_p ? TAG_MSGSENDID_STRET TAG_FIXUP : TAG_MSGSENDID_STRET; + umsg_id_stret_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0; @@ -420,17 +438,17 @@ static void next_runtime_02_initialize (void) objc_super_type, objc_v2_super_selector_type, NULL_TREE); - umsg_id_super2_fixup_decl = add_builtin_function ("objc_msgSendSuper2_fixup", - type, 0, NOT_BUILT_IN, + fnam = fixup_p ? TAG_MSGSENDSUPER TAG_FIXUP : TAG_MSGSENDSUPER; + umsg_id_super2_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0; /* id objc_msgSendSuper2_stret_fixup_rtp (struct objc_super *, struct message_ref_t*, ...); */ - umsg_id_super2_stret_fixup_decl = - add_builtin_function ("objc_msgSendSuper2_stret_fixup", - type, 0, NOT_BUILT_IN, - NULL, NULL_TREE); + fnam = fixup_p ? TAG_MSGSENDSUPER_STRET TAG_FIXUP : TAG_MSGSENDSUPER_STRET; + umsg_id_super2_stret_fixup_decl = add_builtin_function (fnam, type, 0, + NOT_BUILT_IN, NULL, + NULL_TREE); TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0; /* Present in the library, but unused by the FE. */ @@ -742,6 +760,9 @@ build_v2_super_template (void) const struct _prop_list_t * const properties; const uint32_t size; const uint32_t flags; + const char ** extended_method_types; + const char * demangled_name; + const struct _prop_list_t * class_properties; } */ static void @@ -783,6 +804,16 @@ build_v2_protocol_template (void) /* const uint32_t flags; */ add_field_decl (integer_type_node, "flags", &chain); + /* const char **extendedMethodTypes; */ + tree ptr_to_ptr_to_char = build_pointer_type (string_type_node); + add_field_decl (ptr_to_ptr_to_char, "extended_method_types", &chain); + + /* const char *demangledName; */ + add_field_decl (string_type_node, "demangled_name", &chain); + + /* const struct _prop_list_t *class_properties; */ + add_field_decl (objc_prop_list_ptr, "class_properties", &chain); + objc_finish_struct (objc_v2_protocol_template, decls); } @@ -889,33 +920,39 @@ create_extern_decl (tree type, const char *name) /* Create a globally visible definition for variable NAME of a given TYPE. The finish_var_decl() routine will need to be called on it afterwards. */ +static tree +create_global_decl (tree type, const char *name, bool is_def = false); static tree -create_global_decl (tree type, const char *name) +create_global_decl (tree type, const char *name, bool is_def) { tree id = get_identifier (name); tree var = hash_name_lookup (extern_names, id); if (var) - { - DECL_EXTERNAL (var) = 0; - TREE_STATIC (var) = 1; - } + is_def = true; else { var = start_var_decl (type, name); hash_name_enter (extern_names, var); } + if (is_def) + { + DECL_EXTERNAL (var) = 0; + TREE_STATIC (var) = 1; + } TREE_PUBLIC (var) = 1; return var; } /* Create a symbol with __attribute__ ((visibility ("hidden"))) attribute (private extern). */ +static tree +create_hidden_decl (tree type, const char *name, bool is_def = false); static tree -create_hidden_decl (tree type, const char *name) +create_hidden_decl (tree type, const char *name, bool is_def) { - tree decl = create_global_decl (type, name); + tree decl = create_global_decl (type, name, is_def); DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; DECL_VISIBILITY_SPECIFIED (decl) = 1; return decl; @@ -966,9 +1003,9 @@ next_runtime_abi_02_category_decl (tree klass) { tree decl; char buf[BUFSIZE]; - snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s", - IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)), - IDENTIFIER_POINTER (CLASS_NAME (klass))); + snprintf (buf, BUFSIZE, "_OBJC_Category_%s_%s", + IDENTIFIER_POINTER (CLASS_NAME (klass)), + IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass))); decl = start_var_decl (objc_v2_category_template, buf); OBJCMETA (decl, objc_meta, meta_category); return decl; @@ -983,7 +1020,13 @@ next_runtime_abi_02_protocol_decl (tree p) /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */ snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s", IDENTIFIER_POINTER (PROTOCOL_NAME (p))); - decl = start_var_decl (objc_v2_protocol_template, buf); + if (flag_next_runtime >= USE_FIXUP_BEFORE) + { + decl = create_hidden_decl (objc_v2_protocol_template, buf); + DECL_WEAK (decl) = true; + } + else + decl = start_var_decl (objc_v2_protocol_template, buf); OBJCMETA (decl, objc_meta, meta_protocol); return decl; } @@ -1120,10 +1163,12 @@ next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes, receiver_type = objc_object_type; vec_safe_push (*argtypes, receiver_type); - /* Selector type - will eventually change to `int'. */ - vec_safe_push (*argtypes, - superflag ? objc_v2_super_selector_type - : objc_v2_selector_type); + if (flag_next_runtime < USE_FIXUP_BEFORE) + /* Selector type - will eventually change to `int'. */ + vec_safe_push (*argtypes, superflag ? objc_v2_super_selector_type + : objc_v2_selector_type); + else + vec_safe_push (*argtypes, objc_selector_type); } /* TODO: Merge this with the message refs. */ @@ -1362,12 +1407,7 @@ objc_v2_build_ivar_ref (tree datum, tree component) return NULL_TREE; /* This routine only handles non-bitfield fields */ - /* DECL_INITIAL macro is set to width of bitfield and can be relied - on to check for bitfield ivars. Note that I cannot rely on - DECL_BIT_FIELD macro because it is only set when the whole struct - is seen (at finish_struct) and not when the ivar chain is - built. */ - if (DECL_INITIAL (field)) + if (DECL_C_BIT_FIELD (field)) return NULL_TREE; create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field); @@ -1438,13 +1478,12 @@ build_v2_superclass_ref_decl (tree ident, bool inst) static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs; static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs; +/* Find or build a superclass reference decl for class NAME. */ + static tree -next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, - struct imp_entry *imp, bool inst_meth) +objc_get_superclass_ref_decl (tree name, bool inst_meth) { tree decl; - ident_data_tuple e; - tree id = CLASS_NAME (imp->imp_context); vec<ident_data_tuple, va_gc> *list = inst_meth ? class_super_refs : metaclass_super_refs; @@ -1454,10 +1493,10 @@ next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, ident_data_tuple *ref; FOR_EACH_VEC_ELT (*list, count, ref) { - if (ref->ident == id) + if (ref->ident == name) { if (!ref->data) - ref->data = build_v2_superclass_ref_decl (id, inst_meth); + ref->data = build_v2_superclass_ref_decl (name, inst_meth); return ref->data; } } @@ -1478,48 +1517,49 @@ next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, } /* We come here if we don't find the entry - or if the table was yet to be created. */ - decl = build_v2_superclass_ref_decl (id, inst_meth); - e.ident = id; + decl = build_v2_superclass_ref_decl (name, inst_meth); + ident_data_tuple e; + e.ident = name; e.data = decl; vec_safe_push (list, e); return decl; } +/* Get a reference to the superclass for IMP. */ + +static tree +next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, + struct imp_entry *imp, bool inst_meth) +{ + tree name = CLASS_NAME (imp->imp_context); + return objc_get_superclass_ref_decl (name, inst_meth); +} + +/* Get a reference to the superclass for category IMP. */ + static tree next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED, - struct imp_entry *imp, bool inst_meth) + struct imp_entry *imp, + bool inst_meth) { - /* ??? is this OK when zero-link = true? */ - tree super_name = CLASS_SUPER_NAME (imp->imp_template); - tree super_class; - - if (!flag_zero_link) + if (flag_zero_link) { - super_class = objc_get_class_reference (CLASS_NAME (imp->imp_template)); - - if (!inst_meth) - - /* If we are in a class method, we must retrieve the - _metaclass_ for the current class, pointed at by the - class's "isa" pointer. The following assumes that "isa" is - the first ivar in a class (which it must be). */ - super_class = - build_indirect_ref (input_location, - build_c_cast (input_location, - build_pointer_type (objc_class_type), - super_class), - RO_UNARY_STAR); - return super_class; - } - /* ??? Do we need to add the class ref anway for zero-link? */ - /* else do it the slow way. */ - super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl); - super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1, - IDENTIFIER_POINTER (super_name)); - /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */ - return build_function_call (input_location, - super_class, - build_tree_list (NULL_TREE, super_name)); + /* Do it the slow way. */ + tree get_cl_fn = inst_meth ? objc_get_class_decl + : objc_get_meta_class_decl; + tree super_name = CLASS_SUPER_NAME (imp->imp_template); + super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1, + IDENTIFIER_POINTER (super_name)); + /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */ + return build_function_call (input_location, get_cl_fn, + build_tree_list (NULL_TREE, super_name)); + } + + /* This is the 'usual' path. */ + tree cls_name = CLASS_NAME (imp->imp_template); + if (!inst_meth) + return objc_get_superclass_ref_decl (cls_name, inst_meth); + return objc_get_class_reference (cls_name); } static tree @@ -1575,10 +1615,9 @@ objc_copy_to_temp_side_effect_params (tree fntype, tree values) (*_msg.messenger) (receiver, &_msg, ...) */ static tree -build_v2_build_objc_method_call (int super_flag, tree method_prototype, - tree lookup_object, tree selector, - tree method_params, - bool check_for_nil) +build_v2_objc_method_fixup_call (int super_flag, tree method_prototype, + tree lookup_object, tree selector, + tree method_params, bool check_for_nil) { tree ret_val; tree sender, rcv_p, t; @@ -1659,6 +1698,118 @@ build_v2_build_objc_method_call (int super_flag, tree method_prototype, } static tree +build_v2_build_objc_method_call (int super, tree method_prototype, + tree lookup_object, tree selector, + tree method_params, location_t loc, + bool check_for_nil, bool rx_is_id) +{ + tree sender, sender_cast, method, t; + tree rcv_p = (super ? objc_super_type : objc_object_type); + vec<tree, va_gc> *parms; + unsigned nparm = (method_params ? list_length (method_params) : 0); + + /* If a prototype for the method to be called exists, then cast + the sender's return type and arguments to match that of the method. + Otherwise, leave sender as is. */ + tree ret_type + = (method_prototype + ? TREE_VALUE (TREE_TYPE (method_prototype)) + : objc_object_type); + tree ftype = build_function_type_for_method (ret_type, method_prototype, + METHOD_REF, super); + + if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype)) + ftype = build_type_attribute_variant (ftype, + METHOD_TYPE_ATTRIBUTES + (method_prototype)); + + sender_cast = build_pointer_type (ftype); + + lookup_object = build_c_cast (loc, rcv_p, lookup_object); + + /* Use SAVE_EXPR to avoid evaluating the receiver twice. */ + lookup_object = save_expr (lookup_object); + + /* Param list + 2 slots for object and selector. */ + vec_alloc (parms, nparm + 2); + + /* If we are returning a struct in memory, and the address + of that memory location is passed as a hidden first + argument, then change which messenger entry point this + expr will call. NB: Note that sender_cast remains + unchanged (it already has a struct return type). */ + if (!targetm.calls.struct_value_rtx (0, 0) + && (TREE_CODE (ret_type) == RECORD_TYPE + || TREE_CODE (ret_type) == UNION_TYPE) + && targetm.calls.return_in_memory (ret_type, 0)) + { + if (super) + sender = umsg_id_super2_stret_fixup_decl; + else + sender = rx_is_id ? umsg_id_stret_fixup_decl + : umsg_stret_fixup_decl; + } + else + { + if (super) + sender = umsg_id_super2_fixup_decl; + else + sender = rx_is_id ? umsg_id_fixup_decl + : umsg_fixup_decl; + } + + method = build_fold_addr_expr_loc (loc, sender); + + /* Pass the object to the method. */ + parms->quick_push (lookup_object); + /* Pass the selector to the method. */ + parms->quick_push (selector); + /* Now append the remainder of the parms. */ + if (nparm) + for (; method_params; method_params = TREE_CHAIN (method_params)) + parms->quick_push (TREE_VALUE (method_params)); + + /* Build an obj_type_ref, with the correct cast for the method call. */ + t = build3 (OBJ_TYPE_REF, sender_cast, method, + lookup_object, size_zero_node); + tree ret_val = build_function_call_vec (loc, vNULL, t, parms, NULL); + vec_free (parms); + if (check_for_nil) + { + /* receiver != nil ? ret_val : 0 */ + tree ftree; + tree ifexp; + + if (TREE_CODE (ret_type) == RECORD_TYPE + || TREE_CODE (ret_type) == UNION_TYPE) + { + vec<constructor_elt, va_gc> *rtt = NULL; + /* ??? CHECKME. hmmm..... think we need something more + here. */ + CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE); + ftree = objc_build_constructor (ret_type, rtt); + } + else + ftree = fold_convert (ret_type, integer_zero_node); + + ifexp = build_binary_op (loc, NE_EXPR, + lookup_object, + fold_convert (rcv_p, integer_zero_node), 1); + +#ifdef OBJCPLUS + ret_val = build_conditional_expr (loc, ifexp, ret_val, ftree, + tf_warning_or_error); +#else + /* ??? CHECKME. */ + ret_val = build_conditional_expr (loc, ifexp, 1, + ret_val, NULL_TREE, loc, + ftree, NULL_TREE, loc); +#endif + } + return ret_val; +} + +static tree next_runtime_abi_02_build_objc_method_call (location_t loc, tree method_prototype, tree receiver, @@ -1667,27 +1818,38 @@ next_runtime_abi_02_build_objc_method_call (location_t loc, tree method_params, int super) { - tree ret_type, selector; - tree message_func_decl; - bool check_for_nil = flag_objc_nilcheck; - - ret_type = method_prototype - ? TREE_VALUE (TREE_TYPE (method_prototype)) - : objc_object_type; - /* Do we need to check for nil receivers ? */ /* For now, message sent to classes need no nil check. In the future, class declaration marked as weak_import must be nil checked. */ + bool check_for_nil = flag_objc_nilcheck; if (super || (TREE_CODE (receiver) == VAR_DECL && TREE_TYPE (receiver) == objc_class_type)) check_for_nil = false; + if (flag_next_runtime >= USE_FIXUP_BEFORE) + { + tree selector + = next_runtime_abi_02_build_selector_reference (loc, sel_name, + method_prototype); + return build_v2_build_objc_method_call (super, method_prototype, + receiver, selector, + method_params, loc, + check_for_nil, + objc_is_id (rtype)); + } + + /* else we have to build a pair of the function and selector. */ + tree message_func_decl; + tree ret_type = method_prototype + ? TREE_VALUE (TREE_TYPE (method_prototype)) + : objc_object_type; + if (!targetm.calls.struct_value_rtx (0, 0) - && (TREE_CODE (ret_type) == RECORD_TYPE - || TREE_CODE (ret_type) == UNION_TYPE) - && targetm.calls.return_in_memory (ret_type, 0)) + && (TREE_CODE (ret_type) == RECORD_TYPE + || TREE_CODE (ret_type) == UNION_TYPE) + && targetm.calls.return_in_memory (ret_type, 0)) { if (super) message_func_decl = umsg_id_super2_stret_fixup_decl; @@ -1706,7 +1868,7 @@ next_runtime_abi_02_build_objc_method_call (location_t loc, : umsg_fixup_decl; } - selector = build_v2_selector_messenger_reference (sel_name, + tree selector = build_v2_selector_messenger_reference (sel_name, message_func_decl); /* selector = &_msg; */ @@ -1717,9 +1879,9 @@ next_runtime_abi_02_build_objc_method_call (location_t loc, selector); /* (*_msg.messenger) (receiver, &_msg, ...); */ - return build_v2_build_objc_method_call (super, method_prototype, - receiver, selector, - method_params, check_for_nil); + return build_v2_objc_method_fixup_call (super, method_prototype, receiver, + selector, method_params, + check_for_nil); } /* NOTE --- Constant String Class Stuff --- */ @@ -2145,7 +2307,13 @@ build_v2_protocol_list_address_table (void) gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE); snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s", IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id))); - decl = create_global_decl (objc_protocol_type, buf); + if (flag_next_runtime >= USE_FIXUP_BEFORE) + { + decl = create_hidden_decl (objc_protocol_type, buf, /*is def=*/true); + DECL_WEAK (decl) = true; + } + else + decl = create_global_decl (objc_protocol_type, buf, /*is def=*/true); expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl)); OBJCMETA (decl, objc_meta, meta_label_protocollist); finish_var_decl (decl, expr); @@ -2295,9 +2463,10 @@ build_v2_method_list_template (tree list_type, int size) objc_method_prototype_template which is missing this field. */ static tree generate_v2_meth_descriptor_table (tree chain, tree protocol, - const char *prefix, tree attr) + const char *prefix, tree attr, + vec<tree>& all_meths) { - tree method_list_template, initlist, decl, methods; + tree method_list_template, initlist, decl; int size, entsize; vec<constructor_elt, va_gc> *v = NULL; char buf[BUFSIZE]; @@ -2305,13 +2474,14 @@ generate_v2_meth_descriptor_table (tree chain, tree protocol, if (!chain || !prefix) return NULL_TREE; - methods = chain; + tree method = chain; size = 0; - while (methods) + while (method) { - if (! METHOD_ENCODING (methods)) - METHOD_ENCODING (methods) = encode_method_prototype (methods); - methods = TREE_CHAIN (methods); + if (! METHOD_ENCODING (method)) + METHOD_ENCODING (method) = encode_method_prototype (method); + all_meths.safe_push (method); + method = TREE_CHAIN (method); size++; } @@ -2336,6 +2506,31 @@ generate_v2_meth_descriptor_table (tree chain, tree protocol, return decl; } +static tree +generate_v2_meth_type_list (vec<tree>& all_meths, tree protocol, + const char *prefix) +{ + if (all_meths.is_empty () || !prefix) + return NULL_TREE; + + unsigned size = all_meths.length (); + tree list_type = build_sized_array_type (string_type_node, size); + char *nam; + asprintf (&nam, "%s_%s", prefix, + IDENTIFIER_POINTER (PROTOCOL_NAME (protocol))); + tree decl = start_var_decl (list_type, nam); + free (nam); + OBJCMETA (decl, objc_meta, meta_base); + vec<constructor_elt, va_gc> *v = NULL; + + for (unsigned i = 0; i < size; ++i) + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, + add_objc_string (METHOD_ENCODING (all_meths[i]), + meth_var_types)); + finish_var_decl (decl, objc_build_constructor (list_type, v)); + return decl; +} + /* This routine builds the initializer list to initialize the 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */ @@ -2462,7 +2657,8 @@ static tree build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list, tree inst_methods, tree class_methods, tree opt_ins_meth, tree opt_cls_meth, - tree property_list) + tree property_list, tree ext_meth_types, + tree demangled_name, tree class_prop_list) { tree expr, ttyp; location_t loc; @@ -2517,7 +2713,28 @@ build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list /* const uint32_t flags; = 0 */ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node); - return objc_build_constructor (type, inits); + ttyp = build_pointer_type (string_type_node); + if (ext_meth_types) + expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, ext_meth_types, 0)); + else + expr = convert (ttyp, null_pointer_node); + CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); + + ttyp = string_type_node; + if (demangled_name) + expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, demangled_name, 0)); + else + expr = convert (ttyp, null_pointer_node); + CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); + + ttyp = objc_prop_list_ptr; + if (class_prop_list) + expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_prop_list, 0)); + else + expr = convert (ttyp, null_pointer_node); + CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); + + return objc_build_constructor (type, inits); } /* Main routine to build all meta data for all protocols used in a @@ -2553,25 +2770,26 @@ generate_v2_protocols (void) loc = DECL_SOURCE_LOCATION (decl); some = true; + vec<tree> all_meths = vNULL; inst_meth = generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p, "_OBJC_ProtocolInstanceMethods", - meta_proto_nst_meth); + meta_proto_nst_meth, all_meths); class_meth = generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p, "_OBJC_ProtocolClassMethods", - meta_proto_cls_meth); + meta_proto_cls_meth, all_meths); opt_inst_meth = generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p, - "_OBJC_OptProtocolInstMethods", - meta_proto_nst_meth); + "_OBJC_ProtocolOptInstMethods", + meta_proto_nst_meth, all_meths); opt_class_meth = generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p, - "_OBJC_OptProtocolClassMethods", - meta_proto_cls_meth); + "_OBJC_ProtocolOptClassMethods", + meta_proto_cls_meth, all_meths); if (PROTOCOL_LIST (p)) refs_decl = generate_v2_protocol_list (p, NULL_TREE); @@ -2589,13 +2807,21 @@ generate_v2_protocols (void) props = generate_v2_property_table (p, NULL_TREE); + tree ext_meth_types + = generate_v2_meth_type_list (all_meths, p, + "_OBJC_ProtocolMethodTypes"); + tree demangled_name = NULL_TREE; + tree class_prop_list = NULL_TREE; + initlist = build_v2_protocol_initializer (TREE_TYPE (decl), protocol_name_expr, refs_expr, inst_meth, class_meth, opt_inst_meth, opt_class_meth, - props); + props, ext_meth_types, + demangled_name,class_prop_list); finish_var_decl (decl, initlist); objc_add_to_protocol_list (p, decl); + all_meths.truncate (0); } if (some) diff --git a/gcc/objc/objc-runtime-shared-support.c b/gcc/objc/objc-runtime-shared-support.c index 4aecc7f..16d4d63 100644 --- a/gcc/objc/objc-runtime-shared-support.c +++ b/gcc/objc/objc-runtime-shared-support.c @@ -117,14 +117,17 @@ add_field_decl (tree type, const char *name, tree **chain) tree start_var_decl (tree type, const char *name) { - tree var = build_decl (input_location, - VAR_DECL, get_identifier (name), type); - TREE_STATIC (var) = 1; + tree name_id = get_identifier (name); + tree var = build_decl (input_location, VAR_DECL, name_id, type); DECL_INITIAL (var) = error_mark_node; /* A real initializer is coming... */ + TREE_STATIC (var) = 1; DECL_IGNORED_P (var) = 1; DECL_ARTIFICIAL (var) = 1; DECL_CONTEXT (var) = NULL_TREE; #ifdef OBJCPLUS + /* Meta-data for the NeXT runtime is expected to be 'extern "C"'. */ + if (flag_next_runtime) + SET_DECL_ASSEMBLER_NAME (var, name_id); DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */ #endif return var; |