aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Sandoe <iains@gcc.gnu.org>2011-02-18 00:07:38 +0000
committerNicola Pero <nicola@gcc.gnu.org>2011-02-18 00:07:38 +0000
commitd764a8e6bdae09aecb7a8378def9d900f84ce53e (patch)
treec0b6f091c931f0a65e3fb59fbd9fff3f5ba9bde9
parent0a8134cacea8b18b0e241cc492546cbb69ae598a (diff)
downloadgcc-d764a8e6bdae09aecb7a8378def9d900f84ce53e.zip
gcc-d764a8e6bdae09aecb7a8378def9d900f84ce53e.tar.gz
gcc-d764a8e6bdae09aecb7a8378def9d900f84ce53e.tar.bz2
Added support for the 64-bit Apple Objective-C runtime
From-SVN: r170260
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/config/darwin-c.c3
-rw-r--r--gcc/config/darwin-sections.def41
-rw-r--r--gcc/config/darwin.c325
-rw-r--r--gcc/config/darwin.h12
-rw-r--r--gcc/objc/ChangeLog103
-rw-r--r--gcc/objc/Make-lang.in48
-rw-r--r--gcc/objc/config-lang.in6
-rw-r--r--gcc/objc/objc-act.c5621
-rw-r--r--gcc/objc/objc-act.h198
-rw-r--r--gcc/objc/objc-gnu-runtime-abi-01.c2265
-rw-r--r--gcc/objc/objc-lang.c10
-rw-r--r--gcc/objc/objc-next-metadata-tags.h172
-rw-r--r--gcc/objc/objc-next-runtime-abi-01.c2969
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c3750
-rw-r--r--gcc/objc/objc-runtime-hooks.h108
-rw-r--r--gcc/objc/objc-runtime-shared-support.c733
-rw-r--r--gcc/objc/objc-runtime-shared-support.h90
-rw-r--r--gcc/objcp/ChangeLog16
-rw-r--r--gcc/objcp/Make-lang.in52
-rw-r--r--gcc/objcp/config-lang.in4
-rw-r--r--gcc/objcp/objcp-lang.c18
-rw-r--r--gcc/testsuite/ChangeLog52
-rw-r--r--gcc/testsuite/obj-c++.dg/basic.mm29
-rw-r--r--gcc/testsuite/obj-c++.dg/method-11.mm7
-rw-r--r--gcc/testsuite/obj-c++.dg/proto-lossage-3.mm7
-rw-r--r--gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm5
-rw-r--r--gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm7
-rw-r--r--gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm7
-rw-r--r--gcc/testsuite/obj-c++.dg/try-catch-2.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/try-catch-9.mm2
-rw-r--r--gcc/testsuite/objc.dg/encode-7-next-64bit.m58
-rw-r--r--gcc/testsuite/objc.dg/image-info.m13
-rw-r--r--gcc/testsuite/objc.dg/lookup-1.m3
-rw-r--r--gcc/testsuite/objc.dg/method-4.m4
-rw-r--r--gcc/testsuite/objc.dg/next-runtime-1.m15
-rw-r--r--gcc/testsuite/objc.dg/pr23214.m15
-rw-r--r--gcc/testsuite/objc.dg/special/unclaimed-category-1.h4
-rw-r--r--gcc/testsuite/objc.dg/special/unclaimed-category-1.m4
-rw-r--r--gcc/testsuite/objc.dg/symtab-1.m9
-rw-r--r--gcc/testsuite/objc.dg/torture/forward-1.m12
-rw-r--r--gcc/testsuite/objc.dg/torture/strings/const-str-10.m5
-rw-r--r--gcc/testsuite/objc.dg/torture/strings/const-str-11.m5
-rw-r--r--gcc/testsuite/objc.dg/torture/strings/const-str-9.m5
-rw-r--r--gcc/testsuite/objc.dg/zero-link-1.m3
-rw-r--r--gcc/testsuite/objc.dg/zero-link-2.m6
-rw-r--r--gcc/testsuite/objc/execute/accessing_ivars.m5
-rw-r--r--gcc/testsuite/objc/execute/bf-common.h7
-rw-r--r--gcc/testsuite/objc/execute/bycopy-2.m3
-rw-r--r--gcc/testsuite/objc/execute/bycopy-3.m12
-rw-r--r--gcc/testsuite/objc/execute/class-tests-1.h1
-rw-r--r--gcc/testsuite/objc/execute/class-tests-2.h1
-rw-r--r--gcc/testsuite/objc/execute/compatibility_alias.m1
-rw-r--r--gcc/testsuite/objc/execute/enumeration-1.m1
-rw-r--r--gcc/testsuite/objc/execute/enumeration-2.m1
-rw-r--r--gcc/testsuite/objc/execute/exceptions/catchall-1.m1
-rw-r--r--gcc/testsuite/objc/execute/exceptions/exceptions.exp1
-rw-r--r--gcc/testsuite/objc/execute/exceptions/finally-1.m17
-rw-r--r--gcc/testsuite/objc/execute/exceptions/foward-1.m27
-rw-r--r--gcc/testsuite/objc/execute/exceptions/local-variables-1.m1
-rw-r--r--gcc/testsuite/objc/execute/formal_protocol-1.m2
-rw-r--r--gcc/testsuite/objc/execute/formal_protocol-2.m2
-rw-r--r--gcc/testsuite/objc/execute/formal_protocol-3.m2
-rw-r--r--gcc/testsuite/objc/execute/formal_protocol-4.m2
-rw-r--r--gcc/testsuite/objc/execute/formal_protocol-5.m4
-rw-r--r--gcc/testsuite/objc/execute/formal_protocol-6.m3
-rw-r--r--gcc/testsuite/objc/execute/formal_protocol-7.m2
-rw-r--r--gcc/testsuite/objc/execute/no_clash.m1
-rw-r--r--gcc/testsuite/objc/execute/object_is_class.m11
-rw-r--r--gcc/testsuite/objc/execute/object_is_meta_class.m11
70 files changed, 12197 insertions, 4765 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8382f50..7fecfea 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+2011-02-17 Iain Sandoe <iains@gcc.gnu.org>
+
+ * config/darwin-c.c (darwin_cpp_builtins): Define __OBJC2__ for
+ objc_abi == 2.
+ * config/darwin.c (output_objc_section_asm_op): Added support for
+ ABI v1 and v2.
+ (is_objc_metadata): New.
+ (darwin_objc2_section): New.
+ (darwin_objc1_section): New.
+ (machopic_select_section): Added support for ABI v1 and v2.
+ (darwin_emit_objc_zeroed): New.
+ (darwin_output_aligned_bss): Detect objc metadata and treat it
+ appropriately.
+ (darwin_asm_output_aligned_decl_common): Same.
+ (darwin_asm_output_aligned_decl_local): Same.
+ * config/darwin-sections.def: Updated for ABI v1 and v2.
+ * config/darwin.h (SUBTARGET_C_COMMON_OVERRIDE_OPTIONS): When
+ compiling Objective-C code for the NeXT runtime, default to using
+ ABI version 0 for 32-bit, and version 2 for 64-bit.
+
2011-02-17 Joseph Myers <joseph@codesourcery.com>
* common.opt (optimize_fast): New Variable.
diff --git a/gcc/config/darwin-c.c b/gcc/config/darwin-c.c
index c246f70..0c713ba 100644
--- a/gcc/config/darwin-c.c
+++ b/gcc/config/darwin-c.c
@@ -629,6 +629,9 @@ darwin_cpp_builtins (cpp_reader *pfile)
builtin_define ("__strong=");
builtin_define ("__weak=");
}
+
+ if (flag_objc_abi == 2)
+ builtin_define ("__OBJC2__");
}
/* Handle C family front-end options. */
diff --git a/gcc/config/darwin-sections.def b/gcc/config/darwin-sections.def
index 62d1d8d..61b6f69 100644
--- a/gcc/config/darwin-sections.def
+++ b/gcc/config/darwin-sections.def
@@ -94,7 +94,7 @@ DEF_SECTION (mod_term_section, 0, ".mod_term_func", 0)
DEF_SECTION (constructor_section, 0, ".constructor", 0)
DEF_SECTION (destructor_section, 0, ".destructor", 0)
-/* Objective-C (V1) sections. */
+/* Objective-C ABI=0 (Original version) sections. */
DEF_SECTION (objc_class_section, 0, ".objc_class", 1)
DEF_SECTION (objc_meta_class_section, 0, ".objc_meta_class", 1)
DEF_SECTION (objc_category_section, 0, ".objc_category", 1)
@@ -112,7 +112,7 @@ DEF_SECTION (objc_module_info_section, 0, ".objc_module_info", 1)
DEF_SECTION (objc_protocol_section, 0, ".objc_protocol", 1)
DEF_SECTION (objc_string_object_section, 0, ".objc_string_object", 1)
DEF_SECTION (objc_constant_string_object_section, 0,
- ".section __OBJC, __cstring_object, regular, no_dead_strip", 1)
+ ".section __OBJC, __cstring_object, regular, no_dead_strip", 0)
/* Fix-and-Continue image marker. */
DEF_SECTION (objc_image_info_section, 0,
@@ -156,3 +156,40 @@ DEF_SECTION (darwin_exception_section, SECTION_NO_ANCHOR,
DEF_SECTION (darwin_eh_frame_section, SECTION_NO_ANCHOR,
".section " EH_FRAME_SECTION_NAME ",__eh_frame"
EH_FRAME_SECTION_ATTR, 0)
+
+/* Sections for ObjC ABI=1 (ObjC 'V1' extensions) */
+DEF_SECTION (objc1_class_ext_section, 0,
+ ".section __OBJC, __class_ext, regular, no_dead_strip", 1)
+DEF_SECTION (objc1_prop_list_section, 0,
+ ".section __OBJC, __property, regular, no_dead_strip", 1)
+DEF_SECTION (objc1_protocol_ext_section, 0,
+ ".section __OBJC, __protocol_ext, regular, no_dead_strip", 1)
+
+/* Sections for ObjC ABI=2 (m64). */
+DEF_SECTION (objc2_message_refs_section, 0,
+ ".section __DATA, __objc_msgrefs, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_classdefs_section, 0, ".section __DATA, __objc_data", 1)
+DEF_SECTION (objc2_metadata_section, 0, ".section __DATA, __objc_const", 1)
+
+DEF_SECTION (objc2_classrefs_section, 0,
+ ".section __DATA, __objc_classrefs, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_classlist_section, 0,
+ ".section __DATA, __objc_classlist, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_categorylist_section, 0,
+ ".section __DATA, __objc_catlist, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_selector_refs_section, 0,
+ ".section __DATA, __objc_selrefs, literal_pointers, no_dead_strip", 1)
+DEF_SECTION (objc2_nonlazy_class_section, 0,
+ ".section __DATA, __objc_nlclslist, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_nonlazy_category_section, 0,
+ ".section __DATA, __objc_nlcatlist, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_protocollist_section, 0,
+ ".section __DATA, __objc_protolist, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_protocolrefs_section, 0,
+ ".section __DATA, __objc_protorefs, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_super_classrefs_section, 0,
+ ".section __DATA, __objc_superrefs, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_image_info_section, 0,
+ ".section __DATA, __objc_imageinfo, regular, no_dead_strip", 1)
+DEF_SECTION (objc2_constant_string_object_section, 0,
+ ".section __DATA, __objc_stringobj, regular, no_dead_strip", 1)
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index c31aeed..2969f10 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -148,13 +148,48 @@ output_objc_section_asm_op (const void *directive)
objc_class_vars_section,
objc_instance_vars_section,
objc_module_info_section,
- objc_symbols_section
+ objc_symbols_section,
};
+ /* ABI=1 */
+ static const enum darwin_section_enum tomarkv1[] =
+ {
+ objc1_protocol_ext_section,
+ objc1_class_ext_section,
+ objc1_prop_list_section
+ } ;
+ /* ABI=2 */
+ static const enum darwin_section_enum tomarkv2[] =
+ {
+ objc2_message_refs_section,
+ objc2_classdefs_section,
+ objc2_metadata_section,
+ objc2_classrefs_section,
+ objc2_classlist_section,
+ objc2_categorylist_section,
+ objc2_selector_refs_section,
+ objc2_nonlazy_class_section,
+ objc2_nonlazy_category_section,
+ objc2_protocollist_section,
+ objc2_protocolrefs_section,
+ objc2_super_classrefs_section,
+ objc2_image_info_section,
+ objc2_constant_string_object_section
+ } ;
size_t i;
been_here = true;
- for (i = 0; i < ARRAY_SIZE (tomark); i++)
- switch_to_section (darwin_sections[tomark[i]]);
+ if (flag_objc_abi < 2)
+ {
+ for (i = 0; i < ARRAY_SIZE (tomark); i++)
+ switch_to_section (darwin_sections[tomark[i]]);
+ if (flag_objc_abi == 1)
+ for (i = 0; i < ARRAY_SIZE (tomarkv1); i++)
+ switch_to_section (darwin_sections[tomarkv1[i]]);
+ }
+ else
+ for (i = 0; i < ARRAY_SIZE (tomarkv2); i++)
+ switch_to_section (darwin_sections[tomarkv2[i]]);
+ /* Make sure we don't get varasm.c out of sync with us. */
switch_to_section (saved_in_section);
}
output_section_asm_op (directive);
@@ -277,7 +312,6 @@ indirect_data (rtx sym_ref)
return ! lprefix;
}
-
static int
machopic_data_defined_p (rtx sym_ref)
{
@@ -1233,6 +1267,177 @@ machopic_reloc_rw_mask (void)
return MACHOPIC_INDIRECT ? 3 : 0;
}
+/* We have to deal with ObjC/C++ metadata section placement in the common
+ code, since it will also be called from LTO.
+
+ Return metadata attributes, if present (searching for ABI=2 first)
+ Return NULL_TREE if no such attributes are found. */
+
+static tree
+is_objc_metadata (tree decl)
+{
+ if (DECL_P (decl)
+ && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
+ && DECL_ATTRIBUTES (decl))
+ {
+ tree meta = lookup_attribute ("OBJC2META", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return meta;
+ meta = lookup_attribute ("OBJC1META", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return meta;
+ }
+ return NULL_TREE;
+}
+
+/* Return the section required for Objective C ABI 2 metadata. */
+static section *
+darwin_objc2_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base)
+{
+ const char *p;
+ tree ident = TREE_VALUE (meta);
+ gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE);
+ p = IDENTIFIER_POINTER (ident);
+
+ /* If we are in LTO, then we don't know the state of flag_next_runtime
+ or flag_objc_abi when the code was generated. We set these from the
+ meta-data - which is needed to deal with const string constructors. */
+
+ flag_next_runtime = 1;
+ flag_objc_abi = 2;
+
+ if (base == data_section)
+ base = darwin_sections[objc2_metadata_section];
+
+ /* Most of the OBJC2 META-data end up in the base section, so check it
+ first. */
+ if (!strncmp (p, "V2_BASE", 7))
+ return base;
+ else if (!strncmp (p, "V2_STRG", 7))
+ return darwin_sections[cstring_section];
+
+ else if (!strncmp (p, "G2_META", 7) || !strncmp (p, "G2_CLAS", 7))
+ return darwin_sections[objc2_classdefs_section];
+ else if (!strncmp (p, "V2_MREF", 7))
+ return darwin_sections[objc2_message_refs_section];
+ else if (!strncmp (p, "V2_CLRF", 7))
+ return darwin_sections[objc2_classrefs_section];
+ else if (!strncmp (p, "V2_SURF", 7))
+ return darwin_sections[objc2_super_classrefs_section];
+ else if (!strncmp (p, "V2_NLCL", 7))
+ return darwin_sections[objc2_nonlazy_class_section];
+ else if (!strncmp (p, "V2_CLAB", 7))
+ return darwin_sections[objc2_classlist_section];
+ else if (!strncmp (p, "V2_SRFS", 7))
+ return darwin_sections[objc2_selector_refs_section];
+ else if (!strncmp (p, "V2_NLCA", 7))
+ return darwin_sections[objc2_nonlazy_category_section];
+ else if (!strncmp (p, "V2_CALA", 7))
+ return darwin_sections[objc2_categorylist_section];
+
+ else if (!strncmp (p, "V2_PLST", 7))
+ return darwin_sections[objc2_protocollist_section];
+ else if (!strncmp (p, "V2_PRFS", 7))
+ return darwin_sections[objc2_protocolrefs_section];
+
+ else if (!strncmp (p, "V2_INFO", 7))
+ return darwin_sections[objc2_image_info_section];
+
+ else if (!strncmp (p, "V2_EHTY", 7))
+ return darwin_sections[data_coal_section];
+
+ else if (!strncmp (p, "V2_CSTR", 7))
+ return darwin_sections[objc2_constant_string_object_section];
+
+ /* Not recognized, default. */
+ return base;
+}
+
+/* Return the section required for Objective C ABI 0/1 metadata. */
+static section *
+darwin_objc1_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base)
+{
+ const char *p;
+ tree ident = TREE_VALUE (meta);
+ gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE);
+ p = IDENTIFIER_POINTER (ident);
+
+ /* If we are in LTO, then we don't know the state of flag_next_runtime
+ or flag_objc_abi when the code was generated. We set these from the
+ meta-data - which is needed to deal with const string constructors. */
+ flag_next_runtime = 1;
+ if (!global_options_set.x_flag_objc_abi)
+ flag_objc_abi = 1;
+
+ /* String sections first, cos there are lots of strings. */
+ if (!strncmp (p, "V1_STRG", 7))
+ return darwin_sections[cstring_section];
+ else if (!strncmp (p, "V1_CLSN", 7))
+ return darwin_sections[objc_class_names_section];
+ else if (!strncmp (p, "V1_METN", 7))
+ return darwin_sections[objc_meth_var_names_section];
+ else if (!strncmp (p, "V1_METT", 7))
+ return darwin_sections[objc_meth_var_types_section];
+
+ else if (!strncmp (p, "V1_CLAS", 7))
+ return darwin_sections[objc_class_section];
+ else if (!strncmp (p, "V1_META", 7))
+ return darwin_sections[objc_meta_class_section];
+ else if (!strncmp (p, "V1_CATG", 7))
+ return darwin_sections[objc_category_section];
+ else if (!strncmp (p, "V1_PROT", 7))
+ return darwin_sections[objc_protocol_section];
+
+ else if (!strncmp (p, "V1_CLCV", 7))
+ return darwin_sections[objc_class_vars_section];
+ else if (!strncmp (p, "V1_CLIV", 7))
+ return darwin_sections[objc_instance_vars_section];
+
+ else if (!strncmp (p, "V1_CLCM", 7))
+ return darwin_sections[objc_cls_meth_section];
+ else if (!strncmp (p, "V1_CLIM", 7))
+ return darwin_sections[objc_inst_meth_section];
+ else if (!strncmp (p, "V1_CACM", 7))
+ return darwin_sections[objc_cat_cls_meth_section];
+ else if (!strncmp (p, "V1_CAIM", 7))
+ return darwin_sections[objc_cat_inst_meth_section];
+ else if (!strncmp (p, "V1_PNSM", 7))
+ return darwin_sections[objc_cat_inst_meth_section];
+ else if (!strncmp (p, "V1_PCLM", 7))
+ return darwin_sections[objc_cat_cls_meth_section];
+
+ else if (!strncmp (p, "V1_CLPR", 7))
+ return darwin_sections[objc_cat_cls_meth_section];
+ else if (!strncmp (p, "V1_CAPR", 7))
+ return darwin_sections[objc_category_section]; /* ??? CHECK me. */
+
+ else if (!strncmp (p, "V1_PRFS", 7))
+ return darwin_sections[objc_cat_cls_meth_section];
+ else if (!strncmp (p, "V1_CLRF", 7))
+ return darwin_sections[objc_cls_refs_section];
+ else if (!strncmp (p, "V1_SRFS", 7))
+ return darwin_sections[objc_selector_refs_section];
+
+ else if (!strncmp (p, "V1_MODU", 7))
+ return darwin_sections[objc_module_info_section];
+ else if (!strncmp (p, "V1_SYMT", 7))
+ return darwin_sections[objc_symbols_section];
+ else if (!strncmp (p, "V1_INFO", 7))
+ return darwin_sections[objc_image_info_section];
+
+ else if (!strncmp (p, "V1_PLST", 7))
+ return darwin_sections[objc1_prop_list_section];
+ else if (!strncmp (p, "V1_PEXT", 7))
+ return darwin_sections[objc1_protocol_ext_section];
+ else if (!strncmp (p, "V1_CEXT", 7))
+ return darwin_sections[objc1_class_ext_section];
+
+ else if (!strncmp (p, "V2_CSTR", 7))
+ return darwin_sections[objc_constant_string_object_section];
+
+ return base;
+}
+
section *
machopic_select_section (tree decl,
int reloc,
@@ -1331,7 +1536,25 @@ machopic_select_section (tree decl,
gcc_unreachable ();
}
- /* Darwin weird special cases. */
+ /* Darwin weird special cases.
+ a) OBJC Meta-data. */
+ if (DECL_P (decl)
+ && (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == CONST_DECL)
+ && DECL_ATTRIBUTES (decl))
+ {
+ tree meta = lookup_attribute ("OBJC2META", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return darwin_objc2_section (decl, meta, base_section);
+ meta = lookup_attribute ("OBJC1META", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return darwin_objc1_section (decl, meta, base_section);
+ meta = lookup_attribute ("OBJC1METG", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return base_section; /* GNU runtime is happy with it all in one pot. */
+ }
+
+ /* b) Constant string objects. */
if (TREE_CODE (decl) == CONSTRUCTOR
&& TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
@@ -1341,29 +1564,53 @@ machopic_select_section (tree decl,
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
+ /* FIXME: This is unsatisfactory for LTO, since it relies on other
+ metadata determining the source FE. */
if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString"))
- {
- if (flag_next_runtime)
- return darwin_sections[objc_constant_string_object_section];
- else
- return darwin_sections[objc_string_object_section];
- }
+ {
+ if (flag_next_runtime)
+ {
+ if (flag_objc_abi == 2)
+ return darwin_sections[objc2_constant_string_object_section];
+ else
+ return darwin_sections[objc_constant_string_object_section];
+ }
+ else
+ return darwin_sections[objc_string_object_section];
+ }
else if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_CFString"))
return darwin_sections[cfstring_constant_object_section];
else
- return base_section;
+ return base_section;
}
+ /* c) legacy meta-data selection. */
else if (TREE_CODE (decl) == VAR_DECL
&& DECL_NAME (decl)
&& TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
&& IDENTIFIER_POINTER (DECL_NAME (decl))
+ && flag_next_runtime
&& !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "_OBJC_", 6))
{
const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
-
+ static bool warned_objc_46 = false;
/* We shall assert that zero-sized objects are an error in ObjC
meta-data. */
gcc_assert (tree_low_cst (DECL_SIZE_UNIT (decl), 1) != 0);
+
+ /* ??? This mechanism for determining the metadata section is
+ broken when LTO is in use, since the frontend that generated
+ the data is not identified. We will keep the capability for
+ the short term - in case any non-Objective-C programs are using
+ it to place data in specified sections. */
+ if (!warned_objc_46)
+ {
+ location_t loc = DECL_SOURCE_LOCATION (decl);
+ warning_at (loc, 0, "the use of _OBJC_-prefixed variable names"
+ " to select meta-data sections is deprecated at 4.6"
+ " and will be removed in 4.7");
+ warned_objc_46 = true;
+ }
+
if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
return darwin_sections[objc_cls_meth_section];
else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
@@ -1911,6 +2158,30 @@ darwin_emit_weak_or_comdat (FILE *fp, tree decl, const char *name,
assemble_zeros (size);
}
+/* Emit a chunk of data for ObjC meta-data that got placed in BSS erroneously. */
+static void
+darwin_emit_objc_zeroed (FILE *fp, tree decl, const char *name,
+ unsigned HOST_WIDE_INT size,
+ unsigned int align, tree meta)
+{
+ section *ocs = data_section;
+
+ if (TREE_PURPOSE (meta) == get_identifier("OBJC2META"))
+ ocs = darwin_objc2_section (decl, meta, ocs);
+ else
+ ocs = darwin_objc1_section (decl, meta, ocs);
+
+ switch_to_section (ocs);
+
+ /* We shall declare that zero-sized meta-data are not valid (yet). */
+ gcc_assert (size);
+ fprintf (fp, "\t.align\t%d\n", floor_log2 (align / BITS_PER_UNIT));
+
+ /* ... and we let it deal with outputting one byte of zero for them too. */
+ darwin_asm_declare_object_name (fp, name, decl);
+ assemble_zeros (size);
+}
+
/* This routine emits 'local' storage:
When Section Anchors are off this routine emits .zerofill commands in
@@ -2042,6 +2313,7 @@ darwin_output_aligned_bss (FILE *fp, tree decl, const char *name,
{
unsigned int l2align;
bool one, pub, weak;
+ tree meta;
pub = TREE_PUBLIC (decl);
one = DECL_ONE_ONLY (decl);
@@ -2058,6 +2330,14 @@ fprintf (fp, "# albss: %s (%lld,%d) ro %d cst %d stat %d com %d"
pub, weak, one, (unsigned long)DECL_INITIAL (decl));
#endif
+ /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
+ before the target has a chance to comment. */
+ if ((meta = is_objc_metadata (decl)))
+ {
+ darwin_emit_objc_zeroed (fp, decl, name, size, DECL_ALIGN (decl), meta);
+ return;
+ }
+
/* Check that any initializer is valid. */
gcc_assert ((DECL_INITIAL (decl) == NULL)
|| (DECL_INITIAL (decl) == error_mark_node)
@@ -2152,6 +2432,8 @@ darwin_asm_output_aligned_decl_common (FILE *fp, tree decl, const char *name,
{
unsigned int l2align;
bool one, weak;
+ tree meta;
+
/* No corresponding var. */
if (decl==NULL)
{
@@ -2176,6 +2458,14 @@ fprintf (fp, "# adcom: %s (%lld,%d) ro %d cst %d stat %d com %d pub %d"
TREE_PUBLIC (decl), weak, one, (unsigned long)DECL_INITIAL (decl));
#endif
+ /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
+ before the target has a chance to comment. */
+ if ((meta = is_objc_metadata (decl)))
+ {
+ darwin_emit_objc_zeroed (fp, decl, name, size, DECL_ALIGN (decl), meta);
+ return;
+ }
+
/* We shouldn't be messing with this if the decl has a section name. */
gcc_assert (DECL_SECTION_NAME (decl) == NULL);
@@ -2222,6 +2512,7 @@ darwin_asm_output_aligned_decl_local (FILE *fp, tree decl, const char *name,
{
unsigned long l2align;
bool one, weak;
+ tree meta;
one = DECL_ONE_ONLY (decl);
weak = (DECL_P (decl)
@@ -2237,6 +2528,14 @@ fprintf (fp, "# adloc: %s (%lld,%d) ro %d cst %d stat %d one %d pub %d"
weak , (unsigned long)DECL_INITIAL (decl));
#endif
+ /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
+ before the target has a chance to comment. */
+ if ((meta = is_objc_metadata (decl)))
+ {
+ darwin_emit_objc_zeroed (fp, decl, name, size, DECL_ALIGN (decl), meta);
+ return;
+ }
+
/* We shouldn't be messing with this if the decl has a section name. */
gcc_assert (DECL_SECTION_NAME (decl) == NULL);
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 778ff1e..0526d85 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -140,6 +140,16 @@ extern GTY(()) int darwin_ms_struct;
} while (0)
#define SUBTARGET_C_COMMON_OVERRIDE_OPTIONS do { \
+ /* Unless set, force ABI=2 for NeXT and m64, 0 otherwise. */ \
+ if (!global_options_set.x_flag_objc_abi) \
+ global_options.x_flag_objc_abi \
+ = (flag_next_runtime && TARGET_64BIT) ? 2 : 0; \
+ /* Objective-C family ABI 2 is only valid for next/m64 at present. */ \
+ if (global_options_set.x_flag_objc_abi && flag_next_runtime) \
+ if (TARGET_64BIT && global_options.x_flag_objc_abi < 2) \
+ error_at (UNKNOWN_LOCATION, "%<-fobjc-abi-version%> >= 2 is only" \
+ " supported on %<-m64%> targets for" \
+ " %<-fnext-runtime%>"); \
/* Sort out ObjC exceptions: If the runtime is NeXT we default to \
sjlj for m32 only. */ \
if (!global_options_set.x_flag_objc_sjlj_exceptions) \
@@ -599,7 +609,7 @@ int darwin_label_is_anonymous_local_objc_name (const char *name);
} \
else if (xname[0] == '+' || xname[0] == '-') \
fprintf (FILE, "\"%s\"", xname); \
- else if (darwin_label_is_anonymous_local_objc_name (xname)) \
+ else if (darwin_label_is_anonymous_local_objc_name (xname)) \
fprintf (FILE, "L%s", xname); \
else if (!strncmp (xname, ".objc_class_name_", 17)) \
fprintf (FILE, "%s", xname); \
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 7b42439..926352e 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,106 @@
+2011-02-17 Iain Sandoe <iains@gcc.gnu.org>
+
+ * config-lang.in (gtfiles): Updated.
+ * Make-lang.in (START_HDRS): New.
+ (OBJC_OBJS): Added new object files.
+ (objc/objc-act.o): Updated prerequisites.
+ (objc/objc-lang.o): Updated prerequisites.
+ (objc/objc-runtime-shared-support.o): New.
+ (objc/objc-gnu-runtime-abi-01.o): New.
+ (objc/objc-next-runtime-abi-01.o): New.
+ (objc/objc-next-runtime-abi-02.o): New.
+ * objc-runtime-hooks.h: New.
+ * objc-runtime-shared-support.h: New.
+ * objc-runtime-shared-support.c: New.
+ * objc-gnu-runtime-abi-01.c: New.
+ * objc-next-metadata-tags.h: New.
+ * objc-next-runtime-abi-01.c: New.
+ * objc-next-runtime-abi-02.c: New.
+ * objc-lang.c: Include c-lang.h.
+ (LANG_HOOKS_EH_PERSONALITY): Removed.
+ * objc-act.h: Moved many declarations and code from objc-act.c
+ into objc-act.h to make them available outside objc-act.c.
+ (objc_eh_runtime_type): Removed.
+ (objc_eh_personality): Removed.
+ (CLASS_HAS_EXCEPTION_ATTR): New.
+ (OCTI_SUPER_SUPERFIELD_ID): New.
+ (OCTI_V1_PROP_LIST_TEMPL): New.
+ (OCTI_V1_PROP_NAME_ATTR_CHAIN): New.
+ (super_superclassfield_id): New.
+ (objc_prop_list_ptr): New.
+ (prop_names_attr_chain): New.
+ * objc-act.c: Include new runtime headers. Moved many #defines
+ and declarations into objc-act.h and
+ objc-runtime-shared-support.h. Made some corresponding functions
+ non-static, and moved some others into
+ objc-runtime-shared-support.c. Moved metadata generation code
+ into the new runtime hook files.
+ (ivar_offset_hash_list): New.
+ (objc_init): Call generate_struct_value_by_array() before doing
+ any runtime initialization. Create the appropriate runtime hook
+ structures.
+ (init_objc): Removed. Code moved directly into objc_init.
+ (finish_objc): Removed. Code moved directly into
+ objc_write_global_declarations.
+ (objc_write_global_declarations): Do the warn_selector checks
+ before emitting metadata. Use a runtime hook to emit the
+ metadata. Do not emit the metadata or do -gen-decls processing if
+ -fsyntax-only or we are producing a PCH.
+ (build_objc_exception_stuff): Renamed to
+ build_common_objc_exception_stuff. Remove TREE_NOTHROW flag from
+ objc_exception_throw_decl.
+ (synth_module_prologue): Call runtime initialize hook instead of
+ building runtime declarations here. Use the
+ default_constant_string_class_name runtime hook to set the
+ constant string class name.
+ (objc_build_string_object): Call the setup_const_string_class_decl
+ runtime hook instead of setup_string_decl. Call the
+ build_const_string_constructor runtime hook instead of building
+ the string object here.
+ (get_objc_string_decl): Added prop_names_attr case. Removed
+ gcc_unreachable() at the end.
+ (objc_begin_catch_clause): Distinguish between @catch (...) and
+ @catch (id x). Call the begin_catch runtime hook instead of
+ building the CATCH_EXPR here.
+ (objc_finish_catch_clause): Call the finish_catch runtime hook
+ instead of adding the catch here.
+ (objc_finish_try_stmt): Call the finish_try_stmt runtime hook
+ instead of doing it here.
+ (objc_build_throw_stmt): Bail out early for error_mark_node. Call
+ the build_exc_ptr runtime hook instead of objc_build_exc_ptr.
+ Call the build_throw_stmt runtime hook instead of building the
+ throw call here.
+ (objc_generate_cxx_cdtors): Set has_cxx_cdtors for the GNU runtime
+ as well.
+ (get_arg_type_list): Call the get_arg_type_list_base runtime hook
+ instead of building the list of arguments here.
+ (receiver_is_class_object): Call the receiver_is_class_object
+ runtime hook instead of doing the check here. Call the
+ tag_getclass runtime hook instead of using TAG_GETCLASS.
+ (objc_finish_message_expr): Call the build_objc_method_call
+ runtime hook.
+ (objc_build_protocol_expr): Call the get_protocol_reference
+ runtime hook.
+ (objc_build_selector_expr): Call the build_selector_reference
+ runtime hook.
+ (build_ivar_reference): Call the build_ivar_reference runtime
+ hook.
+ (hash_init): Set up ivar_offset_hash_list.
+ (start_class): Recognize the objc_exception attribute and store
+ it.
+ (continue_class): Use the class_decl and metaclass_decl runtime
+ hooks.
+ (build_objc_property_accessor_helpers): Renamed to
+ build_common_objc_property_accessor_helpers. Do not build
+ objc_copyStruct_decl, objc_getPropertyStruct_decl and
+ objc_setPropertyStruct_decl.
+ (objc_synthesize_getter): Check what struct setter/getter helper
+ is available instead of checking the type of runtime.
+ (get_super_receiver): Use the super_superclassfield_ident runtime
+ hook. Added assert. Use the get_class_super_ref and
+ get_category_super_ref runtime hooks.
+ (objc_v2_encode_prop_attr): New.
+
2011-01-17 Nicola Pero <nicola.pero@meta-innovation.com>
PR objc/47314
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index c479769..6f48aba 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -1,6 +1,6 @@
# Top level -*- makefile -*- fragment for GNU Objective-C
# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
-# 2008, 2009, 2010 Free Software Foundation, Inc.
+# 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
#This file is part of GCC.
@@ -43,11 +43,18 @@ objc: cc1obj$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: objc
+START_HDRS = $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_TREE_H) \
+ c-lang.h langhooks.h c-family/c-objc.h objc/objc-act.h
+
# Use maximal warnings for this front end.
objc-warn = $(STRICT_WARN)
# Language-specific object files for Objective C.
-OBJC_OBJS = objc/objc-lang.o objc/objc-act.o
+OBJC_OBJS = objc/objc-lang.o objc/objc-act.o \
+ objc/objc-runtime-shared-support.o \
+ objc/objc-gnu-runtime-abi-01.o \
+ objc/objc-next-runtime-abi-01.o \
+ objc/objc-next-runtime-abi-02.o \
objc_OBJS = $(OBJC_OBJS) cc1obj-checksum.o
@@ -66,17 +73,32 @@ cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $(
# Objective C language specific files.
-objc/objc-lang.o : objc/objc-lang.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_TREE_H) \
- $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
- c-objc-common.h c-family/c-objc.h objc/objc-act.h
-
-objc/objc-act.o : objc/objc-act.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
- $(TARGET_H) $(C_TREE_H) $(DIAGNOSTIC_CORE_H) toplev.h $(FLAGS_H) \
- objc/objc-act.h input.h $(FUNCTION_H) output.h debug.h langhooks.h \
- $(LANGHOOKS_DEF_H) $(HASHTAB_H) $(C_PRAGMA_H) gt-objc-objc-act.h \
- $(GIMPLE_H) c-lang.h c-family/c-objc.h
+objc/objc-lang.o : objc/objc-lang.c $(START_HDRS) \
+ $(GGC_H) $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
+ c-objc-common.h
+
+objc/objc-runtime-shared-support.o : objc/objc-runtime-shared-support.c \
+ $(START_HDRS) objc/objc-runtime-shared-support.h $(OBSTACK_H) \
+ objc/objc-next-metadata-tags.h gt-objc-objc-runtime-shared-support.h
+
+objc/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c $(START_HDRS) \
+ objc/objc-runtime-hooks.h $(GGC_H) \
+ objc/objc-runtime-shared-support.h gt-objc-objc-gnu-runtime-abi-01.h toplev.h
+
+objc/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c $(START_HDRS) \
+ $(GGC_H) objc/objc-runtime-hooks.h \
+ objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-01.h output.h \
+ objc/objc-runtime-shared-support.h $(TARGET_H)
+
+objc/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c $(START_HDRS) \
+ $(GGC_H) objc/objc-runtime-hooks.h \
+ objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-02.h $(TARGET_H) \
+ objc/objc-runtime-shared-support.h $(OBSTACK_H)
+
+objc/objc-act.o : objc/objc-act.c $(START_HDRS) $(GGC_H) \
+ $(DIAGNOSTIC_CORE_H) toplev.h $(FLAGS_H) input.h $(FUNCTION_H) output.h debug.h \
+ $(LANGHOOKS_DEF_H) $(HASHTAB_H) $(C_PRAGMA_H) gt-objc-objc-act.h $(OBSTACK_H) \
+ $(GIMPLE_H) objc/objc-runtime-shared-support.h objc/objc-runtime-hooks.h
objc.srcextra:
diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in
index 9ae6d6c..db5c5a5 100644
--- a/gcc/objc/config-lang.in
+++ b/gcc/objc/config-lang.in
@@ -1,6 +1,6 @@
# Top level configure fragment for GNU Objective-C
-# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2010
-# Free Software Foundation, Inc.
+# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2010,
+# 2011 Free Software Foundation, Inc.
#This file is part of GCC.
@@ -33,4 +33,4 @@ target_libs=target-libobjc
# Most of the object files for cc1obj actually come from C.
lang_requires="c"
-gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/objc/objc-act.c"
+gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 33d39b2..d73f2c0 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, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+ 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Steve Naroff.
@@ -53,15 +53,17 @@ along with GCC; see the file COPYING3. If not see
#include "tree-iterator.h"
#include "hashtab.h"
#include "langhooks-def.h"
-
+/* Different initialization, code gen and meta data generation for each
+ runtime. */
+#include "objc-runtime-hooks.h"
+/* Routines used mainly by the runtimes. */
+#include "objc-runtime-shared-support.h"
/* For default_tree_printer (). */
#include "tree-pretty-print.h"
/* For enum gimplify_status */
#include "gimple.h"
-#define OBJC_VOID_AT_END void_list_node
-
static unsigned int should_call_super_dealloc = 0;
/* When building Objective-C++, we are not linking against the C front-end
@@ -102,53 +104,30 @@ static unsigned int should_call_super_dealloc = 0;
#ifndef OBJC_FORWARDING_MIN_OFFSET
#define OBJC_FORWARDING_MIN_OFFSET 0
#endif
-
+
/* Set up for use of obstacks. */
#include "obstack.h"
/* This obstack is used to accumulate the encoding of a data type. */
-static struct obstack util_obstack;
+struct obstack util_obstack;
/* This points to the beginning of obstack contents, so we can free
the whole contents. */
char *util_firstobj;
-/* The version identifies which language generation and runtime
- the module (file) was compiled for, and is recorded in the
- module descriptor. */
-
-#define OBJC_VERSION (flag_next_runtime ? 6 : 8)
-#define PROTOCOL_VERSION 2
-
-/* (Decide if these can ever be validly changed.) */
-#define OBJC_ENCODE_INLINE_DEFS 0
-#define OBJC_ENCODE_DONT_INLINE_DEFS 1
-
/*** Private Interface (procedures) ***/
-/* Used by compile_file. */
-
-static void init_objc (void);
-static void finish_objc (void);
+/* Init stuff. */
+static void synth_module_prologue (void);
/* Code generation. */
-static tree objc_build_constructor (tree, VEC(constructor_elt,gc) *);
-static tree build_objc_method_call (location_t, int, tree, tree, tree, tree);
-static tree get_proto_encoding (tree);
-static tree lookup_interface (tree);
-static tree objc_add_static_instance (tree, tree);
-
static tree start_class (enum tree_code, tree, tree, tree, tree);
static tree continue_class (tree);
static void finish_class (tree);
static void start_method_def (tree);
-#ifdef OBJCPLUS
-static void objc_start_function (tree, tree, tree, tree);
-#else
-static void objc_start_function (tree, tree, tree, struct c_arg_info *);
-#endif
+
static tree start_protocol (enum tree_code, tree, tree, tree);
static tree build_method_decl (enum tree_code, tree, tree, tree, bool);
static tree objc_add_method (tree, tree, int, bool);
@@ -156,9 +135,6 @@ static tree add_instance_variable (tree, objc_ivar_visibility_kind, tree);
static tree build_ivar_reference (tree);
static tree is_ivar (tree, tree);
-static void build_objc_exception_stuff (void);
-static void build_next_objc_exception_stuff (void);
-
/* We only need the following for ObjC; ObjC++ will use C++'s definition
of DERIVED_FROM_P. */
#ifndef OBJCPLUS
@@ -175,18 +151,11 @@ static int match_proto_with_proto (tree, tree, int);
static tree lookup_property (tree, tree);
static tree lookup_property_in_list (tree, tree);
static tree lookup_property_in_protocol_list (tree, tree);
-static void build_objc_property_accessor_helpers (void);
+static void build_common_objc_property_accessor_helpers (void);
static void objc_xref_basetypes (tree, tree);
-static void build_class_template (void);
-static void build_selector_template (void);
-static void build_category_template (void);
-static void build_super_template (void);
-static tree build_protocol_initializer (tree, tree, tree, tree, tree);
static tree get_class_ivars (tree, bool);
-static tree generate_protocol_list (tree);
-static void build_protocol_reference (tree);
static void build_fast_enumeration_state_template (void);
@@ -197,9 +166,9 @@ static void objc_generate_cxx_cdtors (void);
/* objc attribute */
static void objc_decl_method_attributes (tree*, tree, int);
static tree build_keyword_selector (tree);
-static const char *synth_id_with_class_suffix (const char *, tree);
/* Hash tables to manage the global pool of method prototypes. */
+static void hash_init (void);
hash *nst_method_hash_list = 0;
hash *cls_method_hash_list = 0;
@@ -209,6 +178,8 @@ hash *cls_method_hash_list = 0;
hash *cls_name_hash_list = 0;
hash *als_name_hash_list = 0;
+hash *ivar_offset_hash_list = 0;
+
static void hash_class_name_enter (hash *, tree, tree);
static hash hash_class_name_lookup (hash *, tree);
@@ -220,16 +191,6 @@ static tree add_class (tree, tree);
static void add_category (tree, tree);
static inline tree lookup_category (tree, tree);
-enum string_section
-{
- class_names, /* class, category, protocol, module names */
- meth_var_names, /* method and variable names */
- meth_var_types /* method and variable type descriptors */
-};
-
-static tree add_objc_string (tree, enum string_section);
-static void build_selector_table_decl (void);
-
/* Protocols. */
static tree lookup_protocol (tree, bool, bool);
@@ -239,7 +200,6 @@ static tree lookup_and_install_protocols (tree, bool);
static void encode_type_qualifiers (tree);
static void encode_type (tree, int, int);
-static void encode_field_decl (tree, int, int);
#ifdef OBJCPLUS
static void really_start_method (tree, tree);
@@ -247,14 +207,7 @@ static void really_start_method (tree, tree);
static void really_start_method (tree, struct c_arg_info *);
#endif
static int comp_proto_with_proto (tree, tree, int);
-static tree get_arg_type_list (tree, int, int);
static tree objc_decay_parm_type (tree);
-static void objc_push_parm (tree);
-#ifdef OBJCPLUS
-static tree objc_get_parm_info (int);
-#else
-static struct c_arg_info *objc_get_parm_info (int);
-#endif
/* Utilities for debugging and error diagnostics. */
@@ -265,113 +218,13 @@ static char *gen_declaration (tree);
/* Everything else. */
-static tree create_field_decl (tree, const char *);
-static void add_class_reference (tree);
-static void build_protocol_template (void);
-static tree encode_method_prototype (tree);
-static void generate_classref_translation_entry (tree);
-static void handle_class_ref (tree);
-static void generate_struct_by_value_array (void)
- ATTRIBUTE_NORETURN;
+static void generate_struct_by_value_array (void) ATTRIBUTE_NORETURN;
+
static void mark_referenced_methods (void);
-static void generate_objc_image_info (void);
static bool objc_type_valid_for_messaging (tree type, bool allow_classes);
+static tree check_duplicates (hash, int, int);
/*** Private Interface (data) ***/
-
-/* Reserved tag definitions. */
-
-#define OBJECT_TYPEDEF_NAME "id"
-#define CLASS_TYPEDEF_NAME "Class"
-
-#define TAG_OBJECT "objc_object"
-#define TAG_CLASS "objc_class"
-#define TAG_SUPER "objc_super"
-#define TAG_SELECTOR "objc_selector"
-
-#define UTAG_CLASS "_objc_class"
-#define UTAG_IVAR "_objc_ivar"
-#define UTAG_IVAR_LIST "_objc_ivar_list"
-#define UTAG_METHOD "_objc_method"
-#define UTAG_METHOD_LIST "_objc_method_list"
-#define UTAG_CATEGORY "_objc_category"
-#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_METHOD_PROTOTYPE "_objc_method_prototype"
-#define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
-
-/* Note that the string object global name is only needed for the
- NeXT runtime. */
-#define STRING_OBJECT_GLOBAL_FORMAT "_%sClassReference"
-
-#define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
-
-#define TAG_ENUMERATION_MUTATION "objc_enumerationMutation"
-#define TAG_FAST_ENUMERATION_STATE "__objcFastEnumerationState"
-
-static const char *TAG_GETCLASS;
-static const char *TAG_GETMETACLASS;
-static const char *TAG_MSGSEND;
-static const char *TAG_MSGSENDSUPER;
-/* The NeXT Objective-C messenger may have two extra entry points, for use
- when returning a structure. */
-static const char *TAG_MSGSEND_STRET;
-static const char *TAG_MSGSENDSUPER_STRET;
-static const char *default_constant_string_class_name;
-
-/* Runtime metadata flags. */
-#define CLS_FACTORY 0x0001L
-#define CLS_META 0x0002L
-#define CLS_HAS_CXX_STRUCTORS 0x2000L
-
-#define OBJC_MODIFIER_STATIC 0x00000001
-#define OBJC_MODIFIER_FINAL 0x00000002
-#define OBJC_MODIFIER_PUBLIC 0x00000004
-#define OBJC_MODIFIER_PRIVATE 0x00000008
-#define OBJC_MODIFIER_PROTECTED 0x00000010
-#define OBJC_MODIFIER_NATIVE 0x00000020
-#define OBJC_MODIFIER_SYNCHRONIZED 0x00000040
-#define OBJC_MODIFIER_ABSTRACT 0x00000080
-#define OBJC_MODIFIER_VOLATILE 0x00000100
-#define OBJC_MODIFIER_TRANSIENT 0x00000200
-#define OBJC_MODIFIER_NONE_SPECIFIED 0x80000000
-
-/* NeXT-specific tags. */
-
-#define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
-#define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
-#define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
-#define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
-#define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
-#define TAG_EXCEPTIONMATCH "objc_exception_match"
-#define TAG_EXCEPTIONTHROW "objc_exception_throw"
-#define TAG_SYNCENTER "objc_sync_enter"
-#define TAG_SYNCEXIT "objc_sync_exit"
-#define TAG_SETJMP "_setjmp"
-#define UTAG_EXCDATA "_objc_exception_data"
-
-#define TAG_ASSIGNIVAR "objc_assign_ivar"
-#define TAG_ASSIGNGLOBAL "objc_assign_global"
-#define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast"
-
-/* Branch entry points. All that matters here are the addresses;
- functions with these names do not really exist in libobjc. */
-
-#define TAG_MSGSEND_FAST "objc_msgSend_Fast"
-#define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast"
-
-#define TAG_CXX_CONSTRUCT ".cxx_construct"
-#define TAG_CXX_DESTRUCT ".cxx_destruct"
-
-/* GNU-specific tags. */
-
-#define TAG_EXECCLASS "__objc_exec_class"
-#define TAG_GNUINIT "__objc_gnu_init"
-
/* Flags for lookup_method_static(). */
/* Look for class methods. */
@@ -385,8 +238,6 @@ static const char *default_constant_string_class_name;
/* The OCTI_... enumeration itself is in objc/objc-act.h. */
tree objc_global_trees[OCTI_MAX];
-static void handle_impent (struct imp_entry *);
-
struct imp_entry *imp_list = 0;
int imp_count = 0; /* `@implementation' */
int cat_count = 0; /* `@category' */
@@ -408,17 +259,12 @@ static int objc_collecting_ivars = 0;
@interface, or in a class extension. */
static bool objc_in_class_extension = false;
-#define BUFSIZE 1024
-
static char *errbuf; /* Buffer for error diagnostics */
/* An array of all the local variables in the current function that
need to be marked as volatile. */
VEC(tree,gc) *local_variables_to_volatilize = NULL;
-
-static int flag_typed_selectors;
-
/* Store all constructed constant strings in a hash table so that
they get uniqued properly. */
@@ -439,59 +285,16 @@ FILE *gen_declaration_file;
Type descriptors for instance variables contain more information
than methods (for static typing and embedded structures). */
-static int generating_instance_variables = 0;
-
-/* For building an objc struct. These may not be used when this file
- is compiled as part of obj-c++. */
-
-static bool objc_building_struct;
-static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED;
-
-/* Start building a struct for objc. */
-
-static tree
-objc_start_struct (tree name)
-{
- gcc_assert (!objc_building_struct);
- objc_building_struct = true;
- return start_struct (input_location, RECORD_TYPE, name, &objc_struct_info);
-}
-
-/* Finish building a struct for objc. */
-
-static tree
-objc_finish_struct (tree type, tree fieldlist)
-{
- gcc_assert (objc_building_struct);
- objc_building_struct = false;
- return finish_struct (input_location, type, fieldlist, NULL_TREE,
- objc_struct_info);
-}
-
-static tree
-build_sized_array_type (tree base_type, int size)
-{
- tree index_type = build_index_type (build_int_cst (NULL_TREE, size - 1));
- return build_array_type (base_type, index_type);
-}
-
-static tree
-add_field_decl (tree type, const char *name, tree **chain)
-{
- tree field = create_field_decl (type, name);
-
- if (*chain != NULL)
- **chain = field;
- *chain = &DECL_CHAIN (field);
+int generating_instance_variables = 0;
- return field;
-}
+/* Hooks for stuff that differs between runtimes. */
+objc_runtime_hooks runtime;
/* Create a temporary variable of type 'type'. If 'name' is set, uses
the specified name, else use no name. Returns the declaration of
the type. The 'name' is mostly useful for debugging.
*/
-static tree
+tree
objc_create_temporary_var (tree type, const char *name)
{
tree decl;
@@ -527,7 +330,8 @@ generate_struct_by_value_array (void)
int aggregate_in_mem[32];
int found = 0;
- /* Presumably no platform passes 32 byte structures in a register. */
+ /* ??? as an example, m64/ppc/Darwin can pass up to 8*long+13*double in regs.
+ Presumably no platform passes 32 byte structures in a register. */
for (i = 1; i < 32; i++)
{
char buffer[5];
@@ -567,6 +371,7 @@ generate_struct_by_value_array (void)
bool
objc_init (void)
{
+ bool ok;
#ifdef OBJCPLUS
if (cxx_init () == false)
#else
@@ -574,54 +379,30 @@ objc_init (void)
#endif
return false;
- /* If gen_declaration desired, open the output file. */
- if (flag_gen_declaration)
- {
- register char * const dumpname = concat (dump_base_name, ".decl", NULL);
- gen_declaration_file = fopen (dumpname, "w");
- if (gen_declaration_file == 0)
- fatal_error ("can%'t open %s: %m", dumpname);
- free (dumpname);
- }
+ if (print_struct_values && !flag_compare_debug)
+ /* This routine does not require any ObjC set-up and never returns. */
+ generate_struct_by_value_array ();
- if (flag_next_runtime)
- {
- TAG_GETCLASS = "objc_getClass";
- TAG_GETMETACLASS = "objc_getMetaClass";
- TAG_MSGSEND = "objc_msgSend";
- TAG_MSGSENDSUPER = "objc_msgSendSuper";
- TAG_MSGSEND_STRET = "objc_msgSend_stret";
- TAG_MSGSENDSUPER_STRET = "objc_msgSendSuper_stret";
- default_constant_string_class_name = "NSConstantString";
- }
- else
- {
- TAG_GETCLASS = "objc_get_class";
- TAG_GETMETACLASS = "objc_get_meta_class";
- TAG_MSGSEND = "objc_msg_lookup";
- TAG_MSGSENDSUPER = "objc_msg_lookup_super";
- /* GNU runtime does not provide special functions to support
- structure-returning methods. */
- default_constant_string_class_name = "NXConstantString";
- flag_typed_selectors = 1;
- /* GNU runtime does not need the compiler to change code
- in order to do GC. */
- if (flag_objc_gc)
- {
- warning_at (0, 0, "%<-fobjc-gc%> is ignored for %<-fgnu-runtime%>");
- flag_objc_gc=0;
- }
- }
+ /* Set up stuff used by FE parser and all runtimes. */
+ errbuf = XNEWVEC (char, 1024 * 10);
+ hash_init ();
+ gcc_obstack_init (&util_obstack);
+ util_firstobj = (char *) obstack_finish (&util_obstack);
- init_objc ();
+ /* ... and then check flags and set-up for the selected runtime ... */
+ if (flag_next_runtime && flag_objc_abi >= 2)
+ ok = objc_next_runtime_abi_02_init (&runtime);
+ else if (flag_next_runtime)
+ ok = objc_next_runtime_abi_01_init (&runtime);
+ else
+ ok = objc_gnu_runtime_abi_01_init (&runtime);
- if (print_struct_values && !flag_compare_debug)
- generate_struct_by_value_array ();
+ /* If that part of the setup failed - bail out immediately. */
+ if (!ok)
+ return false;
-#ifndef OBJCPLUS
- if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
- using_eh_for_cleanups ();
-#endif
+ /* Generate general types and push runtime-specific decls to file scope. */
+ synth_module_prologue ();
return true;
}
@@ -633,13 +414,58 @@ objc_write_global_declarations (void)
{
mark_referenced_methods ();
- /* Finalize Objective-C runtime data. */
- finish_objc ();
+ /* A missing @end might not be detected by the parser. */
+ if (objc_implementation_context)
+ {
+ warning (0, "%<@end%> missing in implementation context");
+ finish_class (objc_implementation_context);
+ objc_ivar_chain = NULL_TREE;
+ objc_implementation_context = NULL_TREE;
+ }
+
+ if (warn_selector)
+ {
+ int slot;
+ hash hsh;
- if (gen_declaration_file)
- fclose (gen_declaration_file);
+ /* Run through the selector hash tables and print a warning for any
+ selector which has multiple methods. */
+
+ for (slot = 0; slot < SIZEHASHTABLE; slot++)
+ {
+ for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
+ check_duplicates (hsh, 0, 1);
+ for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
+ check_duplicates (hsh, 0, 0);
+ }
+ }
+
+ /* TODO: consider an early exit here if either errorcount or sorrycount
+ is non-zero. Not only is it wasting time to generate the metadata,
+ it needlessly imposes need to re-check for things that are already
+ determined to be errors. */
+
+ /* Finalize Objective-C runtime data. No need to generate tables
+ and code if only checking syntax, or if generating a PCH file. */
+ if (!flag_syntax_only && !pch_file)
+ {
+ /* If gen_declaration desired, open the output file. */
+ if (flag_gen_declaration)
+ {
+ char * const dumpname = concat (dump_base_name, ".decl", NULL);
+ gen_declaration_file = fopen (dumpname, "w");
+ if (gen_declaration_file == 0)
+ fatal_error ("can%'t open %s: %m", dumpname);
+ free (dumpname);
+ }
+ /* Compute and emit the meta-data tables for this runtime. */
+ (*runtime.generate_metadata) ();
+ /* ... and then close any declaration file we opened. */
+ if (gen_declaration_file)
+ fclose (gen_declaration_file);
+ }
}
-
+
/* Return the first occurrence of a method declaration corresponding
to sel_name in rproto_list. Search rproto_list recursively.
If is_class is 0, search for instance methods, otherwise for class
@@ -2200,20 +2026,6 @@ objc_add_instance_variable (tree decl)
decl);
}
-/* Return true if TYPE is 'id'. */
-
-static bool
-objc_is_object_id (tree type)
-{
- return OBJC_TYPE_NAME (type) == objc_object_id;
-}
-
-static bool
-objc_is_class_id (tree type)
-{
- return OBJC_TYPE_NAME (type) == objc_class_id;
-}
-
/* Construct a C struct with same name as KLASS, a base struct with tag
SUPER_NAME (if any), and FIELDS indicated. */
@@ -2761,7 +2573,7 @@ objc_derived_from_p (tree parent, tree child)
}
#endif
-static tree
+tree
objc_build_component_ref (tree datum, tree component)
{
/* If COMPONENT is NULL, the caller is referring to the anonymous
@@ -2999,63 +2811,34 @@ lookup_and_install_protocols (tree protocols, bool definition_required)
return return_value;
}
-/* Create a declaration for field NAME of a given TYPE. */
-
-static tree
-create_field_decl (tree type, const char *name)
-{
- return build_decl (input_location,
- FIELD_DECL, get_identifier (name), type);
-}
-
-/* Create a global, static declaration for variable NAME of a given TYPE. The
- finish_var_decl() routine will need to be called on it afterwards. */
-
-static 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;
- DECL_INITIAL (var) = error_mark_node; /* A real initializer is coming... */
- DECL_IGNORED_P (var) = 1;
- DECL_ARTIFICIAL (var) = 1;
- DECL_CONTEXT (var) = NULL_TREE;
-#ifdef OBJCPLUS
- DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
-#endif
-
- return var;
-}
-
-/* Finish off the variable declaration created by start_var_decl(). */
-
static void
-finish_var_decl (tree var, tree initializer)
+build_common_objc_exception_stuff (void)
{
- finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE);
-}
+ tree noreturn_list, nothrow_list, temp_type;
-/* Find the decl for the constant string class reference. This is only
- used for the NeXT runtime. */
+ noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
+ nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
-static tree
-setup_string_decl (void)
-{
- char *name;
- size_t length;
+ /* void objc_exception_throw(id) __attribute__((noreturn)); */
+ /* void objc_sync_enter(id); */
+ /* void objc_sync_exit(id); */
+ temp_type = build_function_type_list (void_type_node,
+ objc_object_type,
+ NULL_TREE);
+ objc_exception_throw_decl
+ = add_builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
+ noreturn_list);
+ /* Make sure that objc_exception_throw (id) claims that it may throw an
+ exception. */
+ TREE_NOTHROW (objc_exception_throw_decl) = 0;
- /* %s in format will provide room for terminating null */
- length = strlen (STRING_OBJECT_GLOBAL_FORMAT)
- + strlen (constant_string_class_name);
- name = XNEWVEC (char, length);
- sprintf (name, STRING_OBJECT_GLOBAL_FORMAT,
- constant_string_class_name);
- constant_string_global_id = get_identifier (name);
- string_class_decl = lookup_name (constant_string_global_id);
+ objc_sync_enter_decl
+ = add_builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
+ NULL, nothrow_list);
- return string_class_decl;
+ objc_sync_exit_decl
+ = add_builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
+ NULL, nothrow_list);
}
/* Purpose: "play" parser, creating/installing representations
@@ -3100,12 +2883,12 @@ synth_module_prologue (void)
objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
/* Declare the 'id' and 'Class' typedefs. */
-
type = lang_hooks.decls.pushdecl (build_decl (input_location,
TYPE_DECL,
objc_object_name,
objc_object_type));
TREE_NO_WARNING (type) = 1;
+
type = lang_hooks.decls.pushdecl (build_decl (input_location,
TYPE_DECL,
objc_class_name,
@@ -3113,29 +2896,11 @@ synth_module_prologue (void)
TREE_NO_WARNING (type) = 1;
/* Forward-declare '@interface Protocol'. */
-
type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
objc_declare_class (tree_cons (NULL_TREE, type, NULL_TREE));
- objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE,
- type));
-
- /* Declare type of selector-objects that represent an operation name. */
-
- if (flag_next_runtime)
- /* `struct objc_selector *' */
- objc_selector_type
- = build_pointer_type (xref_tag (RECORD_TYPE,
- get_identifier (TAG_SELECTOR)));
- else
- /* `const struct objc_selector *' */
- objc_selector_type
- = build_pointer_type
- (build_qualified_type (xref_tag (RECORD_TYPE,
- get_identifier (TAG_SELECTOR)),
- TYPE_QUAL_CONST));
+ objc_protocol_type = build_pointer_type (xref_tag (RECORD_TYPE, type));
/* Declare receiver type used for dispatching messages to 'super'. */
-
/* `struct objc_super *' */
objc_super_type = build_pointer_type (xref_tag (RECORD_TYPE,
get_identifier (TAG_SUPER)));
@@ -3151,162 +2916,18 @@ synth_module_prologue (void)
(xref_tag (RECORD_TYPE,
get_identifier (UTAG_IVAR_LIST)));
- /* TREE_NOTHROW is cleared for the message-sending functions,
- because the function that gets called can throw in Obj-C++, or
- could itself call something that can throw even in Obj-C. */
-
- if (flag_next_runtime)
- {
- /* NB: In order to call one of the ..._stret (struct-returning)
- functions, the function *MUST* first be cast to a signature that
- corresponds to the actual ObjC method being invoked. This is
- what is done by the build_objc_method_call() routine below. */
-
- /* id objc_msgSend (id, SEL, ...); */
- /* id objc_msgSendNonNil (id, SEL, ...); */
- /* id objc_msgSend_stret (id, SEL, ...); */
- /* id objc_msgSendNonNil_stret (id, SEL, ...); */
- type
- = build_varargs_function_type_list (objc_object_type,
- objc_object_type,
- objc_selector_type,
- NULL_TREE);
- umsg_decl = add_builtin_function (TAG_MSGSEND,
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- umsg_nonnil_decl = add_builtin_function (TAG_MSGSEND_NONNIL,
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- umsg_stret_decl = add_builtin_function (TAG_MSGSEND_STRET,
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- umsg_nonnil_stret_decl = add_builtin_function (TAG_MSGSEND_NONNIL_STRET,
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
-
- /* These can throw, because the function that gets called can throw
- in Obj-C++, or could itself call something that can throw even
- in Obj-C. */
- TREE_NOTHROW (umsg_decl) = 0;
- TREE_NOTHROW (umsg_nonnil_decl) = 0;
- TREE_NOTHROW (umsg_stret_decl) = 0;
- TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
-
- /* id objc_msgSend_Fast (id, SEL, ...)
- __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
-#ifdef OFFS_MSGSEND_FAST
- umsg_fast_decl = add_builtin_function (TAG_MSGSEND_FAST,
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- TREE_NOTHROW (umsg_fast_decl) = 0;
- DECL_ATTRIBUTES (umsg_fast_decl)
- = tree_cons (get_identifier ("hard_coded_address"),
- build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
- NULL_TREE);
-#else
- /* No direct dispatch available. */
- umsg_fast_decl = umsg_decl;
-#endif
-
- /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
- /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
- type
- = build_varargs_function_type_list (objc_object_type,
- objc_super_type,
- objc_selector_type,
- NULL_TREE);
- umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- umsg_super_stret_decl = add_builtin_function (TAG_MSGSENDSUPER_STRET,
- type, 0, NOT_BUILT_IN, 0,
- NULL_TREE);
- TREE_NOTHROW (umsg_super_decl) = 0;
- TREE_NOTHROW (umsg_super_stret_decl) = 0;
- }
- else
- {
- /* GNU runtime messenger entry points. */
-
- /* typedef id (*IMP)(id, SEL, ...); */
- tree ftype =
- build_varargs_function_type_list (objc_object_type,
- objc_object_type,
- objc_selector_type,
- NULL_TREE);
- tree IMP_type = build_pointer_type (ftype);
-
- /* IMP objc_msg_lookup (id, SEL); */
- type = build_function_type_list (IMP_type,
- objc_object_type,
- objc_selector_type,
- NULL_TREE);
- umsg_decl = add_builtin_function (TAG_MSGSEND,
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- TREE_NOTHROW (umsg_decl) = 0;
-
- /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
- type
- = build_function_type_list (IMP_type,
- objc_super_type,
- objc_selector_type,
- NULL_TREE);
- umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- TREE_NOTHROW (umsg_super_decl) = 0;
-
- /* The following GNU runtime entry point is called to initialize
- each module:
-
- __objc_exec_class (void *); */
- type
- = build_function_type_list (void_type_node,
- ptr_type_node,
- NULL_TREE);
- execclass_decl = add_builtin_function (TAG_EXECCLASS,
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- }
-
- /* id objc_getClass (const char *); */
-
- type = build_function_type_list (objc_object_type,
- const_string_type_node,
- NULL_TREE);
-
- objc_get_class_decl
- = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
-
- /* id objc_getMetaClass (const char *); */
+ build_common_objc_exception_stuff ();
- objc_get_meta_class_decl
- = add_builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
-
- build_class_template ();
- build_super_template ();
- build_protocol_template ();
- build_category_template ();
- build_objc_exception_stuff ();
+ /* Set-up runtime-specific templates, message and exception stuff. */
+ (*runtime.initialize) ();
/* Declare objc_getProperty, object_setProperty and other property
accessor helpers. */
- build_objc_property_accessor_helpers ();
-
- if (flag_next_runtime)
- build_next_objc_exception_stuff ();
-
- /* static SEL _OBJC_SELECTOR_TABLE[]; */
-
- if (! flag_next_runtime)
- build_selector_table_decl ();
+ build_common_objc_property_accessor_helpers ();
/* Forward declare constant_string_id and constant_string_type. */
if (!constant_string_class_name)
- constant_string_class_name = default_constant_string_class_name;
-
+ constant_string_class_name = runtime.default_constant_string_class_name;
constant_string_id = get_identifier (constant_string_class_name);
objc_declare_class (tree_cons (NULL_TREE, constant_string_id, NULL_TREE));
@@ -3333,6 +2954,8 @@ synth_module_prologue (void)
debug_hooks = save_hooks;
}
+/* --- const strings --- */
+
/* Ensure that the ivar list for NSConstantString/NXConstantString
(or whatever was specified via `-fconstant-string-class')
contains fields at least as large as the following three, so that
@@ -3397,7 +3020,7 @@ objc_build_internal_const_str_type (void)
/* Custom build_string which sets TREE_TYPE! */
-static tree
+tree
my_build_string (int len, const char *str)
{
return fix_string_type (build_string (len, str));
@@ -3406,7 +3029,7 @@ my_build_string (int len, const char *str)
/* Build a string with contents STR and length LEN and convert it to a
pointer. */
-static tree
+tree
my_build_string_pointer (int len, const char *str)
{
tree string = my_build_string (len, str);
@@ -3452,7 +3075,7 @@ objc_build_string_object (tree string)
{
tree constant_string_class;
int length;
- tree fields, addr;
+ tree addr;
struct string_descriptor *desc, key;
void **loc;
@@ -3465,7 +3088,8 @@ objc_build_string_object (tree string)
literal. On Darwin (Mac OS X), for example, we may wish to obtain a
constant CFString reference instead.
At present, this is only supported for the NeXT runtime. */
- if (flag_next_runtime && targetcm.objc_construct_string_object)
+ if (flag_next_runtime
+ && targetcm.objc_construct_string_object)
{
tree constructor = (*targetcm.objc_construct_string_object) (string);
if (constructor)
@@ -3489,11 +3113,10 @@ objc_build_string_object (tree string)
else if (!check_string_class_template ())
error ("interface %qE does not have valid constant string layout",
constant_string_id);
- /* For the NeXT runtime, we can generate a literal reference
- to the string class, don't need to run a constructor. */
- else if (flag_next_runtime && !setup_string_decl ())
- error ("cannot find reference tag for class %qE",
- constant_string_id);
+ /* If the runtime can generate a literal reference to the string class,
+ don't need to run a constructor. */
+ else if (!(*runtime.setup_const_string_class_decl)())
+ error ("cannot find reference tag for class %qE", constant_string_id);
else
{
string_layout_checked = 1; /* Success! */
@@ -3511,40 +3134,10 @@ objc_build_string_object (tree string)
if (!desc)
{
- tree var, constructor;
- VEC(constructor_elt,gc) *v = NULL;
*loc = desc = ggc_alloc_string_descriptor ();
desc->literal = string;
-
- /* GNU: (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length }) */
- /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
- fields = TYPE_FIELDS (internal_const_str_type);
- CONSTRUCTOR_APPEND_ELT (v, fields,
- flag_next_runtime
- ? build_unary_op (input_location,
- ADDR_EXPR, string_class_decl, 0)
- : build_int_cst (NULL_TREE, 0));
- fields = DECL_CHAIN (fields);
- CONSTRUCTOR_APPEND_ELT (v, fields,
- build_unary_op (input_location,
- ADDR_EXPR, string, 1));
- fields = DECL_CHAIN (fields);
- CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
- constructor = objc_build_constructor (internal_const_str_type, v);
-
- if (!flag_next_runtime)
- constructor
- = objc_add_static_instance (constructor, constant_string_type);
- else
- {
- var = build_decl (input_location,
- CONST_DECL, NULL, TREE_TYPE (constructor));
- DECL_INITIAL (var) = constructor;
- TREE_STATIC (var) = 1;
- pushdecl_top_level (var);
- constructor = var;
- }
- desc->constructor = constructor;
+ desc->constructor =
+ (*runtime.build_const_string_constructor) (input_location, string, length);
}
addr = convert (build_pointer_type (constant_string_type),
@@ -3554,51 +3147,10 @@ objc_build_string_object (tree string)
return addr;
}
-/* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
-
-static GTY(()) int num_static_inst;
-
-static tree
-objc_add_static_instance (tree constructor, tree class_decl)
-{
- tree *chain, decl;
- char buf[256];
-
- /* 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 = tree_cons (NULL_TREE, class_decl, NULL_TREE);
- add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
- }
-
- sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++);
- decl = build_decl (input_location,
- VAR_DECL, get_identifier (buf), class_decl);
- TREE_STATIC (decl) = 1;
- DECL_ARTIFICIAL (decl) = 1;
- TREE_USED (decl) = 1;
- DECL_INITIAL (decl) = constructor;
-
- /* We may be writing something else just now.
- Postpone till end of input. */
- DECL_DEFER_OUTPUT (decl) = 1;
- pushdecl_top_level (decl);
- rest_of_decl_compilation (decl, 1, 0);
-
- /* Add the DECL to the head of this CLASS' list. */
- TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
-
- return decl;
-}
-
/* Build a static constant CONSTRUCTOR
with type TYPE and elements ELTS. */
-static tree
+tree
objc_build_constructor (tree type, VEC(constructor_elt,gc) *elts)
{
tree constructor = build_constructor (type, elts);
@@ -3616,360 +3168,10 @@ objc_build_constructor (tree type, VEC(constructor_elt,gc) *elts)
return constructor;
}
-
-/* Take care of defining and initializing _OBJC_SYMBOLS. */
-
-/* Predefine the following data type:
-
- struct _objc_symtab
- {
- long sel_ref_cnt;
- SEL *refs;
- short cls_def_cnt;
- short cat_def_cnt;
- void *defs[cls_def_cnt + cat_def_cnt];
- }; */
-
-static void
-build_objc_symtab_template (void)
-{
- tree fields, *chain = NULL;
-
- objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
-
- /* long sel_ref_cnt; */
- fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
-
- /* SEL *refs; */
- add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
-
- /* short cls_def_cnt; */
- add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
-
- /* short cat_def_cnt; */
- add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
-
- if (imp_count || cat_count || !flag_next_runtime)
- {
- /* void *defs[imp_count + cat_count (+ 1)]; */
- /* NB: The index is one less than the size of the array. */
- int index = imp_count + cat_count + (flag_next_runtime ? -1: 0);
- tree array_type = build_sized_array_type (ptr_type_node, index + 1);
- add_field_decl (array_type, "defs", &chain);
- }
-
- objc_finish_struct (objc_symtab_template, fields);
-}
-
-/* Create the initial value for the `defs' field of _objc_symtab.
- This is a CONSTRUCTOR. */
-
-static tree
-init_def_list (tree type)
-{
- tree expr;
- struct imp_entry *impent;
- VEC(constructor_elt,gc) *v = NULL;
-
- if (imp_count)
- for (impent = imp_list; impent; impent = impent->next)
- {
- if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
- {
- expr = build_unary_op (input_location,
- ADDR_EXPR, impent->class_decl, 0);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
- }
-
- if (cat_count)
- for (impent = imp_list; impent; impent = impent->next)
- {
- if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
- {
- expr = build_unary_op (input_location,
- ADDR_EXPR, impent->class_decl, 0);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
- }
-
- if (!flag_next_runtime)
- {
- /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
- if (static_instances_decl)
- expr = build_unary_op (input_location,
- ADDR_EXPR, static_instances_decl, 0);
- else
- expr = integer_zero_node;
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
-
- return objc_build_constructor (type, v);
-}
-
-/* Construct the initial value for all of _objc_symtab. */
-
-static tree
-init_objc_symtab (tree type)
-{
- VEC(constructor_elt,gc) *v = NULL;
-
- /* sel_ref_cnt = { ..., 5, ... } */
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- build_int_cst (long_integer_type_node, 0));
-
- /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
-
- if (flag_next_runtime || ! sel_ref_chain)
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (
- build_pointer_type (objc_selector_type),
- integer_zero_node));
- else
- {
- tree expr = build_unary_op (input_location, ADDR_EXPR,
- UOBJC_SELECTOR_TABLE_decl, 1);
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- convert (build_pointer_type (objc_selector_type),
- expr));
- }
-
- /* cls_def_cnt = { ..., 5, ... } */
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- build_int_cst (short_integer_type_node, imp_count));
-
- /* cat_def_cnt = { ..., 5, ... } */
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- build_int_cst (short_integer_type_node, cat_count));
-
- /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
-
- if (imp_count || cat_count || !flag_next_runtime)
- {
-
- tree field = TYPE_FIELDS (type);
- field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
- }
-
- return objc_build_constructor (type, v);
-}
-
-/* Generate forward declarations for metadata such as
- 'OBJC_CLASS_...'. */
-
-static tree
-build_metadata_decl (const char *name, tree type)
-{
- tree decl;
-
- /* struct TYPE NAME_<name>; */
- decl = start_var_decl (type, synth_id_with_class_suffix
- (name,
- objc_implementation_context));
-
- return decl;
-}
-
-/* Push forward-declarations of all the categories so that
- init_def_list can use them in a CONSTRUCTOR. */
-
-static void
-forward_declare_categories (void)
-{
- struct imp_entry *impent;
- tree sav = objc_implementation_context;
-
- for (impent = imp_list; impent; impent = impent->next)
- {
- if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
- {
- /* Set an invisible arg to synth_id_with_class_suffix. */
- objc_implementation_context = impent->imp_context;
- /* extern struct objc_category _OBJC_CATEGORY_<name>; */
- impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY",
- objc_category_template);
- }
- }
- objc_implementation_context = sav;
-}
-
-/* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
- and initialized appropriately. */
-
-static void
-generate_objc_symtab_decl (void)
-{
-
- build_objc_symtab_template ();
- UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
- finish_var_decl (UOBJC_SYMBOLS_decl,
- init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
-}
-
-static tree
-init_module_descriptor (tree type)
-{
- tree expr;
- VEC(constructor_elt,gc) *v = NULL;
-
- /* version = { 1, ... } */
-
- expr = build_int_cst (long_integer_type_node, OBJC_VERSION);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
-
- /* size = { ..., sizeof (struct _objc_module), ... } */
-
- expr = convert (long_integer_type_node,
- size_in_bytes (objc_module_template));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
-
- /* Don't provide any file name for security reasons. */
- /* name = { ..., "", ... } */
-
- expr = add_objc_string (get_identifier (""), class_names);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
-
- /* symtab = { ..., _OBJC_SYMBOLS, ... } */
-
- if (UOBJC_SYMBOLS_decl)
- expr = build_unary_op (input_location,
- ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
- else
- expr = null_pointer_node;
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
-
- return objc_build_constructor (type, v);
-}
-
-/* Write out the data structures to describe Objective C classes defined.
-
- struct _objc_module { ... } _OBJC_MODULE = { ... }; */
-
-static void
-build_module_descriptor (void)
-{
- tree decls, *chain = NULL;
-
-#ifdef OBJCPLUS
- push_lang_context (lang_name_c); /* extern "C" */
-#endif
-
- objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE));
-
- /* long version; */
- decls = add_field_decl (long_integer_type_node, "version", &chain);
-
- /* long size; */
- add_field_decl (long_integer_type_node, "size", &chain);
-
- /* char *name; */
- add_field_decl (string_type_node, "name", &chain);
-
- /* struct _objc_symtab *symtab; */
- add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE,
- get_identifier (UTAG_SYMTAB))),
- "symtab", &chain);
-
- objc_finish_struct (objc_module_template, decls);
-
- /* Create an instance of "_objc_module". */
- UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES");
- /* This is the root of the metadata for defined classes and categories, it
- is referenced by the runtime and, therefore, needed. */
- DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1;
- finish_var_decl (UOBJC_MODULES_decl,
- init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)));
-
-#ifdef OBJCPLUS
- pop_lang_context ();
-#endif
-}
-
-/* The GNU runtime requires us to provide a static initializer function
- for each module:
-
- static void __objc_gnu_init (void) {
- __objc_exec_class (&L_OBJC_MODULES);
- } */
-
-static void
-build_module_initializer_routine (void)
-{
- tree body;
-
-#ifdef OBJCPLUS
- push_lang_context (lang_name_c); /* extern "C" */
-#endif
-
- objc_push_parm (build_decl (input_location,
- PARM_DECL, NULL_TREE, void_type_node));
-#ifdef OBJCPLUS
- objc_start_function (get_identifier (TAG_GNUINIT),
- build_function_type_list (void_type_node, NULL_TREE),
- NULL_TREE, NULL_TREE);
-#else
- objc_start_function (get_identifier (TAG_GNUINIT),
- build_function_type_list (void_type_node, NULL_TREE),
- NULL_TREE, objc_get_parm_info (0));
-#endif
- body = c_begin_compound_stmt (true);
- add_stmt (build_function_call
- (input_location,
- execclass_decl,
- build_tree_list
- (NULL_TREE,
- build_unary_op (input_location, ADDR_EXPR,
- UOBJC_MODULES_decl, 0))));
- add_stmt (c_end_compound_stmt (input_location, body, true));
-
- TREE_PUBLIC (current_function_decl) = 0;
-
-#ifndef OBJCPLUS
- /* For Objective-C++, we will need to call __objc_gnu_init
- from objc_generate_static_init_call() below. */
- DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
-#endif
-
- GNU_INIT_decl = current_function_decl;
- finish_function ();
-
-#ifdef OBJCPLUS
- pop_lang_context ();
-#endif
-}
-
-#ifdef OBJCPLUS
-/* Return 1 if the __objc_gnu_init function has been synthesized and needs
- to be called by the module initializer routine. */
-
-int
-objc_static_init_needed_p (void)
-{
- return (GNU_INIT_decl != NULL_TREE);
-}
-
-/* Generate a call to the __objc_gnu_init initializer function. */
-
-tree
-objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
-{
- add_stmt (build_stmt (input_location, EXPR_STMT,
- build_function_call (input_location,
- GNU_INIT_decl, NULL_TREE)));
-
- return ctors;
-}
-#endif /* OBJCPLUS */
/* Return the DECL of the string IDENT in the SECTION. */
-static tree
+tree
get_objc_string_decl (tree ident, enum string_section section)
{
tree chain;
@@ -3985,6 +3187,9 @@ get_objc_string_decl (tree ident, enum string_section section)
case meth_var_types:
chain = meth_var_types_chain;
break;
+ case prop_names_attr:
+ chain = prop_names_attr_chain;
+ break;
default:
gcc_unreachable ();
}
@@ -3993,314 +3198,14 @@ get_objc_string_decl (tree ident, enum string_section section)
if (TREE_VALUE (chain) == ident)
return (TREE_PURPOSE (chain));
- gcc_unreachable ();
+ /* We didn't find the entry. */
return NULL_TREE;
}
-/* Output references to all statically allocated objects. Return the DECL
- for the array built. */
-
-static void
-generate_static_references (void)
-{
- tree expr = NULL_TREE;
- tree class_name, klass, decl;
- tree cl_chain, in_chain, type
- = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
- int num_inst, num_class;
- char buf[256];
- VEC(constructor_elt,gc) *decls = NULL;
-
- 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++)
- {
- VEC(constructor_elt,gc) *v = NULL;
-
- 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);
- decl = start_var_decl (type, buf);
-
- /* Output {class_name, ...}. */
- klass = TREE_VALUE (cl_chain);
- class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- build_unary_op (input_location,
- 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 (input_location,
- ADDR_EXPR, TREE_VALUE (in_chain), 1);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
-
- /* Output {..., NULL}. */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
-
- expr = objc_build_constructor (TREE_TYPE (decl), v);
- finish_var_decl (decl, expr);
- CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE,
- build_unary_op (input_location,
- ADDR_EXPR, decl, 1));
- }
-
- CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE, build_int_cst (NULL_TREE, 0));
- expr = objc_build_constructor (type, decls);
- static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
- finish_var_decl (static_instances_decl, expr);
-}
-
-static GTY(()) int selector_reference_idx;
-
-static tree
-build_selector_reference_decl (void)
-{
- tree decl;
- char buf[256];
-
- sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", selector_reference_idx++);
- decl = start_var_decl (objc_selector_type, buf);
-
- return decl;
-}
-
-static void
-build_selector_table_decl (void)
-{
- tree temp;
-
- if (flag_typed_selectors)
- {
- build_selector_template ();
- temp = build_array_type (objc_selector_template, NULL_TREE);
- }
- else
- temp = build_array_type (objc_selector_type, NULL_TREE);
-
- UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
-}
-
-/* Just a handy wrapper for add_objc_string. */
-
-static tree
-build_selector (tree ident)
-{
- return convert (objc_selector_type,
- add_objc_string (ident, meth_var_names));
-}
-
-/* Used only by build_*_selector_translation_table (). */
-static void
-diagnose_missing_method (tree meth, location_t here)
-{
- tree method_chain;
- bool found = false;
- for (method_chain = meth_var_names_chain;
- method_chain;
- method_chain = TREE_CHAIN (method_chain))
- {
- if (TREE_VALUE (method_chain) == meth)
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- warning_at (here, 0, "creating selector for nonexistent method %qE",
- meth);
-}
-
-static void
-build_next_selector_translation_table (void)
-{
- tree chain;
- for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
- {
- tree expr;
- tree decl = TREE_PURPOSE (chain);
- if (warn_selector && objc_implementation_context)
- {
- location_t loc;
- if (decl)
- loc = DECL_SOURCE_LOCATION (decl);
- else
- loc = input_location;
- diagnose_missing_method (TREE_VALUE (chain), loc);
- }
-
- expr = build_selector (TREE_VALUE (chain));
-
- if (decl)
- {
- /* Entries of this form are used for references to methods.
- The runtime re-writes these on start-up, but the compiler can't see
- that and optimizes it away unless we force it. */
- DECL_PRESERVE_P (decl) = 1;
- finish_var_decl (decl, expr);
- }
- }
-}
-
-static void
-build_gnu_selector_translation_table (void)
-{
- tree chain;
-/* int offset = 0;
- tree decl = NULL_TREE;*/
- VEC(constructor_elt,gc) *inits = NULL;
-
- for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
- {
- tree expr;
-
- if (warn_selector && objc_implementation_context)
- diagnose_missing_method (TREE_VALUE (chain), input_location);
-
- expr = build_selector (TREE_VALUE (chain));
- /* add one for the '\0' character
- offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;*/
-
- {
- if (flag_typed_selectors)
- {
- VEC(constructor_elt,gc) *v = NULL;
- tree encoding = get_proto_encoding (TREE_PURPOSE (chain));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, encoding);
- expr = objc_build_constructor (objc_selector_template, v);
- }
-
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
- }
- } /* each element in the chain */
-
- {
- /* Cause the selector table (previously forward-declared)
- to be actually output. */
- tree expr;
-
- if (flag_typed_selectors)
- {
- VEC(constructor_elt,gc) *v = NULL;
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
- expr = objc_build_constructor (objc_selector_template, v);
- }
- else
- expr = integer_zero_node;
-
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
- expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
- inits);
- finish_var_decl (UOBJC_SELECTOR_TABLE_decl, expr);
- }
-}
-
-static tree
-get_proto_encoding (tree proto)
-{
- tree encoding;
- if (proto)
- {
- if (! METHOD_ENCODING (proto))
- {
- encoding = encode_method_prototype (proto);
- METHOD_ENCODING (proto) = encoding;
- }
- else
- encoding = METHOD_ENCODING (proto);
-
- return add_objc_string (encoding, meth_var_types);
- }
- else
- return build_int_cst (NULL_TREE, 0);
-}
-
-/* sel_ref_chain is a list whose "value" fields will be instances of
- identifier_node that represent the selector. LOC is the location of
- the @selector. */
-
-static tree
-build_typed_selector_reference (location_t loc, tree ident, tree prototype)
-{
- tree *chain = &sel_ref_chain;
- tree expr;
- int index = 0;
-
- while (*chain)
- {
- if (TREE_PURPOSE (*chain) == prototype && TREE_VALUE (*chain) == ident)
- goto return_at_index;
-
- index++;
- chain = &TREE_CHAIN (*chain);
- }
-
- *chain = tree_cons (prototype, ident, NULL_TREE);
-
- return_at_index:
- expr = build_unary_op (loc, ADDR_EXPR,
- build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
- build_int_cst (NULL_TREE, index)),
- 1);
- return convert (objc_selector_type, expr);
-}
-
-static tree
-build_selector_reference (location_t loc, tree ident)
-{
- tree *chain = &sel_ref_chain;
- tree expr;
- int index = 0;
-
- while (*chain)
- {
- if (TREE_VALUE (*chain) == ident)
- return (flag_next_runtime
- ? TREE_PURPOSE (*chain)
- : build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
- build_int_cst (NULL_TREE, index)));
-
- index++;
- chain = &TREE_CHAIN (*chain);
- }
-
- expr = (flag_next_runtime ? build_selector_reference_decl (): NULL_TREE);
-
- *chain = tree_cons (expr, ident, NULL_TREE);
-
- return (flag_next_runtime
- ? expr
- : build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
- build_int_cst (NULL_TREE, index)));
-}
-
-static GTY(()) int class_reference_idx;
-
-static tree
-build_class_reference_decl (void)
-{
- tree decl;
- char buf[256];
-
- sprintf (buf, "_OBJC_CLASS_REFERENCES_%d", class_reference_idx++);
- decl = start_var_decl (objc_class_type, buf);
-
- return decl;
-}
-
/* Create a class reference, but don't create a variable to reference
it. */
-static void
+void
add_class_reference (tree ident)
{
tree chain;
@@ -4361,93 +3266,7 @@ objc_get_class_reference (tree ident)
return error_mark_node;
}
- if (flag_next_runtime && !flag_zero_link)
- {
- tree *chain;
- tree decl;
-
- for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
- if (TREE_VALUE (*chain) == ident)
- {
- if (! TREE_PURPOSE (*chain))
- TREE_PURPOSE (*chain) = build_class_reference_decl ();
-
- return TREE_PURPOSE (*chain);
- }
-
- decl = build_class_reference_decl ();
- *chain = tree_cons (decl, ident, NULL_TREE);
- return decl;
- }
- else
- {
- tree params;
-
- add_class_reference (ident);
-
- params = build_tree_list (NULL_TREE,
- my_build_string_pointer
- (IDENTIFIER_LENGTH (ident) + 1,
- IDENTIFIER_POINTER (ident)));
-
- assemble_external (objc_get_class_decl);
- return build_function_call (input_location, objc_get_class_decl, params);
- }
-}
-
-/* For each string section we have a chain which maps identifier nodes
- to decls for the strings. */
-
-static GTY(()) int class_names_idx;
-static GTY(()) int meth_var_names_idx;
-static GTY(()) int meth_var_types_idx;
-
-static tree
-add_objc_string (tree ident, enum string_section section)
-{
- tree *chain, decl, type, string_expr;
- char buf[256];
-
- buf[0] = 0;
- switch (section)
- {
- case class_names:
- chain = &class_names_chain;
- sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
- break;
- case meth_var_names:
- chain = &meth_var_names_chain;
- sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
- break;
- case meth_var_types:
- chain = &meth_var_types_chain;
- sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
- break;
- default:
- gcc_unreachable ();
- }
-
- while (*chain)
- {
- if (TREE_VALUE (*chain) == ident)
- return convert (string_type_node,
- build_unary_op (input_location,
- ADDR_EXPR, TREE_PURPOSE (*chain), 1));
-
- chain = &TREE_CHAIN (*chain);
- }
-
- type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1);
- decl = start_var_decl (type, buf);
- string_expr = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
- IDENTIFIER_POINTER (ident));
- TREE_CONSTANT (decl) = 1;
- finish_var_decl (decl, string_expr);
-
- *chain = tree_cons (decl, ident, NULL_TREE);
-
- return convert (string_type_node, build_unary_op (input_location,
- ADDR_EXPR, decl, 1));
+ return (*runtime.get_class_reference) (ident);
}
void
@@ -4505,9 +3324,9 @@ objc_declare_class (tree ident_list)
if (record)
{
if (TREE_CODE (record) == TYPE_DECL)
- type = DECL_ORIGINAL_TYPE (record) ?
- DECL_ORIGINAL_TYPE (record) :
- TREE_TYPE (record);
+ type = DECL_ORIGINAL_TYPE (record)
+ ? DECL_ORIGINAL_TYPE (record)
+ : TREE_TYPE (record);
if (!TYPE_HAS_OBJC_INFO (type)
|| !TYPE_OBJC_INTERFACE (type))
@@ -4909,7 +3728,7 @@ eq_interface (const void *p1, const void *p2)
return d->id == p2;
}
-static tree
+tree
lookup_interface (tree ident)
{
#ifdef OBJCPLUS
@@ -4997,76 +3816,6 @@ get_class_ivars (tree interface, bool inherited)
return ivar_chain;
}
-
-/* Exception handling constructs. We begin by having the parser do most
- of the work and passing us blocks. What we do next depends on whether
- we're doing "native" exception handling or legacy Darwin setjmp exceptions.
- We abstract all of this in a handful of appropriately named routines. */
-
-/* Stack of open try blocks. */
-
-struct objc_try_context
-{
- struct objc_try_context *outer;
-
- /* Statements (or statement lists) as processed by the parser. */
- tree try_body;
- tree finally_body;
-
- /* Some file position locations. */
- location_t try_locus;
- location_t end_try_locus;
- location_t end_catch_locus;
- location_t finally_locus;
- location_t end_finally_locus;
-
- /* A STATEMENT_LIST of CATCH_EXPRs, appropriate for sticking into op1
- of a TRY_CATCH_EXPR. Even when doing Darwin setjmp. */
- tree catch_list;
-
- /* The CATCH_EXPR of an open @catch clause. */
- tree current_catch;
-
- /* The VAR_DECL holding the Darwin equivalent of __builtin_eh_pointer. */
- tree caught_decl;
- tree stack_decl;
- tree rethrow_decl;
-};
-
-static struct objc_try_context *cur_try_context;
-
-static GTY(()) tree objc_eh_personality_decl;
-
-/* This hook, called via lang_eh_runtime_type, generates a runtime object
- that represents TYPE. For Objective-C, this is just the class name. */
-/* ??? Isn't there a class object or some such? Is it easy to get? */
-
-#ifndef OBJCPLUS
-tree
-objc_eh_runtime_type (tree type)
-{
- /* Use 'ErrorMarkNode' as class name when error_mark_node is found
- to prevent an ICE. Note that we know that the compiler will
- terminate with an error and this 'ErrorMarkNode' class name will
- never be actually used. */
- if (type == error_mark_node)
- return add_objc_string (get_identifier ("ErrorMarkNode"), class_names);
- else
- return add_objc_string (OBJC_TYPE_NAME (TREE_TYPE (type)), class_names);
-}
-
-tree
-objc_eh_personality (void)
-{
- if (!flag_objc_sjlj_exceptions && !objc_eh_personality_decl)
- objc_eh_personality_decl = build_personality_function
- (flag_next_runtime
- ? "objc"
- : "gnu_objc");
- return objc_eh_personality_decl;
-}
-#endif
-
void
objc_maybe_warn_exceptions (location_t loc)
{
@@ -5089,293 +3838,7 @@ objc_maybe_warn_exceptions (location_t loc)
}
}
-/* Build __builtin_eh_pointer, or the moral equivalent. In the case
- of Darwin, we'll arrange for it to be initialized (and associated
- with a binding) later. */
-
-static tree
-objc_build_exc_ptr (void)
-{
- if (flag_objc_sjlj_exceptions)
- {
- tree var = cur_try_context->caught_decl;
- if (!var)
- {
- var = objc_create_temporary_var (objc_object_type, NULL);
- cur_try_context->caught_decl = var;
- }
- return var;
- }
- else
- {
- tree t;
- t = built_in_decls[BUILT_IN_EH_POINTER];
- t = build_call_expr (t, 1, integer_zero_node);
- return fold_convert (objc_object_type, t);
- }
-}
-
-/* Build "objc_exception_try_exit(&_stack)". */
-
-static tree
-next_sjlj_build_try_exit (void)
-{
- tree t;
- t = build_fold_addr_expr_loc (input_location, cur_try_context->stack_decl);
- t = tree_cons (NULL, t, NULL);
- t = build_function_call (input_location,
- objc_exception_try_exit_decl, t);
- return t;
-}
-
-/* Build
- objc_exception_try_enter (&_stack);
- if (_setjmp(&_stack.buf))
- ;
- else
- ;
- Return the COND_EXPR. Note that the THEN and ELSE fields are left
- empty, ready for the caller to fill them in. */
-
-static tree
-next_sjlj_build_enter_and_setjmp (void)
-{
- tree t, enter, sj, cond;
-
- t = build_fold_addr_expr_loc (input_location, cur_try_context->stack_decl);
- t = tree_cons (NULL, t, NULL);
- enter = build_function_call (input_location,
- objc_exception_try_enter_decl, t);
-
- t = objc_build_component_ref (cur_try_context->stack_decl,
- get_identifier ("buf"));
- t = build_fold_addr_expr_loc (input_location, t);
-#ifdef OBJCPLUS
- /* Convert _setjmp argument to type that is expected. */
- if (prototype_p (TREE_TYPE (objc_setjmp_decl)))
- t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
- else
- t = convert (ptr_type_node, t);
-#else
- t = convert (ptr_type_node, t);
-#endif
- t = tree_cons (NULL, t, NULL);
- sj = build_function_call (input_location,
- objc_setjmp_decl, t);
-
- cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
- cond = c_common_truthvalue_conversion (input_location, cond);
-
- return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
-}
-
-/* Build:
-
- DECL = objc_exception_extract(&_stack); */
-
-static tree
-next_sjlj_build_exc_extract (tree decl)
-{
- tree t;
-
- t = build_fold_addr_expr_loc (input_location, cur_try_context->stack_decl);
- t = tree_cons (NULL, t, NULL);
- t = build_function_call (input_location,
- objc_exception_extract_decl, t);
- t = convert (TREE_TYPE (decl), t);
- t = build2 (MODIFY_EXPR, void_type_node, decl, t);
-
- return t;
-}
-
-/* Build
- if (objc_exception_match(obj_get_class(TYPE), _caught)
- BODY
- else if (...)
- ...
- else
- {
- _rethrow = _caught;
- objc_exception_try_exit(&_stack);
- }
- from the sequence of CATCH_EXPRs in the current try context. */
-
-static tree
-next_sjlj_build_catch_list (void)
-{
- tree_stmt_iterator i = tsi_start (cur_try_context->catch_list);
- tree catch_seq, t;
- tree *last = &catch_seq;
- bool saw_id = false;
-
- for (; !tsi_end_p (i); tsi_next (&i))
- {
- tree stmt = tsi_stmt (i);
- tree type = CATCH_TYPES (stmt);
- tree body = CATCH_BODY (stmt);
-
- if (type == NULL)
- {
- *last = body;
- saw_id = true;
- break;
- }
- else
- {
- tree args, cond;
-
- if (type == error_mark_node)
- cond = error_mark_node;
- else
- {
- args = tree_cons (NULL, cur_try_context->caught_decl, NULL);
- t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
- args = tree_cons (NULL, t, args);
- t = build_function_call (input_location,
- objc_exception_match_decl, args);
- cond = c_common_truthvalue_conversion (input_location, t);
- }
- t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
- SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
-
- *last = t;
- last = &COND_EXPR_ELSE (t);
- }
- }
-
- if (!saw_id)
- {
- t = build2 (MODIFY_EXPR, void_type_node, cur_try_context->rethrow_decl,
- cur_try_context->caught_decl);
- SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
- append_to_statement_list (t, last);
-
- t = next_sjlj_build_try_exit ();
- SET_EXPR_LOCATION (t, cur_try_context->end_catch_locus);
- append_to_statement_list (t, last);
- }
-
- return catch_seq;
-}
-
-/* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
- exception handling. We aim to build:
-
- {
- struct _objc_exception_data _stack;
- id _rethrow = 0;
- try
- {
- objc_exception_try_enter (&_stack);
- if (_setjmp(&_stack.buf))
- {
- id _caught = objc_exception_extract(&_stack);
- objc_exception_try_enter (&_stack);
- if (_setjmp(&_stack.buf))
- _rethrow = objc_exception_extract(&_stack);
- else
- CATCH-LIST
- }
- else
- TRY-BLOCK
- }
- finally
- {
- if (!_rethrow)
- objc_exception_try_exit(&_stack);
- FINALLY-BLOCK
- if (_rethrow)
- objc_exception_throw(_rethrow);
- }
- }
-
- If CATCH-LIST is empty, we can omit all of the block containing
- "_caught" except for the setting of _rethrow. Note the use of
- a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
- but handles goto and other exits from the block. */
-
-static tree
-next_sjlj_build_try_catch_finally (void)
-{
- tree rethrow_decl, stack_decl, t;
- tree catch_seq, try_fin, bind;
-
- /* Create the declarations involved. */
- t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
- stack_decl = objc_create_temporary_var (t, NULL);
- cur_try_context->stack_decl = stack_decl;
-
- rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
- cur_try_context->rethrow_decl = rethrow_decl;
- TREE_CHAIN (rethrow_decl) = stack_decl;
-
- /* Build the outermost variable binding level. */
- bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
- SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
- TREE_SIDE_EFFECTS (bind) = 1;
-
- /* Initialize rethrow_decl. */
- t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
- convert (objc_object_type, null_pointer_node));
- SET_EXPR_LOCATION (t, cur_try_context->try_locus);
- append_to_statement_list (t, &BIND_EXPR_BODY (bind));
-
- /* Build the outermost TRY_FINALLY_EXPR. */
- try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
- SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
- TREE_SIDE_EFFECTS (try_fin) = 1;
- append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
-
- /* Create the complete catch sequence. */
- if (cur_try_context->catch_list)
- {
- tree caught_decl = objc_build_exc_ptr ();
- catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
- TREE_SIDE_EFFECTS (catch_seq) = 1;
-
- t = next_sjlj_build_exc_extract (caught_decl);
- append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
-
- t = next_sjlj_build_enter_and_setjmp ();
- COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (rethrow_decl);
- COND_EXPR_ELSE (t) = next_sjlj_build_catch_list ();
- append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
- }
- else
- catch_seq = next_sjlj_build_exc_extract (rethrow_decl);
- SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
-
- /* Build the main register-and-try if statement. */
- t = next_sjlj_build_enter_and_setjmp ();
- SET_EXPR_LOCATION (t, cur_try_context->try_locus);
- COND_EXPR_THEN (t) = catch_seq;
- COND_EXPR_ELSE (t) = cur_try_context->try_body;
- TREE_OPERAND (try_fin, 0) = t;
-
- /* Build the complete FINALLY statement list. */
- t = next_sjlj_build_try_exit ();
- t = build_stmt (input_location, COND_EXPR,
- c_common_truthvalue_conversion
- (input_location, rethrow_decl),
- NULL, t);
- SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
- append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
-
- append_to_statement_list (cur_try_context->finally_body,
- &TREE_OPERAND (try_fin, 1));
-
- t = tree_cons (NULL, rethrow_decl, NULL);
- t = build_function_call (input_location,
- objc_exception_throw_decl, t);
- t = build_stmt (input_location, COND_EXPR,
- c_common_truthvalue_conversion (input_location,
- rethrow_decl),
- t, NULL);
- SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
- append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
-
- return bind;
-}
+static struct objc_try_context *cur_try_context;
/* Called just after parsing the @try and its associated BODY. We now
must prepare for the tricky bits -- handling the catches and finally. */
@@ -5407,6 +3870,7 @@ void
objc_begin_catch_clause (tree decl)
{
tree compound, type, t;
+ bool ellipsis = false;
/* Begin a new scope that the entire catch clause will live in. */
compound = c_begin_compound_stmt (true);
@@ -5422,6 +3886,9 @@ objc_begin_catch_clause (tree decl)
type 'id' and use it. */
decl = objc_create_temporary_var (objc_object_type, "__objc_generic_catch_var");
DECL_SOURCE_LOCATION (decl) = input_location;
+ /* ... but allow the runtime to differentiate between ellipsis and the
+ case of @catch (id xyz). */
+ ellipsis = true;
}
else
{
@@ -5441,13 +3908,13 @@ objc_begin_catch_clause (tree decl)
type = TREE_TYPE (decl);
}
- /* Verify that the type of the catch is valid. It must be a pointer
- to an Objective-C class, or "id" (which is catch-all). */
- if (type == error_mark_node)
- {
- ;/* Just keep going. */
- }
- else if (!objc_type_valid_for_messaging (type, false))
+ /* Verify that the type of the catch is valid. It must be a pointer
+ to an Objective-C class, or "id" (which is catch-all). */
+ if (type == error_mark_node)
+ {
+ ;/* Just keep going. */
+ }
+ else if (!objc_type_valid_for_messaging (type, false))
{
error ("@catch parameter is not a known Objective-C class type");
type = error_mark_node;
@@ -5458,8 +3925,10 @@ objc_begin_catch_clause (tree decl)
error ("@catch parameter can not be protocol-qualified");
type = error_mark_node;
}
- else if (objc_is_object_id (TREE_TYPE (type)))
- type = NULL;
+ else if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
+ /* @catch (id xyz) or @catch (...) but we note this for runtimes that
+ identify 'id'. */
+ ;
else
{
/* If 'type' was built using typedefs, we need to get rid of
@@ -5508,15 +3977,7 @@ objc_begin_catch_clause (tree decl)
}
}
- /* Record the data for the catch in the try context so that we can
- finalize it later. */
- t = build_stmt (input_location, CATCH_EXPR, type, compound);
- cur_try_context->current_catch = t;
-
- /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
- t = objc_build_exc_ptr ();
- t = convert (TREE_TYPE (decl), t);
- t = build2 (MODIFY_EXPR, void_type_node, decl, t);
+ t = (*runtime.begin_catch) (&cur_try_context, type, decl, compound, ellipsis);
add_stmt (t);
}
@@ -5531,7 +3992,8 @@ objc_finish_catch_clause (void)
cur_try_context->end_catch_locus = input_location;
CATCH_BODY (c) = c_end_compound_stmt (input_location, CATCH_BODY (c), 1);
- append_to_statement_list (c, &cur_try_context->catch_list);
+
+ (*runtime.finish_catch) (&cur_try_context, c);
}
/* Called after parsing a @finally clause and its associated BODY.
@@ -5556,34 +4018,7 @@ objc_finish_try_stmt (void)
if (c->catch_list == NULL && c->finally_body == NULL)
error ("%<@try%> without %<@catch%> or %<@finally%>");
- /* If we're doing Darwin setjmp exceptions, build the big nasty. */
- if (flag_objc_sjlj_exceptions)
- {
- bool save = in_late_binary_op;
- in_late_binary_op = true;
- if (!cur_try_context->finally_body)
- {
- cur_try_context->finally_locus = input_location;
- cur_try_context->end_finally_locus = input_location;
- }
- stmt = next_sjlj_build_try_catch_finally ();
- in_late_binary_op = save;
- }
- else
- {
- /* Otherwise, nest the CATCH inside a FINALLY. */
- stmt = c->try_body;
- if (c->catch_list)
- {
- stmt = build_stmt (input_location, TRY_CATCH_EXPR, stmt, c->catch_list);
- SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
- }
- if (c->finally_body)
- {
- stmt = build_stmt (input_location, TRY_FINALLY_EXPR, stmt, c->finally_body);
- SET_EXPR_LOCATION (stmt, cur_try_context->try_locus);
- }
- }
+ stmt = (*runtime.finish_try_stmt) (&cur_try_context);
add_stmt (stmt);
cur_try_context = c->outer;
@@ -5594,10 +4029,14 @@ objc_finish_try_stmt (void)
tree
objc_build_throw_stmt (location_t loc, tree throw_expr)
{
- tree args;
+ bool rethrown = false;
objc_maybe_warn_exceptions (loc);
+ /* Don't waste time trying to build something if we're already dead. */
+ if (throw_expr == error_mark_node)
+ return error_mark_node;
+
if (throw_expr == NULL)
{
/* If we're not inside a @catch block, there is no "current
@@ -5611,9 +4050,10 @@ objc_build_throw_stmt (location_t loc, tree throw_expr)
/* Otherwise the object is still sitting in the EXC_PTR_EXPR
value that we get from the runtime. */
- throw_expr = objc_build_exc_ptr ();
+ throw_expr = (*runtime.build_exc_ptr) (&cur_try_context);
+ rethrown = true;
}
- else if (throw_expr != error_mark_node)
+ else
{
if (!objc_type_valid_for_messaging (TREE_TYPE (throw_expr), true))
{
@@ -5622,11 +4062,7 @@ objc_build_throw_stmt (location_t loc, tree throw_expr)
}
}
- /* A throw is just a call to the runtime throw function with the
- object as a parameter. */
- args = tree_cons (NULL, throw_expr, NULL);
- return add_stmt (build_function_call (loc,
- objc_exception_throw_decl, args));
+ return (*runtime.build_throw_stmt) (loc, throw_expr, rethrown);
}
tree
@@ -5685,143 +4121,6 @@ objc_build_synchronized (location_t start_locus, tree object_expr, tree body)
}
}
-
-/* Predefine the following data type:
-
- struct _objc_exception_data
- {
- int buf[OBJC_JBLEN];
- void *pointers[4];
- }; */
-
-/* The following yuckiness should prevent users from having to #include
- <setjmp.h> in their code... */
-
-/* Define to a harmless positive value so the below code doesn't die. */
-#ifndef OBJC_JBLEN
-#define OBJC_JBLEN 18
-#endif
-
-static void
-build_next_objc_exception_stuff (void)
-{
- tree decls, temp_type, *chain = NULL;
-
- objc_exception_data_template
- = objc_start_struct (get_identifier (UTAG_EXCDATA));
-
- /* int buf[OBJC_JBLEN]; */
-
- temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
- decls = add_field_decl (temp_type, "buf", &chain);
-
- /* void *pointers[4]; */
-
- temp_type = build_sized_array_type (ptr_type_node, 4);
- add_field_decl (temp_type, "pointers", &chain);
-
- objc_finish_struct (objc_exception_data_template, decls);
-
- /* int _setjmp(...); */
- /* If the user includes <setjmp.h>, this shall be superseded by
- 'int _setjmp(jmp_buf);' */
- temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
- objc_setjmp_decl
- = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
-
- /* id objc_exception_extract(struct _objc_exception_data *); */
- temp_type
- = build_function_type_list (objc_object_type,
- build_pointer_type (objc_exception_data_template),
- NULL_TREE);
- objc_exception_extract_decl
- = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
- NULL_TREE);
- /* void objc_exception_try_enter(struct _objc_exception_data *); */
- /* void objc_exception_try_exit(struct _objc_exception_data *); */
- temp_type
- = build_function_type_list (void_type_node,
- build_pointer_type (objc_exception_data_template),
- NULL_TREE);
- objc_exception_try_enter_decl
- = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
- NULL_TREE);
- objc_exception_try_exit_decl
- = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
- NULL_TREE);
-
- /* int objc_exception_match(id, id); */
- temp_type
- = build_function_type_list (integer_type_node,
- objc_object_type, objc_object_type, NULL_TREE);
- objc_exception_match_decl
- = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
- NULL_TREE);
-
- /* id objc_assign_ivar (id, id, unsigned int); */
- /* id objc_assign_ivar_Fast (id, id, unsigned int)
- __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
- temp_type
- = build_function_type_list (objc_object_type,
- objc_object_type,
- objc_object_type,
- unsigned_type_node,
- NULL_TREE);
- objc_assign_ivar_decl
- = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
-#ifdef OFFS_ASSIGNIVAR_FAST
- objc_assign_ivar_fast_decl
- = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
- NOT_BUILT_IN, NULL, NULL_TREE);
- DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
- = tree_cons (get_identifier ("hard_coded_address"),
- build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
- NULL_TREE);
-#else
- /* Default to slower ivar method. */
- objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
-#endif
-
- /* id objc_assign_global (id, id *); */
- /* id objc_assign_strongCast (id, id *); */
- temp_type = build_function_type_list (objc_object_type,
- objc_object_type,
- build_pointer_type (objc_object_type),
- NULL_TREE);
- objc_assign_global_decl
- = add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
- NULL_TREE);
- objc_assign_strong_cast_decl
- = add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
- NULL_TREE);
-}
-
-static void
-build_objc_exception_stuff (void)
-{
- tree noreturn_list, nothrow_list, temp_type;
-
- noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
- nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
-
- /* void objc_exception_throw(id) __attribute__((noreturn)); */
- /* void objc_sync_enter(id); */
- /* void objc_sync_exit(id); */
- temp_type = build_function_type_list (void_type_node,
- objc_object_type,
- NULL_TREE);
- objc_exception_throw_decl
- = add_builtin_function (TAG_EXCEPTIONTHROW, temp_type, 0, NOT_BUILT_IN, NULL,
- noreturn_list);
- objc_sync_enter_decl
- = add_builtin_function (TAG_SYNCENTER, temp_type, 0, NOT_BUILT_IN,
- NULL, nothrow_list);
- objc_sync_exit_decl
- = add_builtin_function (TAG_SYNCEXIT, temp_type, 0, NOT_BUILT_IN,
- NULL, nothrow_list);
-}
-
/* Construct a C struct corresponding to ObjC class CLASS, with the same
name as the class:
@@ -5847,120 +4146,13 @@ build_private_template (tree klass)
/* Copy the attributes from the class to the type. */
if (TREE_DEPRECATED (klass))
TREE_DEPRECATED (record) = 1;
- }
-}
-
-/* Begin code generation for protocols... */
-
-/* struct _objc_protocol {
- struct _objc_class *isa;
- char *protocol_name;
- struct _objc_protocol **protocol_list;
- struct _objc__method_prototype_list *instance_methods;
- struct _objc__method_prototype_list *class_methods;
- }; */
-
-static void
-build_protocol_template (void)
-{
- tree ptype, decls, *chain = NULL;
-
- objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
-
- /* struct _objc_class *isa; */
- ptype = build_pointer_type (xref_tag (RECORD_TYPE,
- get_identifier (UTAG_CLASS)));
- decls = add_field_decl (ptype, "isa", &chain);
- /* char *protocol_name; */
- add_field_decl (string_type_node, "protocol_name", &chain);
-
- /* struct _objc_protocol **protocol_list; */
- ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
- add_field_decl (ptype, "protocol_list", &chain);
-
- /* struct _objc__method_prototype_list *instance_methods; */
- add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
-
- /* struct _objc__method_prototype_list *class_methods; */
- add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
-
- objc_finish_struct (objc_protocol_template, decls);
-}
-
-static tree
-build_descriptor_table_initializer (tree type, tree entries)
-{
- VEC(constructor_elt,gc) *inits = NULL;
-
- do
- {
- VEC(constructor_elt,gc) *elts = NULL;
-
- CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
- build_selector (METHOD_SEL_NAME (entries)));
- CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
- add_objc_string (METHOD_ENCODING (entries),
- meth_var_types));
-
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
- objc_build_constructor (type, elts));
-
- entries = DECL_CHAIN (entries);
+ if (CLASS_HAS_EXCEPTION_ATTR (klass))
+ CLASS_HAS_EXCEPTION_ATTR (record) = 1;
}
- while (entries);
-
- return objc_build_constructor (build_array_type (type, 0), inits);
-}
-
-/* struct objc_method_prototype_list {
- int count;
- struct objc_method_prototype {
- SEL name;
- char *types;
- } list[1];
- }; */
-
-static tree
-build_method_prototype_list_template (tree list_type, int size)
-{
- tree objc_ivar_list_record;
- tree array_type, decls, *chain = NULL;
-
- /* Generate an unnamed struct definition. */
-
- objc_ivar_list_record = objc_start_struct (NULL_TREE);
-
- /* int method_count; */
- decls = add_field_decl (integer_type_node, "method_count", &chain);
-
- /* struct objc_method method_list[]; */
- array_type = build_sized_array_type (list_type, size);
- add_field_decl (array_type, "method_list", &chain);
-
- objc_finish_struct (objc_ivar_list_record, decls);
-
- return objc_ivar_list_record;
}
-static tree
-build_method_prototype_template (void)
-{
- tree proto_record;
- tree decls, *chain = NULL;
-
- proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE));
-
- /* SEL _cmd; */
- decls = add_field_decl (objc_selector_type, "_cmd", &chain);
-
- /* char *method_types; */
- add_field_decl (string_type_node, "method_types", &chain);
-
- objc_finish_struct (proto_record, decls);
-
- return proto_record;
-}
+/* Begin code generation for protocols... */
static tree
objc_method_parm_type (tree type)
@@ -5992,7 +4184,8 @@ objc_encoded_type_size (tree type)
The format is described in gcc/doc/objc.texi, section 'Method
signatures'.
*/
-static tree
+
+tree
encode_method_prototype (tree method_decl)
{
tree parms;
@@ -6063,96 +4256,6 @@ encode_method_prototype (tree method_decl)
return result;
}
-static tree
-generate_descriptor_table (tree type, const char *name, int size, tree list,
- tree proto)
-{
- tree decl;
- VEC(constructor_elt,gc) *v = NULL;
-
- decl = start_var_decl (type, synth_id_with_class_suffix (name, proto));
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, list);
-
- finish_var_decl (decl, objc_build_constructor (type, v));
-
- return decl;
-}
-
-static void
-generate_method_descriptors (tree protocol)
-{
- tree initlist, chain, method_list_template;
- int size;
-
- if (!objc_method_prototype_template)
- objc_method_prototype_template = build_method_prototype_template ();
-
- chain = PROTOCOL_CLS_METHODS (protocol);
- if (chain)
- {
- size = list_length (chain);
-
- method_list_template
- = build_method_prototype_list_template (objc_method_prototype_template,
- size);
-
- initlist
- = build_descriptor_table_initializer (objc_method_prototype_template,
- chain);
-
- UOBJC_CLASS_METHODS_decl
- = generate_descriptor_table (method_list_template,
- "_OBJC_PROTOCOL_CLASS_METHODS",
- size, initlist, protocol);
- }
- else
- UOBJC_CLASS_METHODS_decl = 0;
-
- chain = PROTOCOL_NST_METHODS (protocol);
- if (chain)
- {
- size = list_length (chain);
-
- method_list_template
- = build_method_prototype_list_template (objc_method_prototype_template,
- size);
- initlist
- = build_descriptor_table_initializer (objc_method_prototype_template,
- chain);
-
- UOBJC_INSTANCE_METHODS_decl
- = generate_descriptor_table (method_list_template,
- "_OBJC_PROTOCOL_INSTANCE_METHODS",
- size, initlist, protocol);
- }
- else
- UOBJC_INSTANCE_METHODS_decl = 0;
-}
-
-static void
-generate_protocol_references (tree plist)
-{
- tree lproto;
-
- /* Forward declare protocols referenced. */
- for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
- {
- tree proto = TREE_VALUE (lproto);
-
- if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
- && PROTOCOL_NAME (proto))
- {
- if (! PROTOCOL_FORWARD_DECL (proto))
- build_protocol_reference (proto);
-
- if (PROTOCOL_LIST (proto))
- generate_protocol_references (PROTOCOL_LIST (proto));
- }
- }
-}
-
/* Generate either '- .cxx_construct' or '- .cxx_destruct' for the
current class. */
#ifdef OBJCPLUS
@@ -6282,346 +4385,11 @@ objc_generate_cxx_cdtors (void)
/* The 'imp_list' variable points at an imp_entry record for the current
@implementation. Record the existence of '- .cxx_construct' and/or
'- .cxx_destruct' methods therein; it will be included in the
- metadata for the class. */
- if (flag_next_runtime)
- imp_list->has_cxx_cdtors = (need_ctor || need_dtor);
+ metadata for the class if the runtime needs it. */
+ imp_list->has_cxx_cdtors = (need_ctor || need_dtor);
}
#endif
-/* For each protocol which was referenced either from a @protocol()
- expression, or because a class/category implements it (then a
- pointer to the protocol is stored in the struct describing the
- class/category), we create a statically allocated instance of the
- Protocol class. The code is written in such a way as to generate
- as few Protocol objects as possible; we generate a unique Protocol
- instance for each protocol, and we don't generate a Protocol
- instance if the protocol is never referenced (either from a
- @protocol() or from a class/category implementation). These
- statically allocated objects can be referred to via the static
- (that is, private to this module) symbols _OBJC_PROTOCOL_n.
-
- The statically allocated Protocol objects that we generate here
- need to be fixed up at runtime in order to be used: the 'isa'
- pointer of the objects need to be set up to point to the 'Protocol'
- class, as known at runtime.
-
- The NeXT runtime fixes up all protocols at program startup time,
- before main() is entered. It uses a low-level trick to look up all
- those symbols, then loops on them and fixes them up.
-
- The GNU runtime as well fixes up all protocols before user code
- from the module is executed; it requires pointers to those symbols
- to be put in the objc_symtab (which is then passed as argument to
- the function __objc_exec_class() which the compiler sets up to be
- executed automatically when the module is loaded); setup of those
- Protocol objects happen in two ways in the GNU runtime: all
- Protocol objects referred to by a class or category implementation
- are fixed up when the class/category is loaded; all Protocol
- objects referred to by a @protocol() expression are added by the
- compiler to the list of statically allocated instances to fixup
- (the same list holding the statically allocated constant string
- objects). Because, as explained above, the compiler generates as
- few Protocol objects as possible, some Protocol object might end up
- being referenced multiple times when compiled with the GNU runtime,
- and end up being fixed up multiple times at runtime initialization.
- But that doesn't hurt, it's just a little inefficient. */
-
-static void
-generate_protocols (void)
-{
- tree p, encoding;
- tree decl;
- tree initlist, protocol_name_expr, refs_decl, refs_expr;
-
- /* If a protocol was directly referenced, pull in indirect references. */
- for (p = protocol_chain; p; p = TREE_CHAIN (p))
- if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
- generate_protocol_references (PROTOCOL_LIST (p));
-
- for (p = protocol_chain; p; p = TREE_CHAIN (p))
- {
- tree nst_methods = PROTOCOL_NST_METHODS (p);
- tree cls_methods = PROTOCOL_CLS_METHODS (p);
-
- /* If protocol wasn't referenced, don't generate any code. */
- decl = PROTOCOL_FORWARD_DECL (p);
-
- if (!decl)
- continue;
-
- /* Make sure we link in the Protocol class. */
- add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
-
- while (nst_methods)
- {
- if (! METHOD_ENCODING (nst_methods))
- {
- encoding = encode_method_prototype (nst_methods);
- METHOD_ENCODING (nst_methods) = encoding;
- }
- nst_methods = DECL_CHAIN (nst_methods);
- }
-
- while (cls_methods)
- {
- if (! METHOD_ENCODING (cls_methods))
- {
- encoding = encode_method_prototype (cls_methods);
- METHOD_ENCODING (cls_methods) = encoding;
- }
-
- cls_methods = DECL_CHAIN (cls_methods);
- }
- generate_method_descriptors (p);
-
- if (PROTOCOL_LIST (p))
- refs_decl = generate_protocol_list (p);
- else
- refs_decl = 0;
-
- /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
- protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
-
- if (refs_decl)
- refs_expr = convert (build_pointer_type (build_pointer_type
- (objc_protocol_template)),
- build_unary_op (input_location,
- ADDR_EXPR, refs_decl, 0));
- else
- refs_expr = build_int_cst (NULL_TREE, 0);
-
- /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
- by generate_method_descriptors, which is called above. */
- initlist = build_protocol_initializer (TREE_TYPE (decl),
- protocol_name_expr, refs_expr,
- UOBJC_INSTANCE_METHODS_decl,
- UOBJC_CLASS_METHODS_decl);
- finish_var_decl (decl, initlist);
- }
-}
-
-static tree
-build_protocol_initializer (tree type, tree protocol_name,
- tree protocol_list, tree instance_methods,
- tree class_methods)
-{
- tree expr;
- tree cast_type = build_pointer_type
- (xref_tag (RECORD_TYPE,
- get_identifier (UTAG_CLASS)));
- VEC(constructor_elt,gc) *inits = NULL;
-
- /* Filling the "isa" in with one allows the runtime system to
- detect that the version change...should remove before final release. */
-
- expr = build_int_cst (cast_type, PROTOCOL_VERSION);
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
-
- if (!instance_methods)
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, 0));
- else
- {
- expr = convert (objc_method_proto_list_ptr,
- build_unary_op (input_location,
- ADDR_EXPR, instance_methods, 0));
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
- }
-
- if (!class_methods)
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, 0));
- else
- {
- expr = convert (objc_method_proto_list_ptr,
- build_unary_op (input_location,
- ADDR_EXPR, class_methods, 0));
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
- }
-
- return objc_build_constructor (type, inits);
-}
-
-/* struct _objc_category {
- char *category_name;
- char *class_name;
- struct _objc_method_list *instance_methods;
- struct _objc_method_list *class_methods;
- struct _objc_protocol_list *protocols;
- }; */
-
-static void
-build_category_template (void)
-{
- tree ptype, decls, *chain = NULL;
-
- objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
-
- /* char *category_name; */
- decls = add_field_decl (string_type_node, "category_name", &chain);
-
- /* char *class_name; */
- add_field_decl (string_type_node, "class_name", &chain);
-
- /* struct _objc_method_list *instance_methods; */
- add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
-
- /* struct _objc_method_list *class_methods; */
- add_field_decl (objc_method_list_ptr, "class_methods", &chain);
-
- /* struct _objc_protocol **protocol_list; */
- ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
- add_field_decl (ptype, "protocol_list", &chain);
-
- objc_finish_struct (objc_category_template, decls);
-}
-
-/* struct _objc_selector {
- SEL sel_id;
- char *sel_type;
- }; */
-
-static void
-build_selector_template (void)
-{
- tree decls, *chain = NULL;
-
- objc_selector_template = objc_start_struct (get_identifier (UTAG_SELECTOR));
-
- /* SEL sel_id; */
- decls = add_field_decl (objc_selector_type, "sel_id", &chain);
-
- /* char *sel_type; */
- add_field_decl (string_type_node, "sel_type", &chain);
-
- objc_finish_struct (objc_selector_template, decls);
-}
-
-/* struct _objc_class {
- struct _objc_class *isa;
- struct _objc_class *super_class;
- char *name;
- long version;
- long info;
- long instance_size;
- struct _objc_ivar_list *ivars;
- struct _objc_method_list *methods;
- #ifdef __NEXT_RUNTIME__
- struct objc_cache *cache;
- #else
- struct sarray *dtable;
- struct _objc_class *subclass_list;
- struct _objc_class *sibling_class;
- #endif
- struct _objc_protocol_list *protocols;
- #ifdef __NEXT_RUNTIME__
- void *sel_id;
- #endif
- void *gc_object_type;
- }; */
-
-/* NB: The 'sel_id' and 'gc_object_type' fields are not being used by
- the NeXT/Apple runtime; still, the compiler must generate them to
- maintain backward binary compatibility (and to allow for future
- expansion). */
-
-static void
-build_class_template (void)
-{
- tree ptype, decls, *chain = NULL;
-
- objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
-
- /* struct _objc_class *isa; */
- decls = add_field_decl (build_pointer_type (objc_class_template),
- "isa", &chain);
-
- /* struct _objc_class *super_class; */
- add_field_decl (build_pointer_type (objc_class_template),
- "super_class", &chain);
-
- /* char *name; */
- add_field_decl (string_type_node, "name", &chain);
-
- /* long version; */
- add_field_decl (long_integer_type_node, "version", &chain);
-
- /* long info; */
- add_field_decl (long_integer_type_node, "info", &chain);
-
- /* long instance_size; */
- add_field_decl (long_integer_type_node, "instance_size", &chain);
-
- /* struct _objc_ivar_list *ivars; */
- add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
-
- /* struct _objc_method_list *methods; */
- add_field_decl (objc_method_list_ptr, "methods", &chain);
-
- if (flag_next_runtime)
- {
- /* struct objc_cache *cache; */
- ptype = build_pointer_type (xref_tag (RECORD_TYPE,
- get_identifier ("objc_cache")));
- add_field_decl (ptype, "cache", &chain);
- }
- else
- {
- /* struct sarray *dtable; */
- ptype = build_pointer_type(xref_tag (RECORD_TYPE,
- get_identifier ("sarray")));
- add_field_decl (ptype, "dtable", &chain);
-
- /* struct objc_class *subclass_list; */
- ptype = build_pointer_type (objc_class_template);
- add_field_decl (ptype, "subclass_list", &chain);
-
- /* struct objc_class *sibling_class; */
- ptype = build_pointer_type (objc_class_template);
- add_field_decl (ptype, "sibling_class", &chain);
- }
-
- /* struct _objc_protocol **protocol_list; */
- ptype = build_pointer_type (build_pointer_type
- (xref_tag (RECORD_TYPE,
- get_identifier (UTAG_PROTOCOL))));
- add_field_decl (ptype, "protocol_list", &chain);
-
- if (flag_next_runtime)
- {
- /* void *sel_id; */
- add_field_decl (build_pointer_type (void_type_node), "sel_id", &chain);
- }
-
- /* void *gc_object_type; */
- add_field_decl (build_pointer_type (void_type_node),
- "gc_object_type", &chain);
-
- objc_finish_struct (objc_class_template, decls);
-}
-
-/* Generate appropriate forward declarations for an implementation. */
-
-static void
-synth_forward_declarations (void)
-{
- tree an_id;
-
- /* static struct objc_class _OBJC_CLASS_<my_name>; */
- UOBJC_CLASS_decl = build_metadata_decl ("_OBJC_CLASS",
- objc_class_template);
-
- /* static struct objc_class _OBJC_METACLASS_<my_name>; */
- UOBJC_METACLASS_decl = build_metadata_decl ("_OBJC_METACLASS",
- objc_class_template);
-
- /* Pre-build the following entities - for speed/convenience. */
-
- an_id = get_identifier ("super_class");
- ucls_super_ref = objc_build_component_ref (UOBJC_CLASS_decl, an_id);
- uucls_super_ref = objc_build_component_ref (UOBJC_METACLASS_decl, an_id);
-}
-
static void
error_with_ivar (const char *message, tree decl)
{
@@ -6685,322 +4453,6 @@ check_ivars (tree inter, tree imp)
}
}
-/* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
- This needs to be done just once per compilation. */
-
-/* struct _objc_super {
- struct _objc_object *self;
- struct _objc_class *super_class;
- }; */
-
-static void
-build_super_template (void)
-{
- tree decls, *chain = NULL;
-
- objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
-
- /* struct _objc_object *self; */
- decls = add_field_decl (objc_object_type, "self", &chain);
-
- /* struct _objc_class *super_class; */
- add_field_decl (build_pointer_type (objc_class_template),
- "super_class", &chain);
-
- objc_finish_struct (objc_super_template, decls);
-}
-
-/* struct _objc_ivar {
- char *ivar_name;
- char *ivar_type;
- int ivar_offset;
- }; */
-
-static tree
-build_ivar_template (void)
-{
- tree objc_ivar_id, objc_ivar_record;
- tree decls, *chain = NULL;
-
- objc_ivar_id = get_identifier (UTAG_IVAR);
- objc_ivar_record = objc_start_struct (objc_ivar_id);
-
- /* char *ivar_name; */
- decls = add_field_decl (string_type_node, "ivar_name", &chain);
-
- /* char *ivar_type; */
- add_field_decl (string_type_node, "ivar_type", &chain);
-
- /* int ivar_offset; */
- add_field_decl (integer_type_node, "ivar_offset", &chain);
-
- objc_finish_struct (objc_ivar_record, decls);
-
- return objc_ivar_record;
-}
-
-/* struct {
- int ivar_count;
- struct objc_ivar ivar_list[ivar_count];
- }; */
-
-static tree
-build_ivar_list_template (tree list_type, int size)
-{
- tree objc_ivar_list_record;
- tree array_type, decls, *chain = NULL;
-
- objc_ivar_list_record = objc_start_struct (NULL_TREE);
-
- /* int ivar_count; */
- decls = add_field_decl (integer_type_node, "ivar_count", &chain);
-
- /* struct objc_ivar ivar_list[]; */
- array_type = build_sized_array_type (list_type, size);
- add_field_decl (array_type, "ivar_list", &chain);
-
- objc_finish_struct (objc_ivar_list_record, decls);
-
- return objc_ivar_list_record;
-}
-
-/* struct {
- struct _objc__method_prototype_list *method_next;
- int method_count;
- struct objc_method method_list[method_count];
- }; */
-
-static tree
-build_method_list_template (tree list_type, int size)
-{
- tree objc_ivar_list_record;
- tree array_type, decls, *chain = NULL;
-
- objc_ivar_list_record = objc_start_struct (NULL_TREE);
-
- /* struct _objc__method_prototype_list *method_next; */
- decls = add_field_decl (objc_method_proto_list_ptr, "method_next", &chain);
-
- /* int method_count; */
- add_field_decl (integer_type_node, "method_count", &chain);
-
- /* struct objc_method method_list[]; */
- array_type = build_sized_array_type (list_type, size);
- add_field_decl (array_type, "method_list", &chain);
-
- objc_finish_struct (objc_ivar_list_record, decls);
-
- return objc_ivar_list_record;
-}
-
-static tree
-build_ivar_list_initializer (tree type, tree field_decl)
-{
- VEC(constructor_elt,gc) *inits = NULL;
-
- do
- {
- VEC(constructor_elt,gc) *ivar = NULL;
- tree id;
-
- /* Set name. */
- if (DECL_NAME (field_decl))
- CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
- add_objc_string (DECL_NAME (field_decl),
- meth_var_names));
- else
- /* Unnamed bit-field ivar (yuck). */
- CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, build_int_cst (NULL_TREE, 0));
-
- /* Set type. */
- encode_field_decl (field_decl,
- obstack_object_size (&util_obstack),
- OBJC_ENCODE_DONT_INLINE_DEFS);
-
- /* Null terminate string. */
- obstack_1grow (&util_obstack, 0);
- id = add_objc_string (get_identifier (XOBFINISH (&util_obstack, char *)),
- meth_var_types);
- CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
- obstack_free (&util_obstack, util_firstobj);
-
- /* Set offset. */
- CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl));
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
- objc_build_constructor (type, ivar));
- do
- field_decl = DECL_CHAIN (field_decl);
- while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
- }
- while (field_decl);
-
- return objc_build_constructor (build_array_type (type, 0), inits);
-}
-
-static tree
-generate_ivars_list (tree type, const char *name, int size, tree list)
-{
- tree decl;
- VEC(constructor_elt,gc) *inits = NULL;
-
- decl = start_var_decl (type, synth_id_with_class_suffix
- (name, objc_implementation_context));
-
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, list);
-
- finish_var_decl (decl,
- objc_build_constructor (TREE_TYPE (decl), inits));
-
- return decl;
-}
-
-/* Count only the fields occurring in T. */
-
-static int
-ivar_list_length (tree t)
-{
- int count = 0;
-
- for (; t; t = DECL_CHAIN (t))
- if (TREE_CODE (t) == FIELD_DECL)
- ++count;
-
- return count;
-}
-
-static void
-generate_ivar_lists (void)
-{
- tree initlist, ivar_list_template, chain;
- int size;
-
- generating_instance_variables = 1;
-
- if (!objc_ivar_template)
- objc_ivar_template = build_ivar_template ();
-
- /* Only generate class variables for the root of the inheritance
- hierarchy since these will be the same for every class. */
-
- if (CLASS_SUPER_NAME (implementation_template) == NULL_TREE
- && (chain = TYPE_FIELDS (objc_class_template)))
- {
- size = ivar_list_length (chain);
-
- ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
- initlist = build_ivar_list_initializer (objc_ivar_template, chain);
-
- UOBJC_CLASS_VARIABLES_decl
- = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
- size, initlist);
- }
- else
- UOBJC_CLASS_VARIABLES_decl = 0;
-
- chain = CLASS_IVARS (implementation_template);
- if (chain)
- {
- size = ivar_list_length (chain);
- ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
- initlist = build_ivar_list_initializer (objc_ivar_template, chain);
-
- UOBJC_INSTANCE_VARIABLES_decl
- = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
- size, initlist);
- }
- else
- UOBJC_INSTANCE_VARIABLES_decl = 0;
-
- generating_instance_variables = 0;
-}
-
-static tree
-build_dispatch_table_initializer (tree type, tree entries)
-{
- VEC(constructor_elt,gc) *inits = NULL;
-
- do
- {
- VEC(constructor_elt,gc) *elems = NULL;
- tree expr;
-
- CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
- build_selector (METHOD_SEL_NAME (entries)));
-
- /* Generate the method encoding if we don't have one already. */
- if (! METHOD_ENCODING (entries))
- METHOD_ENCODING (entries) =
- encode_method_prototype (entries);
-
- CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
- add_objc_string (METHOD_ENCODING (entries),
- meth_var_types));
-
- expr = convert (ptr_type_node,
- build_unary_op (input_location, ADDR_EXPR,
- METHOD_DEFINITION (entries), 1));
- CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, expr);
-
- CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
- objc_build_constructor (type, elems));
-
- entries = DECL_CHAIN (entries);
- }
- while (entries);
-
- return objc_build_constructor (build_array_type (type, 0), inits);
-}
-
-/* To accomplish method prototyping without generating all kinds of
- inane warnings, the definition of the dispatch table entries were
- changed from:
-
- struct objc_method { SEL _cmd; ...; id (*_imp)(); };
- to:
- struct objc_method { SEL _cmd; ...; void *_imp; }; */
-
-static tree
-build_method_template (void)
-{
- tree _SLT_record;
- tree decls, *chain = NULL;
-
- _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD));
-
- /* SEL _cmd; */
- decls = add_field_decl (objc_selector_type, "_cmd", &chain);
-
- /* char *method_types; */
- add_field_decl (string_type_node, "method_types", &chain);
-
- /* void *_imp; */
- add_field_decl (build_pointer_type (void_type_node), "_imp", &chain);
-
- objc_finish_struct (_SLT_record, decls);
-
- return _SLT_record;
-}
-
-
-static tree
-generate_dispatch_table (tree type, const char *name, int size, tree list)
-{
- tree decl;
- VEC(constructor_elt,gc) *v = NULL;
-
- decl = start_var_decl (type, synth_id_with_class_suffix
- (name, objc_implementation_context));
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, size));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, list);
-
- finish_var_decl (decl,
- objc_build_constructor (TREE_TYPE (decl), v));
-
- return decl;
-}
static void
mark_referenced_methods (void)
@@ -7026,477 +4478,6 @@ mark_referenced_methods (void)
}
}
-static void
-generate_dispatch_tables (void)
-{
- tree initlist, chain, method_list_template;
- int size;
-
- if (!objc_method_template)
- objc_method_template = build_method_template ();
-
- chain = CLASS_CLS_METHODS (objc_implementation_context);
- if (chain)
- {
- size = list_length (chain);
-
- method_list_template
- = build_method_list_template (objc_method_template, size);
- initlist
- = build_dispatch_table_initializer (objc_method_template, chain);
-
- UOBJC_CLASS_METHODS_decl
- = generate_dispatch_table (method_list_template,
- ((TREE_CODE (objc_implementation_context)
- == CLASS_IMPLEMENTATION_TYPE)
- ? "_OBJC_CLASS_METHODS"
- : "_OBJC_CATEGORY_CLASS_METHODS"),
- size, initlist);
- }
- else
- UOBJC_CLASS_METHODS_decl = 0;
-
- chain = CLASS_NST_METHODS (objc_implementation_context);
- if (chain)
- {
- size = list_length (chain);
-
- method_list_template
- = build_method_list_template (objc_method_template, size);
- initlist
- = build_dispatch_table_initializer (objc_method_template, chain);
-
- if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
- UOBJC_INSTANCE_METHODS_decl
- = generate_dispatch_table (method_list_template,
- "_OBJC_INSTANCE_METHODS",
- size, initlist);
- else
- /* We have a category. */
- UOBJC_INSTANCE_METHODS_decl
- = generate_dispatch_table (method_list_template,
- "_OBJC_CATEGORY_INSTANCE_METHODS",
- size, initlist);
- }
- else
- UOBJC_INSTANCE_METHODS_decl = 0;
-}
-
-static tree
-generate_protocol_list (tree i_or_p)
-{
- tree array_type, ptype, refs_decl, lproto, e, plist;
- int size = 0;
- const char *ref_name;
- VEC(constructor_elt,gc) *v = NULL;
-
- switch (TREE_CODE (i_or_p))
- {
- case CLASS_INTERFACE_TYPE:
- case CATEGORY_INTERFACE_TYPE:
- plist = CLASS_PROTOCOL_LIST (i_or_p);
- break;
- case PROTOCOL_INTERFACE_TYPE:
- plist = PROTOCOL_LIST (i_or_p);
- break;
- default:
- gcc_unreachable ();
- }
-
- /* Compute size. */
- for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
- if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
- && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
- size++;
-
- /* Build initializer. */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
- e = build_int_cst (build_pointer_type (objc_protocol_template), size);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
-
- for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
- {
- tree pval = TREE_VALUE (lproto);
-
- if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
- && PROTOCOL_FORWARD_DECL (pval))
- {
- e = build_unary_op (input_location, ADDR_EXPR,
- PROTOCOL_FORWARD_DECL (pval), 0);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
- }
- }
-
- /* static struct objc_protocol *refs[n]; */
-
- switch (TREE_CODE (i_or_p))
- {
- case PROTOCOL_INTERFACE_TYPE:
- ref_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL_REFS", i_or_p);
- break;
- case CLASS_INTERFACE_TYPE:
- ref_name = synth_id_with_class_suffix ("_OBJC_CLASS_PROTOCOLS", i_or_p);
- break;
- case CATEGORY_INTERFACE_TYPE:
- ref_name = synth_id_with_class_suffix ("_OBJC_CATEGORY_PROTOCOLS", i_or_p);
- break;
- default:
- gcc_unreachable ();
- }
-
- ptype = build_pointer_type (objc_protocol_template);
- array_type = build_sized_array_type (ptype, size + 3);
- refs_decl = start_var_decl (array_type, ref_name);
-
- finish_var_decl (refs_decl,
- objc_build_constructor (TREE_TYPE (refs_decl), v));
-
- return refs_decl;
-}
-
-static tree
-build_category_initializer (tree type, tree cat_name, tree class_name,
- tree instance_methods, tree class_methods,
- tree protocol_list)
-{
- tree expr;
- VEC(constructor_elt,gc) *v = NULL;
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
-
- if (!instance_methods)
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
- else
- {
- expr = convert (objc_method_list_ptr,
- build_unary_op (input_location, ADDR_EXPR,
- instance_methods, 0));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
- if (!class_methods)
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
- else
- {
- expr = convert (objc_method_list_ptr,
- build_unary_op (input_location, ADDR_EXPR,
- class_methods, 0));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
-
- /* protocol_list = */
- if (!protocol_list)
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
- else
- {
- expr = convert (build_pointer_type
- (build_pointer_type
- (objc_protocol_template)),
- build_unary_op (input_location, ADDR_EXPR,
- protocol_list, 0));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
-
- return objc_build_constructor (type, v);
-}
-
-/* struct _objc_class {
- struct objc_class *isa;
- struct objc_class *super_class;
- char *name;
- long version;
- long info;
- long instance_size;
- struct objc_ivar_list *ivars;
- struct objc_method_list *methods;
- if (flag_next_runtime)
- struct objc_cache *cache;
- else {
- struct sarray *dtable;
- struct objc_class *subclass_list;
- struct objc_class *sibling_class;
- }
- struct objc_protocol_list *protocols;
- if (flag_next_runtime)
- void *sel_id;
- void *gc_object_type;
- }; */
-
-static tree
-build_shared_structure_initializer (tree type, tree isa, tree super,
- tree name, tree size, int status,
- tree dispatch_table, tree ivar_list,
- tree protocol_list)
-{
- tree expr;
- VEC(constructor_elt,gc) *v = NULL;
-
- /* isa = */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
-
- /* super_class = */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
-
- /* name = */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
-
- /* version = */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- build_int_cst (long_integer_type_node, 0));
-
- /* info = */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- build_int_cst (long_integer_type_node, status));
-
- /* instance_size = */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
- convert (long_integer_type_node, size));
-
- /* objc_ivar_list = */
- if (!ivar_list)
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
- else
- {
- expr = convert (objc_ivar_list_ptr,
- build_unary_op (input_location, ADDR_EXPR,
- ivar_list, 0));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
-
- /* objc_method_list = */
- if (!dispatch_table)
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
- else
- {
- expr = convert (objc_method_list_ptr,
- build_unary_op (input_location, ADDR_EXPR,
- dispatch_table, 0));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
-
- if (flag_next_runtime)
- /* method_cache = */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
- else
- {
- /* 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));
-
- /* sibling_class = */
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
- }
-
- /* protocol_list = */
- if (! protocol_list)
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
- else
- {
- expr = convert (build_pointer_type
- (build_pointer_type
- (objc_protocol_template)),
- build_unary_op (input_location, ADDR_EXPR,
- protocol_list, 0));
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
- }
-
- 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));
-
- return objc_build_constructor (type, v);
-}
-
-/* Retrieve category interface CAT_NAME (if any) associated with CLASS. */
-
-static inline tree
-lookup_category (tree klass, tree cat_name)
-{
- tree category = CLASS_CATEGORY_LIST (klass);
-
- while (category && CLASS_SUPER_NAME (category) != cat_name)
- category = CLASS_CATEGORY_LIST (category);
- return category;
-}
-
-/* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
-
-static void
-generate_category (struct imp_entry *impent)
-{
- tree initlist, cat_name_expr, class_name_expr;
- tree protocol_decl, category;
- tree cat = impent->imp_context;
-
- implementation_template = impent->imp_template;
- UOBJC_CLASS_decl = impent->class_decl;
- UOBJC_METACLASS_decl = impent->meta_decl;
-
- add_class_reference (CLASS_NAME (cat));
- cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
-
- class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
-
- category = lookup_category (implementation_template,
- CLASS_SUPER_NAME (cat));
-
- if (category && CLASS_PROTOCOL_LIST (category))
- {
- generate_protocol_references (CLASS_PROTOCOL_LIST (category));
- protocol_decl = generate_protocol_list (category);
- }
- else
- protocol_decl = 0;
-
- initlist = build_category_initializer (TREE_TYPE (UOBJC_CLASS_decl),
- cat_name_expr, class_name_expr,
- UOBJC_INSTANCE_METHODS_decl,
- UOBJC_CLASS_METHODS_decl,
- protocol_decl);
- /* Finish and initialize the forward decl. */
- finish_var_decl (UOBJC_CLASS_decl, initlist);
-}
-
-/* static struct objc_class _OBJC_METACLASS_Foo={ ... };
- static struct objc_class _OBJC_CLASS_Foo={ ... }; */
-
-static void
-generate_shared_structures (struct imp_entry *impent)
-{
- tree name_expr, super_expr, root_expr;
- tree my_root_id, my_super_id;
- tree cast_type, initlist, protocol_decl;
- int cls_flags;
-
- objc_implementation_context = impent->imp_context;
- implementation_template = impent->imp_template;
- UOBJC_CLASS_decl = impent->class_decl;
- UOBJC_METACLASS_decl = impent->meta_decl;
- cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ;
-
- my_super_id = CLASS_SUPER_NAME (implementation_template);
- if (my_super_id)
- {
- add_class_reference (my_super_id);
-
- /* Compute "my_root_id" - this is required for code generation.
- the "isa" for all meta class structures points to the root of
- the inheritance hierarchy (e.g. "__Object")... */
- my_root_id = my_super_id;
- do
- {
- tree my_root_int = lookup_interface (my_root_id);
-
- if (my_root_int && CLASS_SUPER_NAME (my_root_int))
- my_root_id = CLASS_SUPER_NAME (my_root_int);
- else
- break;
- }
- while (1);
- }
- else
- /* No super class. */
- my_root_id = CLASS_NAME (implementation_template);
-
- cast_type = build_pointer_type (objc_class_template);
- name_expr = add_objc_string (CLASS_NAME (implementation_template),
- class_names);
-
- /* Install class `isa' and `super' pointers at runtime. */
- if (my_super_id)
- super_expr = add_objc_string (my_super_id, class_names);
- else
- super_expr = integer_zero_node;
-
- super_expr = build_c_cast (input_location,
- cast_type, super_expr); /* cast! */
-
- root_expr = add_objc_string (my_root_id, class_names);
- root_expr = build_c_cast (input_location, cast_type, root_expr); /* cast! */
-
- if (CLASS_PROTOCOL_LIST (implementation_template))
- {
- generate_protocol_references
- (CLASS_PROTOCOL_LIST (implementation_template));
- protocol_decl = generate_protocol_list (implementation_template);
- }
- else
- protocol_decl = 0;
-
- /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
-
- initlist
- = build_shared_structure_initializer
- (TREE_TYPE (UOBJC_METACLASS_decl),
- root_expr, super_expr, name_expr,
- convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
- 2 /*CLS_META*/,
- UOBJC_CLASS_METHODS_decl,
- UOBJC_CLASS_VARIABLES_decl,
- protocol_decl);
-
- finish_var_decl (UOBJC_METACLASS_decl, initlist);
-
- /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
-
- initlist
- = build_shared_structure_initializer
- (TREE_TYPE (UOBJC_CLASS_decl),
- build_unary_op (input_location, ADDR_EXPR, UOBJC_METACLASS_decl, 0),
- super_expr, name_expr,
- convert (integer_type_node,
- TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
- (implementation_template))),
- 1 /*CLS_FACTORY*/ | cls_flags,
- UOBJC_INSTANCE_METHODS_decl,
- UOBJC_INSTANCE_VARIABLES_decl,
- protocol_decl);
-
- finish_var_decl (UOBJC_CLASS_decl, initlist);
-}
-
-
-static const char *
-synth_id_with_class_suffix (const char *preamble, tree ctxt)
-{
- static char string[BUFSIZE];
-
- switch (TREE_CODE (ctxt))
- {
- case CLASS_IMPLEMENTATION_TYPE:
- case CLASS_INTERFACE_TYPE:
- sprintf (string, "%s_%s", preamble,
- IDENTIFIER_POINTER (CLASS_NAME (ctxt)));
- break;
- case CATEGORY_IMPLEMENTATION_TYPE:
- case CATEGORY_INTERFACE_TYPE:
- {
- /* We have a category. */
- const char *const class_name
- = IDENTIFIER_POINTER (CLASS_NAME (objc_implementation_context));
- const char *const class_super_name
- = IDENTIFIER_POINTER (CLASS_SUPER_NAME (objc_implementation_context));
- sprintf (string, "%s_%s_%s", preamble, class_name, class_super_name);
- break;
- }
- case PROTOCOL_INTERFACE_TYPE:
- {
- const char *protocol_name = IDENTIFIER_POINTER (PROTOCOL_NAME (ctxt));
- sprintf (string, "%s_%s", preamble, protocol_name);
- break;
- }
- default:
- gcc_unreachable ();
- }
-
- return string;
-}
-
/* If type is empty or only type qualifiers are present, add default
type of id (otherwise grokdeclarator will default to int). */
static inline tree
@@ -7666,9 +4647,6 @@ build_method_decl (enum tree_code code, tree ret_type, tree selector,
return method_decl;
}
-#define METHOD_DEF 0
-#define METHOD_REF 1
-
/* This routine processes objective-c method attributes. */
static void
@@ -7803,21 +4781,13 @@ objc_method_decl (enum tree_code opcode)
the method call are done together. If METH is null, user-defined
arguments (i.e., beyond self and _cmd) shall be represented by `...'. */
-static tree
+tree
get_arg_type_list (tree meth, int context, int superflag)
{
tree arglist, akey;
- /* Receiver type. */
- if (flag_next_runtime && superflag)
- arglist = build_tree_list (NULL_TREE, objc_super_type);
- else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
- arglist = build_tree_list (NULL_TREE, objc_instance_type);
- else
- arglist = build_tree_list (NULL_TREE, objc_object_type);
-
- /* Selector type - will eventually change to `int'. */
- chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
+ /* Receiver & _cmd types are runtime-dependent. */
+ arglist = (*runtime.get_arg_type_list_base) (meth, context, superflag);
/* No actual method prototype given -- assume that remaining arguments
are `...'. */
@@ -7934,7 +4904,7 @@ check_duplicates (hash hsh, int methods, int is_class)
static tree
receiver_is_class_object (tree receiver, int self, int super)
{
- tree chain, exp, arg;
+ tree exp, arg;
/* The receiver is 'self' or 'super' in the context of a class method. */
if (objc_method_context
@@ -7944,16 +4914,10 @@ receiver_is_class_object (tree receiver, int self, int super)
? CLASS_SUPER_NAME (implementation_template)
: CLASS_NAME (implementation_template));
- if (flag_next_runtime)
- {
- /* The receiver is a variable created by
- build_class_reference_decl. */
- if (TREE_CODE (receiver) == VAR_DECL && IS_CLASS (TREE_TYPE (receiver)))
- /* Look up the identifier. */
- for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
- if (TREE_PURPOSE (chain) == receiver)
- return TREE_VALUE (chain);
- }
+ /* The runtime might encapsulate things its own way. */
+ exp = (*runtime.receiver_is_class_object) (receiver);
+ if (exp)
+ return exp;
/* The receiver is a function call that returns an id. Check if
it is a call to objc_getClass, if so, pick up the class name. */
@@ -7966,7 +4930,7 @@ receiver_is_class_object (tree receiver, int self, int super)
prototypes for objc_get_class(). Thankfully, they seem to share the
same function type. */
&& TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
- && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
+ && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), runtime.tag_getclass)
/* We have a call to objc_get_class/objc_getClass! */
&& (arg = CALL_EXPR_ARG (receiver, 0)))
{
@@ -7979,7 +4943,7 @@ receiver_is_class_object (tree receiver, int self, int super)
}
return 0;
}
-
+
/* If we are currently building a message expr, this holds
the identifier of the selector of the message. This is
used when printing warnings about argument mismatches. */
@@ -8108,7 +5072,7 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params,
tree *deprecated_method_prototype)
{
tree method_prototype = NULL_TREE, rprotos = NULL_TREE, rtype;
- tree selector, retval, class_tree;
+ tree retval, class_tree;
int self, super, have_cast;
/* We have used the receiver, so mark it as read. */
@@ -8321,7 +5285,7 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params,
In practice this makes sense since casting an object to 'id'
is often used precisely to turn off warnings associated with
the object being of a particular class. */
- if (TREE_DEPRECATED (method_prototype) && rtype != NULL_TREE)
+ if (TREE_DEPRECATED (method_prototype) && rtype != NULL_TREE)
{
if (deprecated_method_prototype)
*deprecated_method_prototype = method_prototype;
@@ -8330,213 +5294,42 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params,
}
}
-
/* Save the selector name for printing error messages. */
current_objc_message_selector = 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 (input_location,
- sel_name, method_prototype);
- else
- selector = build_selector_reference (input_location, sel_name);
-
- retval = build_objc_method_call (input_location, super, method_prototype,
- receiver,
- selector, method_params);
+ /* Build the method call.
+ TODO: Get the location from somewhere that will work for delayed
+ expansion. */
+
+ retval = (*runtime.build_objc_method_call) (input_location, method_prototype,
+ receiver, rtype, sel_name,
+ method_params, super);
current_objc_message_selector = 0;
return retval;
}
-/* Build a tree expression to send OBJECT the operation SELECTOR,
- looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
- assuming the method has prototype METHOD_PROTOTYPE.
- (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
- LOC is the location of the expression to build.
- Use METHOD_PARAMS as list of args to pass to the method.
- If SUPER_FLAG is nonzero, we look up the superclass's method. */
-
-static tree
-build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
- tree lookup_object, tree selector,
- tree method_params)
-{
- tree sender = (super_flag ? umsg_super_decl :
- (!flag_next_runtime || flag_nil_receivers
- ? (flag_objc_direct_dispatch
- ? umsg_fast_decl
- : umsg_decl)
- : umsg_nonnil_decl));
- tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
- VEC(tree, gc) *parms = NULL;
- 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 method_param_types =
- get_arg_type_list (method_prototype, METHOD_REF, super_flag);
- tree ftype = build_function_type (ret_type, method_param_types);
- tree sender_cast;
- tree method, t;
-
- 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. */
- parms = VEC_alloc (tree, gc, nparm + 2);
-
- if (flag_next_runtime)
- {
- /* 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))
- sender = (super_flag ? umsg_super_stret_decl :
- flag_nil_receivers ? umsg_stret_decl : umsg_nonnil_stret_decl);
-
- method = build_fold_addr_expr_loc (input_location, sender);
- /* Pass the object to the method. */
- VEC_quick_push (tree, parms, lookup_object);
- }
- else
- {
- /* This is the portable (GNU) way. */
- /* First, call the lookup function to get a pointer to the method,
- then cast the pointer, then call it with the method arguments. */
- VEC(tree, gc) *tv = VEC_alloc (tree, gc, 2);
- VEC_quick_push (tree, tv, lookup_object);
- VEC_quick_push (tree, tv, selector);
- method = build_function_call_vec (loc, sender, tv, NULL);
- VEC_free (tree, gc, tv);
-
- /* Pass the appropriate object to the method. */
- VEC_quick_push (tree, parms, (super_flag ? self_decl : lookup_object));
- }
- /* Pass the selector to the method. */
- VEC_quick_push (tree, parms, selector);
- /* Now append the remainder of the parms. */
- if (nparm)
- for (; method_params; method_params = TREE_CHAIN (method_params))
- VEC_quick_push (tree, parms, 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);
- t = build_function_call_vec (loc, t, parms, NULL);\
- VEC_free (tree, gc, parms);
- return t;
-}
-
-static void
-build_protocol_reference (tree p)
-{
- tree decl;
- const char *proto_name;
-
- /* static struct _objc_protocol _OBJC_PROTOCOL_<mumble>; */
-
- proto_name = synth_id_with_class_suffix ("_OBJC_PROTOCOL", p);
- decl = start_var_decl (objc_protocol_template, proto_name);
-
- PROTOCOL_FORWARD_DECL (p) = decl;
-}
+/* This routine creates a static variable used to implement @protocol(MyProtocol)
+ expression. This variable will be initialized to global protocol_t meta-data
+ pointer. */
/* This function is called by the parser when (and only when) a
@protocol() expression is found, in order to compile it. */
tree
objc_build_protocol_expr (tree protoname)
{
- tree expr;
tree p = lookup_protocol (protoname, /* warn if deprecated */ true,
/* definition_required */ false);
if (!p)
{
- error ("cannot find protocol declaration for %qE",
- protoname);
+ error ("cannot find protocol declaration for %qE", protoname);
return error_mark_node;
}
- if (!PROTOCOL_FORWARD_DECL (p))
- build_protocol_reference (p);
-
- expr = build_unary_op (input_location,
- ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
-
- /* ??? Ideally we'd build the reference with objc_protocol_type directly,
- if we have it, rather than converting it here. */
- expr = convert (objc_protocol_type, expr);
-
- /* The @protocol() expression is being compiled into a pointer to a
- statically allocated instance of the Protocol class. To become
- usable at runtime, the 'isa' pointer of the instance need to be
- fixed up at runtime by the runtime library, to point to the
- actual 'Protocol' class. */
-
- /* For the GNU runtime, put the static Protocol instance in the list
- of statically allocated instances, so that we make sure that its
- 'isa' pointer is fixed up at runtime by the GNU runtime library
- to point to the Protocol class (at runtime, when loading the
- module, the GNU runtime library loops on the statically allocated
- instances (as found in the defs field in objc_symtab) and fixups
- all the 'isa' pointers of those objects). */
- if (! flag_next_runtime)
- {
- /* This type is a struct containing the fields of a Protocol
- object. (Cfr. objc_protocol_type instead is the type of a pointer
- to such a struct). */
- tree protocol_struct_type = xref_tag
- (RECORD_TYPE, get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
- tree *chain;
-
- /* Look for the list of Protocol statically allocated instances
- to fixup at runtime. Create a new list to hold Protocol
- statically allocated instances, if the list is not found. At
- present there is only another list, holding NSConstantString
- static instances to be fixed up at runtime. */
- for (chain = &objc_static_instances;
- *chain && TREE_VALUE (*chain) != protocol_struct_type;
- chain = &TREE_CHAIN (*chain));
- if (!*chain)
- {
- *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
- add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
- class_names);
- }
-
- /* Add this statically allocated instance to the Protocol list. */
- TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
- PROTOCOL_FORWARD_DECL (p),
- TREE_PURPOSE (*chain));
- }
-
-
- return expr;
+ return (*runtime.get_protocol_reference) (input_location, p);
}
/* This function is called by the parser when a @selector() expression
@@ -8587,11 +5380,9 @@ objc_build_selector_expr (location_t loc, tree selnamelist)
}
}
-
- if (flag_typed_selectors)
- return build_typed_selector_reference (loc, selname, 0);
- else
- return build_selector_reference (loc, selname);
+ /* The runtimes do this differently, most particularly, GNU has typed
+ selectors, whilst NeXT does not. */
+ return (*runtime.build_selector_reference) (loc, selname, NULL_TREE);
}
/* This is used to implement @encode(). See gcc/doc/objc.texi,
@@ -8616,6 +5407,7 @@ objc_build_encode_expr (tree type)
static tree
build_ivar_reference (tree id)
{
+ tree base;
if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
{
/* Historically, a class method that produced objects (factory
@@ -8632,11 +5424,10 @@ build_ivar_reference (tree id)
self_decl = convert (objc_instance_type, self_decl); /* cast */
}
- return objc_build_component_ref (build_indirect_ref (input_location,
- self_decl, RO_ARROW),
- id);
+ base = build_indirect_ref (input_location, self_decl, RO_ARROW);
+ return (*runtime.build_ivar_reference) (input_location, base, id);
}
-
+
/* Compute a hash value for a given method SEL_NAME. */
static size_t
@@ -8660,6 +5451,8 @@ hash_init (void)
cls_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
als_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+ ivar_offset_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+
/* Initialize the hash table used to hold the constant string objects. */
string_htab = htab_create_ggc (31, string_hash,
string_eq, NULL);
@@ -9200,16 +5993,6 @@ add_instance_variable (tree klass, objc_ivar_visibility_kind visibility,
return klass;
}
-
-
-static tree
-is_ivar (tree decl_chain, tree ident)
-{
- for ( ; decl_chain; decl_chain = DECL_CHAIN (decl_chain))
- if (DECL_NAME (decl_chain) == ident)
- return decl_chain;
- return NULL_TREE;
-}
/* True if the ivar is private and we are not in its implementation. */
@@ -9763,9 +6546,6 @@ start_class (enum tree_code code, tree class_name, tree super_name,
CLASS_PROTOCOL_LIST (klass)
= lookup_and_install_protocols (protocol_list, /* definition_required */ true);
- /* Determine if 'deprecated', the only attribute we recognize
- for classes, was used. Ignore all other attributes for now,
- but store them in the klass. */
if (attributes)
{
tree attribute;
@@ -9773,9 +6553,14 @@ start_class (enum tree_code code, tree class_name, tree super_name,
{
tree name = TREE_PURPOSE (attribute);
+ /* We handle the 'deprecated' and (undocumented) 'objc_exception'
+ attributes. */
if (is_attribute_p ("deprecated", name))
TREE_DEPRECATED (klass) = 1;
+ else if (is_attribute_p ("objc_exception", name))
+ CLASS_HAS_EXCEPTION_ATTR (klass) = 1;
else
+ /* Warn about and ignore all others for now, but store them. */
warning (OPT_Wattributes, "%qE attribute directive ignored", name);
}
TYPE_ATTRIBUTES (klass) = attributes;
@@ -9874,25 +6659,32 @@ continue_class (tree klass)
#ifdef OBJCPLUS
push_lang_context (lang_name_c);
#endif
- build_private_template (implementation_template);
- uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
- objc_instance_type = build_pointer_type (uprivate_record);
-
- imp_entry = ggc_alloc_imp_entry ();
+ build_private_template (implementation_template);
+ uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
+ objc_instance_type = build_pointer_type (uprivate_record);
- imp_entry->next = imp_list;
- imp_entry->imp_context = klass;
- imp_entry->imp_template = implementation_template;
+ imp_entry = ggc_alloc_imp_entry ();
- synth_forward_declarations ();
- imp_entry->class_decl = UOBJC_CLASS_decl;
- imp_entry->meta_decl = UOBJC_METACLASS_decl;
+ imp_entry->next = imp_list;
+ imp_entry->imp_context = klass;
+ imp_entry->imp_template = implementation_template;
+ ucls_super_ref = uucls_super_ref = NULL;
+ if (TREE_CODE (klass) == CLASS_IMPLEMENTATION_TYPE)
+ {
+ imp_entry->class_decl = (*runtime.class_decl) (klass);
+ imp_entry->meta_decl = (*runtime.metaclass_decl) (klass);
+ }
+ else
+ {
+ imp_entry->class_decl = (*runtime.category_decl) (klass);
+ imp_entry->meta_decl = NULL;
+ }
imp_entry->has_cxx_cdtors = 0;
- /* Append to front and increment count. */
- imp_list = imp_entry;
- if (TREE_CODE (klass) == CLASS_IMPLEMENTATION_TYPE)
- imp_count++;
+ /* Append to front and increment count. */
+ imp_list = imp_entry;
+ if (TREE_CODE (klass) == CLASS_IMPLEMENTATION_TYPE)
+ imp_count++;
else
cat_count++;
#ifdef OBJCPLUS
@@ -9936,9 +6728,12 @@ objc_build_property_setter_name (tree ident)
/* This routine prepares the declarations of the property accessor
helper functions (objc_getProperty(), etc) that are used when
- @synthesize is used. */
+ @synthesize is used.
+
+ runtime-specific routines are built in the respective runtime
+ initialize functions. */
static void
-build_objc_property_accessor_helpers (void)
+build_common_objc_property_accessor_helpers (void)
{
tree type;
@@ -9974,52 +6769,6 @@ build_objc_property_accessor_helpers (void)
type, 0, NOT_BUILT_IN,
NULL, NULL_TREE);
TREE_NOTHROW (objc_setProperty_decl) = 0;
-
- /* This is the type of all of the following functions
- (objc_copyStruct(), objc_getPropertyStruct() and
- objc_setPropertyStruct()). */
- type = build_function_type_list (void_type_node,
- ptr_type_node,
- const_ptr_type_node,
- ptrdiff_type_node,
- boolean_type_node,
- boolean_type_node,
- NULL_TREE);
-
- if (flag_next_runtime)
- {
- /* Declare the following function:
- void
- objc_copyStruct (void *destination, const void *source,
- ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
- objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- TREE_NOTHROW (objc_copyStruct_decl) = 0;
- objc_getPropertyStruct_decl = NULL_TREE;
- objc_setPropertyStruct_decl = NULL_TREE;
- }
- else
- {
- objc_copyStruct_decl = NULL_TREE;
-
- /* Declare the following function:
- void
- objc_getPropertyStruct (void *destination, const void *source,
- ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
- objc_getPropertyStruct_decl = add_builtin_function ("objc_getPropertyStruct",
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- TREE_NOTHROW (objc_getPropertyStruct_decl) = 0;
- /* Declare the following function:
- void
- objc_setPropertyStruct (void *destination, const void *source,
- ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
- objc_setPropertyStruct_decl = add_builtin_function ("objc_setPropertyStruct",
- type, 0, NOT_BUILT_IN,
- NULL, NULL_TREE);
- TREE_NOTHROW (objc_setPropertyStruct_decl) = 0;
- }
}
/* This looks up an ivar in a class (including superclasses). */
@@ -10169,7 +6918,7 @@ objc_synthesize_getter (tree klass, tree class_methods ATTRIBUTE_UNUSED, tree pr
else
is_atomic = boolean_true_node;
- if (flag_next_runtime)
+ if (objc_copyStruct_decl)
function_decl = objc_copyStruct_decl;
else
function_decl = objc_getPropertyStruct_decl;
@@ -10369,7 +7118,7 @@ objc_synthesize_setter (tree klass, tree class_methods ATTRIBUTE_UNUSED, tree pr
else
is_atomic = boolean_true_node;
- if (flag_next_runtime)
+ if (objc_copyStruct_decl)
function_decl = objc_copyStruct_decl;
else
function_decl = objc_setPropertyStruct_decl;
@@ -10756,6 +7505,10 @@ objc_gen_property_data (tree klass, tree class_methods)
/* @dynamic property - nothing to check or synthesize. */
if (PROPERTY_DYNAMIC (x))
continue;
+ /* Add any property that is declared in the interface, but undeclared in the
+ implementation to thie implementation. These are the 'dynamic' properties.
+
+ objc_v2_merge_dynamic_property ();*/
/* @synthesize property - need to synthesize the accessors. */
if (PROPERTY_IVAR_NAME (x))
@@ -10781,7 +7534,7 @@ finish_class (tree klass)
{
case CLASS_IMPLEMENTATION_TYPE:
{
- /* All code generation is done in finish_objc. */
+ /* All metadata generation is done in runtime.generate_metadata(). */
/* Generate what needed for property; setters, getters, etc. */
objc_gen_property_data (implementation_template, implementation_template);
@@ -11018,6 +7771,7 @@ objc_declare_protocols (tree names, tree attributes)
add_protocol (protocol);
PROTOCOL_DEFINED (protocol) = 0;
PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
+/* PROTOCOL_V2_FORWARD_DECL (protocol) = NULL_TREE;*/
if (attributes)
{
@@ -11070,6 +7824,7 @@ start_protocol (enum tree_code code, tree name, tree list, tree attributes)
add_protocol (protocol);
PROTOCOL_DEFINED (protocol) = 1;
PROTOCOL_FORWARD_DECL (protocol) = NULL_TREE;
+/* PROTOCOL_V2_FORWARD_DECL (protocol) = NULL_TREE;*/
check_protocol_recursively (protocol, list);
}
@@ -11096,666 +7851,6 @@ start_protocol (enum tree_code code, tree name, tree list, tree attributes)
return protocol;
}
-
-/* "Encode" a data type into a string, which grows in util_obstack.
-
- The format is described in gcc/doc/objc.texi, section 'Type
- encoding'.
-
- Most of the encode_xxx functions have a 'type' argument, which is
- the type to encode, and an integer 'curtype' argument, which is the
- index in the encoding string of the beginning of the encoding of
- the current type, and allows you to find what characters have
- already been written for the current type (they are the ones in the
- current encoding string starting from 'curtype').
-
- For example, if we are encoding a method which returns 'int' and
- takes a 'char **' argument, then when we get to the point of
- encoding the 'char **' argument, the encoded string already
- contains 'i12@0:4' (assuming a pointer size of 4 bytes). So,
- 'curtype' will be set to 7 when starting to encode 'char **'.
- During the whole of the encoding of 'char **', 'curtype' will be
- fixed at 7, so the routine encoding the second pointer can find out
- that it's actually encoding a pointer to a pointer by looking
- backwards at what has already been encoded for the current type,
- and seeing there is a "^" (meaning a pointer) in there.
-*/
-
-
-/* Encode type qualifiers encodes one of the "PQ" Objective-C
- keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
- 'const', instead, is encoded directly as part of the type.
- */
-
-static void
-encode_type_qualifiers (tree declspecs)
-{
- tree spec;
-
- for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
- {
- /* FIXME: Shouldn't we use token->keyword here ? */
- if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'n');
- else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'N');
- else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'o');
- else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'O');
- else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'R');
- else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
- obstack_1grow (&util_obstack, 'V');
- else
- gcc_unreachable ();
- }
-}
-
-/* Determine if a pointee is marked read-only. Only used by the NeXT
- runtime to be compatible with gcc-3.3. */
-
-static bool
-pointee_is_readonly (tree pointee)
-{
- while (POINTER_TYPE_P (pointee))
- pointee = TREE_TYPE (pointee);
-
- return TYPE_READONLY (pointee);
-}
-
-/* Encode a pointer type. */
-
-static void
-encode_pointer (tree type, int curtype, int format)
-{
- tree pointer_to = TREE_TYPE (type);
-
- if (flag_next_runtime)
- {
- /* This code is used to be compatible with gcc-3.3. */
- /* For historical/compatibility reasons, the read-only qualifier
- of the pointee gets emitted _before_ the '^'. The read-only
- qualifier of the pointer itself gets ignored, _unless_ we are
- looking at a typedef! Also, do not emit the 'r' for anything
- but the outermost type! */
- if (!generating_instance_variables
- && (obstack_object_size (&util_obstack) - curtype <= 1)
- && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- ? TYPE_READONLY (type)
- : pointee_is_readonly (pointer_to)))
- obstack_1grow (&util_obstack, 'r');
- }
-
- if (TREE_CODE (pointer_to) == RECORD_TYPE)
- {
- if (OBJC_TYPE_NAME (pointer_to)
- && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
- {
- const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
-
- if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
- {
- obstack_1grow (&util_obstack, '@');
- return;
- }
- else if (TYPE_HAS_OBJC_INFO (pointer_to)
- && TYPE_OBJC_INTERFACE (pointer_to))
- {
- if (generating_instance_variables)
- {
- obstack_1grow (&util_obstack, '@');
- obstack_1grow (&util_obstack, '"');
- obstack_grow (&util_obstack, name, strlen (name));
- obstack_1grow (&util_obstack, '"');
- return;
- }
- else
- {
- obstack_1grow (&util_obstack, '@');
- return;
- }
- }
- else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
- {
- obstack_1grow (&util_obstack, '#');
- return;
- }
- else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
- {
- obstack_1grow (&util_obstack, ':');
- return;
- }
- }
- }
- else if (TREE_CODE (pointer_to) == INTEGER_TYPE
- && TYPE_MODE (pointer_to) == QImode)
- {
- tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
- ? OBJC_TYPE_NAME (pointer_to)
- : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
-
- /* (BOOL *) are an exception and are encoded as ^c, while all
- other pointers to char are encoded as *. */
- if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
- {
- if (!flag_next_runtime)
- {
- /* The NeXT runtime adds the 'r' before getting here. */
-
- /* It appears that "r*" means "const char *" rather than
- "char *const". "char *const" is encoded as "*",
- which is identical to "char *", so the "const" is
- unfortunately lost. */
- if (TYPE_READONLY (pointer_to))
- obstack_1grow (&util_obstack, 'r');
- }
-
- obstack_1grow (&util_obstack, '*');
- return;
- }
- }
-
- /* We have a normal pointer type that does not get special treatment. */
- obstack_1grow (&util_obstack, '^');
- encode_type (pointer_to, curtype, format);
-}
-
-static void
-encode_array (tree type, int curtype, int format)
-{
- tree an_int_cst = TYPE_SIZE (type);
- tree array_of = TREE_TYPE (type);
- char buffer[40];
-
- if (an_int_cst == NULL)
- {
- /* We are trying to encode an incomplete array. An incomplete
- array is forbidden as part of an instance variable. */
- if (generating_instance_variables)
- {
- /* TODO: Detect this error earlier. */
- error ("instance variable has unknown size");
- return;
- }
-
- /* So the only case in which an incomplete array could occur is
- if we are encoding the arguments or return value of a method.
- In that case, an incomplete array argument or return value
- (eg, -(void)display: (char[])string) is treated like a
- pointer because that is how the compiler does the function
- call. A special, more complicated case, is when the
- incomplete array is the last member of a struct (eg, if we
- are encoding "struct { unsigned long int a;double b[];}"),
- which is again part of a method argument/return value. In
- that case, we really need to communicate to the runtime that
- there is an incomplete array (not a pointer!) there. So, we
- detect that special case and encode it as a zero-length
- array.
-
- Try to detect that we are part of a struct. We do this by
- searching for '=' in the type encoding for the current type.
- NB: This hack assumes that you can't use '=' as part of a C
- identifier.
- */
- {
- char *enc = obstack_base (&util_obstack) + curtype;
- if (memchr (enc, '=',
- obstack_object_size (&util_obstack) - curtype) == NULL)
- {
- /* We are not inside a struct. Encode the array as a
- pointer. */
- encode_pointer (type, curtype, format);
- return;
- }
- }
-
- /* Else, we are in a struct, and we encode it as a zero-length
- array. */
- sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
- }
- else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
- sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
- else
- sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
- TREE_INT_CST_LOW (an_int_cst)
- / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
-
- obstack_grow (&util_obstack, buffer, strlen (buffer));
- encode_type (array_of, curtype, format);
- obstack_1grow (&util_obstack, ']');
- return;
-}
-
-/* Encode a vector. The vector type is a GCC extension to C. */
-static void
-encode_vector (tree type, int curtype, int format)
-{
- tree vector_of = TREE_TYPE (type);
- char buffer[40];
-
- /* Vectors are like simple fixed-size arrays. */
-
- /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
- alignment of the vector, and <code> is the base type. Eg, int
- __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
- assuming that the alignment is 32 bytes. We include size and
- alignment in bytes so that the runtime does not have to have any
- knowledge of the actual types.
- */
- sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
- /* We want to compute the equivalent of sizeof (<vector>).
- Code inspired by c_sizeof_or_alignof_type. */
- ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
- / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
- /* We want to compute the equivalent of __alignof__
- (<vector>). Code inspired by
- c_sizeof_or_alignof_type. */
- TYPE_ALIGN_UNIT (type));
- obstack_grow (&util_obstack, buffer, strlen (buffer));
- encode_type (vector_of, curtype, format);
- obstack_1grow (&util_obstack, ']');
- return;
-}
-
-static void
-encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
-{
- tree field = TYPE_FIELDS (type);
-
- for (; field; field = DECL_CHAIN (field))
- {
-#ifdef OBJCPLUS
- /* C++ static members, and things that are not field at all,
- should not appear in the encoding. */
- if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
- continue;
-#endif
-
- /* Recursively encode fields of embedded base classes. */
- if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
- && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
- {
- encode_aggregate_fields (TREE_TYPE (field),
- pointed_to, curtype, format);
- continue;
- }
-
- if (generating_instance_variables && !pointed_to)
- {
- tree fname = DECL_NAME (field);
-
- obstack_1grow (&util_obstack, '"');
-
- if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
- obstack_grow (&util_obstack,
- IDENTIFIER_POINTER (fname),
- strlen (IDENTIFIER_POINTER (fname)));
-
- obstack_1grow (&util_obstack, '"');
- }
-
- encode_field_decl (field, curtype, format);
- }
-}
-
-static void
-encode_aggregate_within (tree type, int curtype, int format, int left,
- int right)
-{
- tree name;
- /* NB: aggregates that are pointed to have slightly different encoding
- rules in that you never encode the names of instance variables. */
- int ob_size = obstack_object_size (&util_obstack);
- bool inline_contents = false;
- bool pointed_to = false;
-
- if (flag_next_runtime)
- {
- if (ob_size > 0 && *(obstack_next_free (&util_obstack) - 1) == '^')
- pointed_to = true;
-
- if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
- && (!pointed_to || ob_size - curtype == 1
- || (ob_size - curtype == 2
- && *(obstack_next_free (&util_obstack) - 2) == 'r')))
- inline_contents = true;
- }
- else
- {
- /* c0 and c1 are the last two characters in the encoding of the
- current type; if the last two characters were '^' or '^r',
- then we are encoding an aggregate that is "pointed to". The
- comment above applies: in that case we should avoid encoding
- the names of instance variables.
- */
- char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
- char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
-
- if (c0 == '^' || (c1 == '^' && c0 == 'r'))
- pointed_to = true;
-
- if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
- {
- if (!pointed_to)
- inline_contents = true;
- else
- {
- /* Note that the check (ob_size - curtype < 2) prevents
- infinite recursion when encoding a structure which is
- a linked list (eg, struct node { struct node *next;
- }). Each time we follow a pointer, we add one
- character to ob_size, and curtype is fixed, so after
- at most two pointers we stop inlining contents and
- break the loop.
-
- The other case where we don't inline is "^r", which
- is a pointer to a constant struct.
- */
- if ((ob_size - curtype <= 2) && !(c0 == 'r'))
- inline_contents = true;
- }
- }
- }
-
- /* Traverse struct aliases; it is important to get the
- original struct and its tag name (if any). */
- type = TYPE_MAIN_VARIANT (type);
- name = OBJC_TYPE_NAME (type);
- /* Open parenth/bracket. */
- obstack_1grow (&util_obstack, left);
-
- /* Encode the struct/union tag name, or '?' if a tag was
- not provided. Typedef aliases do not qualify. */
-#ifdef OBJCPLUS
- /* For compatibility with the NeXT runtime, ObjC++ encodes template
- args as a composite struct tag name. */
- if (name && TREE_CODE (name) == IDENTIFIER_NODE
- /* Did this struct have a tag? */
- && !TYPE_WAS_ANONYMOUS (type))
- obstack_grow (&util_obstack,
- decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
- strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
-#else
- if (name && TREE_CODE (name) == IDENTIFIER_NODE)
- obstack_grow (&util_obstack,
- IDENTIFIER_POINTER (name),
- strlen (IDENTIFIER_POINTER (name)));
-#endif
- else
- obstack_1grow (&util_obstack, '?');
-
- /* Encode the types (and possibly names) of the inner fields,
- if required. */
- if (inline_contents)
- {
- obstack_1grow (&util_obstack, '=');
- encode_aggregate_fields (type, pointed_to, curtype, format);
- }
- /* Close parenth/bracket. */
- obstack_1grow (&util_obstack, right);
-}
-
-/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
- field type. */
-
-static void
-encode_next_bitfield (int width)
-{
- char buffer[40];
- sprintf (buffer, "b%d", width);
- obstack_grow (&util_obstack, buffer, strlen (buffer));
-}
-
-
-/* Encodes 'type', ignoring type qualifiers (which you should encode
- beforehand if needed) with the exception of 'const', which is
- encoded by encode_type. See above for the explanation of
- 'curtype'. 'format' can be OBJC_ENCODE_INLINE_DEFS or
- OBJC_ENCODE_DONT_INLINE_DEFS.
-*/
-static void
-encode_type (tree type, int curtype, int format)
-{
- enum tree_code code = TREE_CODE (type);
-
- /* Ignore type qualifiers other than 'const' when encoding a
- type. */
-
- if (type == error_mark_node)
- return;
-
- if (!flag_next_runtime)
- {
- if (TYPE_READONLY (type))
- obstack_1grow (&util_obstack, 'r');
- }
-
- switch (code)
- {
- case ENUMERAL_TYPE:
- if (flag_next_runtime)
- {
- /* Kludge for backwards-compatibility with gcc-3.3: enums
- are always encoded as 'i' no matter what type they
- actually are (!). */
- obstack_1grow (&util_obstack, 'i');
- break;
- }
- /* Else, they are encoded exactly like the integer type that is
- used by the compiler to store them. */
- case INTEGER_TYPE:
- {
- char c;
- switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
- {
- case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
- case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
- case 32:
- {
- tree int_type = type;
- if (flag_next_runtime)
- {
- /* Another legacy kludge for compatiblity with
- gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
- but not always. For typedefs, we need to use 'i'
- or 'I' instead if encoding a struct field, or a
- pointer! */
- int_type = ((!generating_instance_variables
- && (obstack_object_size (&util_obstack)
- == (unsigned) curtype))
- ? TYPE_MAIN_VARIANT (type)
- : type);
- }
- if (int_type == long_unsigned_type_node
- || int_type == long_integer_type_node)
- c = TYPE_UNSIGNED (type) ? 'L' : 'l';
- else
- c = TYPE_UNSIGNED (type) ? 'I' : 'i';
- }
- break;
- case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
- case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
- default: gcc_unreachable ();
- }
- obstack_1grow (&util_obstack, c);
- break;
- }
- case REAL_TYPE:
- {
- char c;
- /* Floating point types. */
- switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
- {
- case 32: c = 'f'; break;
- case 64: c = 'd'; break;
- case 96:
- case 128: c = 'D'; break;
- default: gcc_unreachable ();
- }
- obstack_1grow (&util_obstack, c);
- break;
- }
- case VOID_TYPE:
- obstack_1grow (&util_obstack, 'v');
- break;
-
- case BOOLEAN_TYPE:
- obstack_1grow (&util_obstack, 'B');
- break;
-
- case ARRAY_TYPE:
- encode_array (type, curtype, format);
- break;
-
- case POINTER_TYPE:
-#ifdef OBJCPLUS
- case REFERENCE_TYPE:
-#endif
- encode_pointer (type, curtype, format);
- break;
-
- case RECORD_TYPE:
- encode_aggregate_within (type, curtype, format, '{', '}');
- break;
-
- case UNION_TYPE:
- encode_aggregate_within (type, curtype, format, '(', ')');
- break;
-
- case FUNCTION_TYPE: /* '?' means an unknown type. */
- obstack_1grow (&util_obstack, '?');
- break;
-
- case COMPLEX_TYPE:
- /* A complex is encoded as 'j' followed by the inner type (eg,
- "_Complex int" is encoded as 'ji'). */
- obstack_1grow (&util_obstack, 'j');
- encode_type (TREE_TYPE (type), curtype, format);
- break;
-
- case VECTOR_TYPE:
- encode_vector (type, curtype, format);
- break;
-
- default:
- warning (0, "unknown type %s found during Objective-C encoding",
- gen_type_name (type));
- obstack_1grow (&util_obstack, '?');
- break;
- }
-
- if (flag_next_runtime)
- {
- /* Super-kludge. Some ObjC qualifier and type combinations need
- to be rearranged for compatibility with gcc-3.3. */
- if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
- {
- char *enc = obstack_base (&util_obstack) + curtype;
-
- /* Rewrite "in const" from "nr" to "rn". */
- if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
- strncpy (enc - 1, "rn", 2);
- }
- }
-}
-
-static void
-encode_gnu_bitfield (int position, tree type, int size)
-{
- enum tree_code code = TREE_CODE (type);
- char buffer[40];
- char charType = '?';
-
- /* This code is only executed for the GNU runtime, so we can ignore
- the NeXT runtime kludge of always encoding enums as 'i' no matter
- what integers they actually are. */
- if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
- {
- if (integer_zerop (TYPE_MIN_VALUE (type)))
- /* Unsigned integer types. */
- {
- switch (TYPE_MODE (type))
- {
- case QImode:
- charType = 'C'; break;
- case HImode:
- charType = 'S'; break;
- case SImode:
- {
- if (type == long_unsigned_type_node)
- charType = 'L';
- else
- charType = 'I';
- break;
- }
- case DImode:
- charType = 'Q'; break;
- default:
- gcc_unreachable ();
- }
- }
- else
- /* Signed integer types. */
- {
- switch (TYPE_MODE (type))
- {
- case QImode:
- charType = 'c'; break;
- case HImode:
- charType = 's'; break;
- case SImode:
- {
- if (type == long_integer_type_node)
- charType = 'l';
- else
- charType = 'i';
- break;
- }
- case DImode:
- charType = 'q'; break;
- default:
- gcc_unreachable ();
- }
- }
- }
- else
- {
- /* Do not do any encoding, produce an error and keep going. */
- error ("trying to encode non-integer type as a bitfield");
- return;
- }
-
- sprintf (buffer, "b%d%c%d", position, charType, size);
- obstack_grow (&util_obstack, buffer, strlen (buffer));
-}
-
-static void
-encode_field_decl (tree field_decl, int curtype, int format)
-{
-#ifdef OBJCPLUS
- /* C++ static members, and things that are not fields at all,
- should not appear in the encoding. */
- if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
- return;
-#endif
-
- /* Generate the bitfield typing information, if needed. Note the difference
- between GNU and NeXT runtimes. */
- if (DECL_BIT_FIELD_TYPE (field_decl))
- {
- int size = tree_low_cst (DECL_SIZE (field_decl), 1);
-
- if (flag_next_runtime)
- encode_next_bitfield (size);
- else
- encode_gnu_bitfield (int_bit_position (field_decl),
- DECL_BIT_FIELD_TYPE (field_decl), size);
- }
- else
- encode_type (TREE_TYPE (field_decl), curtype, format);
-}
-
/* Decay array and function parameters into pointers. */
static tree
@@ -11774,7 +7869,7 @@ static GTY(()) tree objc_parmlist = NULL_TREE;
/* Append PARM to a list of formal parameters of a method, making a necessary
array-to-pointer adjustment along the way. */
-static void
+void
objc_push_parm (tree parm)
{
tree type;
@@ -11809,19 +7904,18 @@ objc_push_parm (tree parm)
objc_push_parm(). */
#ifdef OBJCPLUS
-static tree
+tree
objc_get_parm_info (int have_ellipsis ATTRIBUTE_UNUSED)
-#else
-static struct c_arg_info *
-objc_get_parm_info (int have_ellipsis)
-#endif
{
-#ifdef OBJCPLUS
tree parm_info = objc_parmlist;
objc_parmlist = NULL_TREE;
return parm_info;
+}
#else
+struct c_arg_info *
+objc_get_parm_info (int have_ellipsis)
+{
tree parm_info = objc_parmlist;
struct c_arg_info *arg_info;
/* The C front-end requires an elaborate song and dance at
@@ -11841,8 +7935,8 @@ objc_get_parm_info (int have_ellipsis)
pop_scope ();
objc_parmlist = NULL_TREE;
return arg_info;
-#endif
}
+#endif
/* Synthesize the formal parameters 'id self' and 'SEL _cmd' needed for ObjC
method definitions. In the case of instance methods, we can be more
@@ -12043,6 +8137,39 @@ match_proto_with_proto (tree proto1, tree proto2, int strict)
return (!type1 && !type2);
}
+/* This routine returns true if TYPE is a valid objc object type,
+ suitable for messaging; false otherwise. If 'accept_class' is
+ 'true', then a Class object is considered valid for messaging and
+ 'true' is returned if 'type' refers to a Class. If 'accept_class'
+ is 'false', then a Class object is not considered valid for
+ messaging and 'false' is returned in that case. */
+
+static bool
+objc_type_valid_for_messaging (tree type, bool accept_classes)
+{
+ if (!POINTER_TYPE_P (type))
+ return false;
+
+ /* Remove the pointer indirection; don't remove more than one
+ otherwise we'd consider "NSObject **" a valid type for messaging,
+ which it isn't. */
+ type = TREE_TYPE (type);
+
+ if (TREE_CODE (type) != RECORD_TYPE)
+ return false;
+
+ if (objc_is_object_id (type))
+ return true;
+
+ if (objc_is_class_id (type))
+ return accept_classes;
+
+ if (TYPE_HAS_OBJC_INFO (type))
+ return true;
+
+ return false;
+}
+
/* Fold an OBJ_TYPE_REF expression for ObjC method dispatches, where
this occurs. ObjC method dispatches are _not_ like C++ virtual
member function dispatches, and we account for the difference here. */
@@ -12070,7 +8197,7 @@ objc_fold_obj_type_ref (tree ref ATTRIBUTE_UNUSED,
#endif
}
-static void
+void
objc_start_function (tree name, tree type, tree attrs,
#ifdef OBJCPLUS
tree params
@@ -12255,8 +8382,8 @@ get_super_receiver (void)
{
if (objc_method_context)
{
- tree super_expr, super_expr_list;
-
+ tree super_expr, super_expr_list, class_expr;
+ bool inst_meth;
if (!UOBJC_SUPER_decl)
{
UOBJC_SUPER_decl = build_decl (input_location,
@@ -12279,80 +8406,42 @@ get_super_receiver (void)
super_expr_list = super_expr;
/* Set class to begin searching. */
- super_expr = objc_build_component_ref (UOBJC_SUPER_decl,
- get_identifier ("super_class"));
+ /* Get the ident for the superclass class field & build a ref to it.
+ ??? maybe we should just name the field the same for all runtimes. */
+ super_expr = (*runtime.super_superclassfield_ident) ();
+ super_expr = objc_build_component_ref (UOBJC_SUPER_decl, super_expr);
- if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
- {
- /* [_cls, __cls]Super are "pre-built" in
- synth_forward_declarations. */
-
- super_expr = build_modify_expr (input_location, super_expr,
- NULL_TREE, NOP_EXPR,
- input_location,
- ((TREE_CODE (objc_method_context)
- == INSTANCE_METHOD_DECL)
- ? ucls_super_ref
- : uucls_super_ref),
- NULL_TREE);
- }
+ gcc_assert (imp_list->imp_context == objc_implementation_context
+ && imp_list->imp_template == implementation_template);
+ inst_meth = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL);
+ if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
+ class_expr = (*runtime.get_class_super_ref) (input_location,
+ imp_list, inst_meth);
else
/* We have a category. */
{
- tree super_name = CLASS_SUPER_NAME (implementation_template);
+ tree super_name = CLASS_SUPER_NAME (imp_list->imp_template);
tree super_class;
- /* Barf if super used in a category of Object. */
+ /* Barf if super used in a category of a root object. */
if (!super_name)
{
error ("no super class declared in interface for %qE",
- CLASS_NAME (implementation_template));
+ CLASS_NAME (imp_list->imp_template));
return error_mark_node;
}
- if (flag_next_runtime && !flag_zero_link)
- {
- super_class = objc_get_class_reference (super_name);
- if (TREE_CODE (objc_method_context) == CLASS_METHOD_DECL)
- /* 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);
- }
- else
- {
- add_class_reference (super_name);
- super_class = (TREE_CODE (objc_method_context) == INSTANCE_METHOD_DECL
- ? objc_get_class_decl : objc_get_meta_class_decl);
- assemble_external (super_class);
- super_class
- = build_function_call
- (input_location,
- super_class,
- build_tree_list
- (NULL_TREE,
- my_build_string_pointer
- (IDENTIFIER_LENGTH (super_name) + 1,
- IDENTIFIER_POINTER (super_name))));
- }
-
- super_expr
- = build_modify_expr (input_location, super_expr, NULL_TREE,
- NOP_EXPR,
- input_location,
- build_c_cast (input_location,
- TREE_TYPE (super_expr),
- super_class),
- NULL_TREE);
+ super_class = (*runtime.get_category_super_ref) (input_location,
+ imp_list, inst_meth);
+ class_expr = build_c_cast (input_location,
+ TREE_TYPE (super_expr), super_class);
}
+ super_expr = build_modify_expr (input_location, super_expr, NULL_TREE,
+ NOP_EXPR,
+ input_location, class_expr, NULL_TREE);
+
super_expr_list = build_compound_expr (input_location,
super_expr_list, super_expr);
@@ -12581,7 +8670,7 @@ gen_method_decl (tree method)
supplied file FP. Used to implement the -gen-decls option (which
prints out an @interface declaration of all classes compiled in
this run); potentially useful for debugging the compiler too. */
-static void
+void
dump_interface (FILE *fp, tree chain)
{
/* FIXME: A heap overflow here whenever a method (or ivar)
@@ -12856,313 +8945,6 @@ objc_printable_name (tree decl, int v)
return IDENTIFIER_POINTER (DECL_NAME (decl));
}
-static void
-init_objc (void)
-{
- gcc_obstack_init (&util_obstack);
- util_firstobj = (char *) obstack_finish (&util_obstack);
-
- errbuf = XNEWVEC (char, 1024 * 10);
- hash_init ();
- synth_module_prologue ();
-}
-
-static void
-finish_objc (void)
-{
- struct imp_entry *impent;
- tree chain;
- /* The internally generated initializers appear to have missing braces.
- Don't warn about this. */
- int save_warn_missing_braces = warn_missing_braces;
- warn_missing_braces = 0;
-
- /* A missing @end may not be detected by the parser. */
- if (objc_implementation_context)
- {
- warning (0, "%<@end%> missing in implementation context");
- finish_class (objc_implementation_context);
- objc_ivar_chain = NULL_TREE;
- objc_implementation_context = NULL_TREE;
- }
-
- /* Process the static instances here because initialization of objc_symtab
- depends on them. */
- if (objc_static_instances)
- generate_static_references ();
-
- /* forward declare categories */
- if (cat_count)
- forward_declare_categories ();
-
- for (impent = imp_list; impent; impent = impent->next)
- {
- objc_implementation_context = impent->imp_context;
- implementation_template = impent->imp_template;
-
- /* FIXME: This needs reworking to be more obvious. */
-
- UOBJC_CLASS_decl = impent->class_decl;
- UOBJC_METACLASS_decl = impent->meta_decl;
-
- /* Dump the @interface of each class as we compile it, if the
- -gen-decls option is in use. TODO: Dump the classes in the
- order they were found, rather than in reverse order as we
- are doing now. */
- if (flag_gen_declaration)
- {
- dump_interface (gen_declaration_file, objc_implementation_context);
- }
-
- if (TREE_CODE (objc_implementation_context) == CLASS_IMPLEMENTATION_TYPE)
- {
- /* all of the following reference the string pool... */
- generate_ivar_lists ();
- generate_dispatch_tables ();
- generate_shared_structures (impent);
- }
- else
- {
- generate_dispatch_tables ();
- generate_category (impent);
- }
-
- impent->class_decl = UOBJC_CLASS_decl;
- impent->meta_decl = UOBJC_METACLASS_decl;
- }
-
- /* If we are using an array of selectors, we must always
- finish up the array decl even if no selectors were used. */
- if (flag_next_runtime)
- build_next_selector_translation_table ();
- else
- build_gnu_selector_translation_table ();
-
- if (protocol_chain)
- generate_protocols ();
-
- if (flag_next_runtime)
- generate_objc_image_info ();
-
- if (imp_list || class_names_chain
- || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
- generate_objc_symtab_decl ();
-
- /* Arrange for ObjC data structures to be initialized at run time. */
- if (objc_implementation_context || class_names_chain || objc_static_instances
- || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
- {
- build_module_descriptor ();
-
- if (!flag_next_runtime)
- build_module_initializer_routine ();
- }
-
- /* Dump the class references. This forces the appropriate classes
- to be linked into the executable image, preserving unix archive
- semantics. This can be removed when we move to a more dynamically
- linked environment. */
-
- for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
- {
- handle_class_ref (chain);
- if (TREE_PURPOSE (chain))
- generate_classref_translation_entry (chain);
- }
-
- for (impent = imp_list; impent; impent = impent->next)
- handle_impent (impent);
-
- if (warn_selector)
- {
- int slot;
- hash hsh;
-
- /* Run through the selector hash tables and print a warning for any
- selector which has multiple methods. */
-
- for (slot = 0; slot < SIZEHASHTABLE; slot++)
- {
- for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
- check_duplicates (hsh, 0, 1);
- for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
- check_duplicates (hsh, 0, 0);
- }
- }
-
- warn_missing_braces = save_warn_missing_braces;
-}
-
-/* Subroutines of finish_objc. */
-
-static void
-generate_classref_translation_entry (tree chain)
-{
- tree expr, decl, type;
-
- decl = TREE_PURPOSE (chain);
- type = TREE_TYPE (decl);
-
- expr = add_objc_string (TREE_VALUE (chain), class_names);
- expr = convert (type, expr); /* cast! */
-
- /* This is a class reference. It is re-written by the runtime,
- but will be optimized away unless we force it. */
- DECL_PRESERVE_P (decl) = 1;
- finish_var_decl (decl, expr);
- return;
-}
-
-static void
-handle_class_ref (tree chain)
-{
- const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
- char *string = (char *) alloca (strlen (name) + 30);
- tree decl;
- tree exp;
-
- sprintf (string, "%sobjc_class_name_%s",
- (flag_next_runtime ? "." : "__"), name);
-
-#ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
- if (flag_next_runtime)
- {
- ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
- return;
- }
-#endif
-
- /* Make a decl for this name, so we can use its address in a tree. */
- decl = build_decl (input_location,
- VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node));
- DECL_EXTERNAL (decl) = 1;
- TREE_PUBLIC (decl) = 1;
- pushdecl (decl);
- finish_var_decl (decl, 0);
-
- /* Make a decl for the address. */
- sprintf (string, "%sobjc_class_ref_%s",
- (flag_next_runtime ? "." : "__"), name);
- exp = build1 (ADDR_EXPR, string_type_node, decl);
- decl = build_decl (input_location,
- VAR_DECL, get_identifier (string), string_type_node);
- TREE_STATIC (decl) = 1;
- TREE_USED (decl) = 1;
- DECL_READ_P (decl) = 1;
- DECL_ARTIFICIAL (decl) = 1;
- DECL_INITIAL (decl) = error_mark_node;
-
- /* We must force the reference. */
- DECL_PRESERVE_P (decl) = 1;
-
- pushdecl (decl);
- finish_var_decl (decl, exp);
-}
-
-static void
-handle_impent (struct imp_entry *impent)
-{
- char *string;
-
- objc_implementation_context = impent->imp_context;
- implementation_template = impent->imp_template;
-
- switch (TREE_CODE (impent->imp_context))
- {
- case CLASS_IMPLEMENTATION_TYPE:
- {
- const char *const class_name =
- IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
-
- string = (char *) alloca (strlen (class_name) + 30);
-
- sprintf (string, "%sobjc_class_name_%s",
- (flag_next_runtime ? "." : "__"), class_name);
- break;
- }
- case CATEGORY_IMPLEMENTATION_TYPE:
- {
- const char *const class_name =
- IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
- const char *const class_super_name =
- IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
-
- string = (char *) alloca (strlen (class_name)
- + strlen (class_super_name) + 30);
-
- /* Do the same for categories. Even though no references to
- these symbols are generated automatically by the compiler,
- it gives you a handle to pull them into an archive by
- hand. */
- sprintf (string, "*%sobjc_category_name_%s_%s",
- (flag_next_runtime ? "." : "__"), class_name, class_super_name);
- break;
- }
- default:
- return;
- }
-
-#ifdef ASM_DECLARE_CLASS_REFERENCE
- if (flag_next_runtime)
- {
- ASM_DECLARE_CLASS_REFERENCE (asm_out_file, string);
- return;
- }
- else
-#endif
- {
- tree decl, init;
-
- init = integer_zero_node;
- decl = build_decl (input_location,
- VAR_DECL, get_identifier (string), TREE_TYPE (init));
- TREE_PUBLIC (decl) = 1;
- TREE_READONLY (decl) = 1;
- TREE_USED (decl) = 1;
- TREE_CONSTANT (decl) = 1;
- DECL_CONTEXT (decl) = NULL_TREE;
- DECL_ARTIFICIAL (decl) = 1;
- TREE_STATIC (decl) = 1;
- DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */
- /* We must force the reference. */
- DECL_PRESERVE_P (decl) = 1;
-
- finish_var_decl(decl, init) ;
- }
-}
-
-/* The Fix-and-Continue functionality available in Mac OS X 10.3 and
- later requires that ObjC translation units participating in F&C be
- specially marked. The following routine accomplishes this. */
-
-/* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
-
-static void
-generate_objc_image_info (void)
-{
- tree decl;
- int flags
- = ((flag_replace_objc_classes && imp_count ? 1 : 0)
- | (flag_objc_gc ? 2 : 0));
- VEC(constructor_elt,gc) *v = NULL;
- tree array_type;
-
- if (!flags)
- return; /* No need for an image_info entry. */
-
- array_type = build_sized_array_type (integer_type_node, 2);
-
- decl = start_var_decl (array_type, "_OBJC_IMAGE_INFO");
-
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
- CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags));
- /* If we need this (determined above) it is because the runtime wants to
- refer to it in a manner hidden from the compiler. So we must force the
- output. */
- DECL_PRESERVE_P (decl) = 1;
- finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v));
-}
-
/* Routine is called to issue diagnostic when reference to a private
ivar is made and no other variable with same name is found in
current scope. */
@@ -13347,39 +9129,7 @@ objc_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
#endif
}
-/* This routine returns true if TYPE is a valid objc object type,
- suitable for messaging; false otherwise. If 'accept_class' is
- 'true', then a Class object is considered valid for messaging and
- 'true' is returned if 'type' refers to a Class. If 'accept_class'
- is 'false', then a Class object is not considered valid for
- messaging and 'false' is returned in that case. */
-
-static bool
-objc_type_valid_for_messaging (tree type, bool accept_classes)
-{
- if (!POINTER_TYPE_P (type))
- return false;
-
- /* Remove the pointer indirection; don't remove more than one
- otherwise we'd consider "NSObject **" a valid type for messaging,
- which it isn't. */
- type = TREE_TYPE (type);
-
- if (TREE_CODE (type) != RECORD_TYPE)
- return false;
-
- if (objc_is_object_id (type))
- return true;
-
- if (objc_is_class_id (type))
- return accept_classes;
-
- if (TYPE_HAS_OBJC_INFO (type))
- return true;
-
- return false;
-}
-
+/* --- FAST ENUMERATION --- */
/* Begin code generation for fast enumeration (foreach) ... */
/* Defines
@@ -13923,6 +9673,7 @@ objc_finish_foreach_loop (location_t location, tree object_expression, tree coll
/* Done by c-parser.c */
}
+/* --- SUPPORT FOR FORMAT ARG CHECKING --- */
/* Return true if we have an NxString object pointer. */
bool
@@ -13947,4 +9698,722 @@ objc_check_format_arg (tree ARG_UNUSED (format_arg),
{
}
+/* --- Encode --- */
+/* "Encode" a data type into a string, which grows in util_obstack.
+
+ The format is described in gcc/doc/objc.texi, section 'Type
+ encoding'.
+
+ Most of the encode_xxx functions have a 'type' argument, which is
+ the type to encode, and an integer 'curtype' argument, which is the
+ index in the encoding string of the beginning of the encoding of
+ the current type, and allows you to find what characters have
+ already been written for the current type (they are the ones in the
+ current encoding string starting from 'curtype').
+
+ For example, if we are encoding a method which returns 'int' and
+ takes a 'char **' argument, then when we get to the point of
+ encoding the 'char **' argument, the encoded string already
+ contains 'i12@0:4' (assuming a pointer size of 4 bytes). So,
+ 'curtype' will be set to 7 when starting to encode 'char **'.
+ During the whole of the encoding of 'char **', 'curtype' will be
+ fixed at 7, so the routine encoding the second pointer can find out
+ that it's actually encoding a pointer to a pointer by looking
+ backwards at what has already been encoded for the current type,
+ and seeing there is a "^" (meaning a pointer) in there.
+*/
+
+
+/* Encode type qualifiers encodes one of the "PQ" Objective-C
+ keywords, ie 'in', 'out', 'inout', 'bycopy', 'byref', 'oneway'.
+ 'const', instead, is encoded directly as part of the type.
+ */
+
+static void
+encode_type_qualifiers (tree declspecs)
+{
+ tree spec;
+
+ for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
+ {
+ /* FIXME: Shouldn't we use token->keyword here ? */
+ if (ridpointers[(int) RID_IN] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'n');
+ else if (ridpointers[(int) RID_INOUT] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'N');
+ else if (ridpointers[(int) RID_OUT] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'o');
+ else if (ridpointers[(int) RID_BYCOPY] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'O');
+ else if (ridpointers[(int) RID_BYREF] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'R');
+ else if (ridpointers[(int) RID_ONEWAY] == TREE_VALUE (spec))
+ obstack_1grow (&util_obstack, 'V');
+ else
+ gcc_unreachable ();
+ }
+}
+
+/* Determine if a pointee is marked read-only. Only used by the NeXT
+ runtime to be compatible with gcc-3.3. */
+
+static bool
+pointee_is_readonly (tree pointee)
+{
+ while (POINTER_TYPE_P (pointee))
+ pointee = TREE_TYPE (pointee);
+
+ return TYPE_READONLY (pointee);
+}
+
+/* Encode a pointer type. */
+
+static void
+encode_pointer (tree type, int curtype, int format)
+{
+ tree pointer_to = TREE_TYPE (type);
+
+ if (flag_next_runtime)
+ {
+ /* This code is used to be compatible with gcc-3.3. */
+ /* For historical/compatibility reasons, the read-only qualifier
+ of the pointee gets emitted _before_ the '^'. The read-only
+ qualifier of the pointer itself gets ignored, _unless_ we are
+ looking at a typedef! Also, do not emit the 'r' for anything
+ but the outermost type! */
+ if (!generating_instance_variables
+ && (obstack_object_size (&util_obstack) - curtype <= 1)
+ && (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ ? TYPE_READONLY (type)
+ : pointee_is_readonly (pointer_to)))
+ obstack_1grow (&util_obstack, 'r');
+ }
+
+ if (TREE_CODE (pointer_to) == RECORD_TYPE)
+ {
+ if (OBJC_TYPE_NAME (pointer_to)
+ && TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
+ {
+ const char *name = IDENTIFIER_POINTER (OBJC_TYPE_NAME (pointer_to));
+
+ if (strcmp (name, TAG_OBJECT) == 0) /* '@' */
+ {
+ obstack_1grow (&util_obstack, '@');
+ return;
+ }
+ else if (TYPE_HAS_OBJC_INFO (pointer_to)
+ && TYPE_OBJC_INTERFACE (pointer_to))
+ {
+ if (generating_instance_variables)
+ {
+ obstack_1grow (&util_obstack, '@');
+ obstack_1grow (&util_obstack, '"');
+ obstack_grow (&util_obstack, name, strlen (name));
+ obstack_1grow (&util_obstack, '"');
+ return;
+ }
+ else
+ {
+ obstack_1grow (&util_obstack, '@');
+ return;
+ }
+ }
+ else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
+ {
+ obstack_1grow (&util_obstack, '#');
+ return;
+ }
+ else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
+ {
+ obstack_1grow (&util_obstack, ':');
+ return;
+ }
+ }
+ }
+ else if (TREE_CODE (pointer_to) == INTEGER_TYPE
+ && TYPE_MODE (pointer_to) == QImode)
+ {
+ tree pname = TREE_CODE (OBJC_TYPE_NAME (pointer_to)) == IDENTIFIER_NODE
+ ? OBJC_TYPE_NAME (pointer_to)
+ : DECL_NAME (OBJC_TYPE_NAME (pointer_to));
+
+ /* (BOOL *) are an exception and are encoded as ^c, while all
+ other pointers to char are encoded as *. */
+ if (strcmp (IDENTIFIER_POINTER (pname), "BOOL"))
+ {
+ if (!flag_next_runtime)
+ {
+ /* The NeXT runtime adds the 'r' before getting here. */
+
+ /* It appears that "r*" means "const char *" rather than
+ "char *const". "char *const" is encoded as "*",
+ which is identical to "char *", so the "const" is
+ unfortunately lost. */
+ if (TYPE_READONLY (pointer_to))
+ obstack_1grow (&util_obstack, 'r');
+ }
+
+ obstack_1grow (&util_obstack, '*');
+ return;
+ }
+ }
+
+ /* We have a normal pointer type that does not get special treatment. */
+ obstack_1grow (&util_obstack, '^');
+ encode_type (pointer_to, curtype, format);
+}
+
+static void
+encode_array (tree type, int curtype, int format)
+{
+ tree an_int_cst = TYPE_SIZE (type);
+ tree array_of = TREE_TYPE (type);
+ char buffer[40];
+
+ if (an_int_cst == NULL)
+ {
+ /* We are trying to encode an incomplete array. An incomplete
+ array is forbidden as part of an instance variable. */
+ if (generating_instance_variables)
+ {
+ /* TODO: Detect this error earlier. */
+ error ("instance variable has unknown size");
+ return;
+ }
+
+ /* So the only case in which an incomplete array could occur is
+ if we are encoding the arguments or return value of a method.
+ In that case, an incomplete array argument or return value
+ (eg, -(void)display: (char[])string) is treated like a
+ pointer because that is how the compiler does the function
+ call. A special, more complicated case, is when the
+ incomplete array is the last member of a struct (eg, if we
+ are encoding "struct { unsigned long int a;double b[];}"),
+ which is again part of a method argument/return value. In
+ that case, we really need to communicate to the runtime that
+ there is an incomplete array (not a pointer!) there. So, we
+ detect that special case and encode it as a zero-length
+ array.
+
+ Try to detect that we are part of a struct. We do this by
+ searching for '=' in the type encoding for the current type.
+ NB: This hack assumes that you can't use '=' as part of a C
+ identifier.
+ */
+ {
+ char *enc = obstack_base (&util_obstack) + curtype;
+ if (memchr (enc, '=',
+ obstack_object_size (&util_obstack) - curtype) == NULL)
+ {
+ /* We are not inside a struct. Encode the array as a
+ pointer. */
+ encode_pointer (type, curtype, format);
+ return;
+ }
+ }
+
+ /* Else, we are in a struct, and we encode it as a zero-length
+ array. */
+ sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
+ }
+ else if (TREE_INT_CST_LOW (TYPE_SIZE (array_of)) == 0)
+ sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)0);
+ else
+ sprintf (buffer, "[" HOST_WIDE_INT_PRINT_DEC,
+ TREE_INT_CST_LOW (an_int_cst)
+ / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
+
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+ encode_type (array_of, curtype, format);
+ obstack_1grow (&util_obstack, ']');
+ return;
+}
+
+/* Encode a vector. The vector type is a GCC extension to C. */
+static void
+encode_vector (tree type, int curtype, int format)
+{
+ tree vector_of = TREE_TYPE (type);
+ char buffer[40];
+
+ /* Vectors are like simple fixed-size arrays. */
+
+ /* Output ![xx,yy,<code>] where xx is the vector_size, yy is the
+ alignment of the vector, and <code> is the base type. Eg, int
+ __attribute__ ((vector_size (16))) gets encoded as ![16,32,i]
+ assuming that the alignment is 32 bytes. We include size and
+ alignment in bytes so that the runtime does not have to have any
+ knowledge of the actual types.
+ */
+ sprintf (buffer, "![" HOST_WIDE_INT_PRINT_DEC ",%d",
+ /* We want to compute the equivalent of sizeof (<vector>).
+ Code inspired by c_sizeof_or_alignof_type. */
+ ((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type))
+ / (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT))),
+ /* We want to compute the equivalent of __alignof__
+ (<vector>). Code inspired by
+ c_sizeof_or_alignof_type. */
+ TYPE_ALIGN_UNIT (type));
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+ encode_type (vector_of, curtype, format);
+ obstack_1grow (&util_obstack, ']');
+ return;
+}
+
+static void
+encode_aggregate_fields (tree type, bool pointed_to, int curtype, int format)
+{
+ tree field = TYPE_FIELDS (type);
+
+ for (; field; field = DECL_CHAIN (field))
+ {
+#ifdef OBJCPLUS
+ /* C++ static members, and things that are not field at all,
+ should not appear in the encoding. */
+ if (TREE_CODE (field) != FIELD_DECL || TREE_STATIC (field))
+ continue;
+#endif
+
+ /* Recursively encode fields of embedded base classes. */
+ if (DECL_ARTIFICIAL (field) && !DECL_NAME (field)
+ && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
+ {
+ encode_aggregate_fields (TREE_TYPE (field),
+ pointed_to, curtype, format);
+ continue;
+ }
+
+ if (generating_instance_variables && !pointed_to)
+ {
+ tree fname = DECL_NAME (field);
+
+ obstack_1grow (&util_obstack, '"');
+
+ if (fname && TREE_CODE (fname) == IDENTIFIER_NODE)
+ obstack_grow (&util_obstack,
+ IDENTIFIER_POINTER (fname),
+ strlen (IDENTIFIER_POINTER (fname)));
+
+ obstack_1grow (&util_obstack, '"');
+ }
+
+ encode_field_decl (field, curtype, format);
+ }
+}
+
+static void
+encode_aggregate_within (tree type, int curtype, int format, int left,
+ int right)
+{
+ tree name;
+ /* NB: aggregates that are pointed to have slightly different encoding
+ rules in that you never encode the names of instance variables. */
+ int ob_size = obstack_object_size (&util_obstack);
+ bool inline_contents = false;
+ bool pointed_to = false;
+
+ if (flag_next_runtime)
+ {
+ if (ob_size > 0 && *(obstack_next_free (&util_obstack) - 1) == '^')
+ pointed_to = true;
+
+ if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
+ && (!pointed_to || ob_size - curtype == 1
+ || (ob_size - curtype == 2
+ && *(obstack_next_free (&util_obstack) - 2) == 'r')))
+ inline_contents = true;
+ }
+ else
+ {
+ /* c0 and c1 are the last two characters in the encoding of the
+ current type; if the last two characters were '^' or '^r',
+ then we are encoding an aggregate that is "pointed to". The
+ comment above applies: in that case we should avoid encoding
+ the names of instance variables.
+ */
+ char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
+ char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
+
+ if (c0 == '^' || (c1 == '^' && c0 == 'r'))
+ pointed_to = true;
+
+ if (format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
+ {
+ if (!pointed_to)
+ inline_contents = true;
+ else
+ {
+ /* Note that the check (ob_size - curtype < 2) prevents
+ infinite recursion when encoding a structure which is
+ a linked list (eg, struct node { struct node *next;
+ }). Each time we follow a pointer, we add one
+ character to ob_size, and curtype is fixed, so after
+ at most two pointers we stop inlining contents and
+ break the loop.
+
+ The other case where we don't inline is "^r", which
+ is a pointer to a constant struct.
+ */
+ if ((ob_size - curtype <= 2) && !(c0 == 'r'))
+ inline_contents = true;
+ }
+ }
+ }
+
+ /* Traverse struct aliases; it is important to get the
+ original struct and its tag name (if any). */
+ type = TYPE_MAIN_VARIANT (type);
+ name = OBJC_TYPE_NAME (type);
+ /* Open parenth/bracket. */
+ obstack_1grow (&util_obstack, left);
+
+ /* Encode the struct/union tag name, or '?' if a tag was
+ not provided. Typedef aliases do not qualify. */
+#ifdef OBJCPLUS
+ /* For compatibility with the NeXT runtime, ObjC++ encodes template
+ args as a composite struct tag name. */
+ if (name && TREE_CODE (name) == IDENTIFIER_NODE
+ /* Did this struct have a tag? */
+ && !TYPE_WAS_ANONYMOUS (type))
+ obstack_grow (&util_obstack,
+ decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME),
+ strlen (decl_as_string (type, TFF_DECL_SPECIFIERS | TFF_UNQUALIFIED_NAME)));
+#else
+ if (name && TREE_CODE (name) == IDENTIFIER_NODE)
+ obstack_grow (&util_obstack,
+ IDENTIFIER_POINTER (name),
+ strlen (IDENTIFIER_POINTER (name)));
+#endif
+ else
+ obstack_1grow (&util_obstack, '?');
+
+ /* Encode the types (and possibly names) of the inner fields,
+ if required. */
+ if (inline_contents)
+ {
+ obstack_1grow (&util_obstack, '=');
+ encode_aggregate_fields (type, pointed_to, curtype, format);
+ }
+ /* Close parenth/bracket. */
+ obstack_1grow (&util_obstack, right);
+}
+
+/* Encode a bitfield NeXT-style (i.e., without a bit offset or the underlying
+ field type. */
+
+static void
+encode_next_bitfield (int width)
+{
+ char buffer[40];
+ sprintf (buffer, "b%d", width);
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+}
+
+/* Encodes 'type', ignoring type qualifiers (which you should encode
+ beforehand if needed) with the exception of 'const', which is
+ encoded by encode_type. See above for the explanation of
+ 'curtype'. 'format' can be OBJC_ENCODE_INLINE_DEFS or
+ OBJC_ENCODE_DONT_INLINE_DEFS.
+*/
+static void
+encode_type (tree type, int curtype, int format)
+{
+ enum tree_code code = TREE_CODE (type);
+
+ /* Ignore type qualifiers other than 'const' when encoding a
+ type. */
+
+ if (type == error_mark_node)
+ return;
+
+ if (!flag_next_runtime)
+ {
+ if (TYPE_READONLY (type))
+ obstack_1grow (&util_obstack, 'r');
+ }
+
+ switch (code)
+ {
+ case ENUMERAL_TYPE:
+ if (flag_next_runtime)
+ {
+ /* Kludge for backwards-compatibility with gcc-3.3: enums
+ are always encoded as 'i' no matter what type they
+ actually are (!). */
+ obstack_1grow (&util_obstack, 'i');
+ break;
+ }
+ /* Else, they are encoded exactly like the integer type that is
+ used by the compiler to store them. */
+ case INTEGER_TYPE:
+ {
+ char c;
+ switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+ {
+ case 8: c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
+ case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
+ case 32:
+ {
+ tree int_type = type;
+ if (flag_next_runtime)
+ {
+ /* Another legacy kludge for compatiblity with
+ gcc-3.3: 32-bit longs are encoded as 'l' or 'L',
+ but not always. For typedefs, we need to use 'i'
+ or 'I' instead if encoding a struct field, or a
+ pointer! */
+ int_type = ((!generating_instance_variables
+ && (obstack_object_size (&util_obstack)
+ == (unsigned) curtype))
+ ? TYPE_MAIN_VARIANT (type)
+ : type);
+ }
+ if (int_type == long_unsigned_type_node
+ || int_type == long_integer_type_node)
+ c = TYPE_UNSIGNED (type) ? 'L' : 'l';
+ else
+ c = TYPE_UNSIGNED (type) ? 'I' : 'i';
+ }
+ break;
+ case 64: c = TYPE_UNSIGNED (type) ? 'Q' : 'q'; break;
+ case 128: c = TYPE_UNSIGNED (type) ? 'T' : 't'; break;
+ default: gcc_unreachable ();
+ }
+ obstack_1grow (&util_obstack, c);
+ break;
+ }
+ case REAL_TYPE:
+ {
+ char c;
+ /* Floating point types. */
+ switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+ {
+ case 32: c = 'f'; break;
+ case 64: c = 'd'; break;
+ case 96:
+ case 128: c = 'D'; break;
+ default: gcc_unreachable ();
+ }
+ obstack_1grow (&util_obstack, c);
+ break;
+ }
+ case VOID_TYPE:
+ obstack_1grow (&util_obstack, 'v');
+ break;
+
+ case BOOLEAN_TYPE:
+ obstack_1grow (&util_obstack, 'B');
+ break;
+
+ case ARRAY_TYPE:
+ encode_array (type, curtype, format);
+ break;
+
+ case POINTER_TYPE:
+#ifdef OBJCPLUS
+ case REFERENCE_TYPE:
+#endif
+ encode_pointer (type, curtype, format);
+ break;
+
+ case RECORD_TYPE:
+ encode_aggregate_within (type, curtype, format, '{', '}');
+ break;
+
+ case UNION_TYPE:
+ encode_aggregate_within (type, curtype, format, '(', ')');
+ break;
+
+ case FUNCTION_TYPE: /* '?' means an unknown type. */
+ obstack_1grow (&util_obstack, '?');
+ break;
+
+ case COMPLEX_TYPE:
+ /* A complex is encoded as 'j' followed by the inner type (eg,
+ "_Complex int" is encoded as 'ji'). */
+ obstack_1grow (&util_obstack, 'j');
+ encode_type (TREE_TYPE (type), curtype, format);
+ break;
+
+ case VECTOR_TYPE:
+ encode_vector (type, curtype, format);
+ break;
+
+ default:
+ warning (0, "unknown type %s found during Objective-C encoding",
+ gen_type_name (type));
+ obstack_1grow (&util_obstack, '?');
+ break;
+ }
+
+ if (flag_next_runtime)
+ {
+ /* Super-kludge. Some ObjC qualifier and type combinations need
+ to be rearranged for compatibility with gcc-3.3. */
+ if (code == POINTER_TYPE && obstack_object_size (&util_obstack) >= 3)
+ {
+ char *enc = obstack_base (&util_obstack) + curtype;
+
+ /* Rewrite "in const" from "nr" to "rn". */
+ if (curtype >= 1 && !strncmp (enc - 1, "nr", 2))
+ strncpy (enc - 1, "rn", 2);
+ }
+ }
+}
+
+static void
+encode_gnu_bitfield (int position, tree type, int size)
+{
+ enum tree_code code = TREE_CODE (type);
+ char buffer[40];
+ char charType = '?';
+
+ /* This code is only executed for the GNU runtime, so we can ignore
+ the NeXT runtime kludge of always encoding enums as 'i' no matter
+ what integers they actually are. */
+ if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
+ {
+ if (integer_zerop (TYPE_MIN_VALUE (type)))
+ /* Unsigned integer types. */
+ {
+ switch (TYPE_MODE (type))
+ {
+ case QImode:
+ charType = 'C'; break;
+ case HImode:
+ charType = 'S'; break;
+ case SImode:
+ {
+ if (type == long_unsigned_type_node)
+ charType = 'L';
+ else
+ charType = 'I';
+ break;
+ }
+ case DImode:
+ charType = 'Q'; break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ /* Signed integer types. */
+ {
+ switch (TYPE_MODE (type))
+ {
+ case QImode:
+ charType = 'c'; break;
+ case HImode:
+ charType = 's'; break;
+ case SImode:
+ {
+ if (type == long_integer_type_node)
+ charType = 'l';
+ else
+ charType = 'i';
+ break;
+ }
+ case DImode:
+ charType = 'q'; break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ }
+ else
+ {
+ /* Do not do any encoding, produce an error and keep going. */
+ error ("trying to encode non-integer type as a bitfield");
+ return;
+ }
+
+ sprintf (buffer, "b%d%c%d", position, charType, size);
+ obstack_grow (&util_obstack, buffer, strlen (buffer));
+}
+
+void
+encode_field_decl (tree field_decl, int curtype, int format)
+{
+#ifdef OBJCPLUS
+ /* C++ static members, and things that are not fields at all,
+ should not appear in the encoding. */
+ if (TREE_CODE (field_decl) != FIELD_DECL || TREE_STATIC (field_decl))
+ return;
+#endif
+
+ /* Generate the bitfield typing information, if needed. Note the difference
+ between GNU and NeXT runtimes. */
+ if (DECL_BIT_FIELD_TYPE (field_decl))
+ {
+ int size = tree_low_cst (DECL_SIZE (field_decl), 1);
+
+ if (flag_next_runtime)
+ encode_next_bitfield (size);
+ else
+ encode_gnu_bitfield (int_bit_position (field_decl),
+ DECL_BIT_FIELD_TYPE (field_decl), size);
+ }
+ else
+ encode_type (TREE_TYPE (field_decl), curtype, format);
+}
+
+/* This routine encodes the attribute of the input PROPERTY according to following
+ formula:
+
+Property attributes are stored as a comma-delimited C string. The simple attributes
+readonly and copies are encoded as single characters. The parametrized attributes,
+getter=name, setter=name, and ivar=name, are encoded as single characters, followed
+by an identifier. Property types are also encoded as a parametrized attribute. The
+characters used to encode these attributes are defined by the following enumeration:
+
+enum PropertyAttributes {
+ kPropertyReadOnly = 'r', // property is read-only.
+ kPropertyCopies = 'c', // property is a copy of the value last assigned
+ kPropertyGetter = 'g', // followed by getter selector name
+ kPropertySetter = 's', // followed by setter selector name
+ kPropertyInstanceVariable = 'i' // followed by instance variable name
+ kPropertyType = 't' // followed by old-style type encoding.
+};
+
+*/
+
+tree
+objc_v2_encode_prop_attr (tree property)
+{
+ const char *string;
+ tree type = TREE_TYPE (property);
+ obstack_1grow (&util_obstack, 't');
+ encode_type (type, obstack_object_size (&util_obstack),
+ OBJC_ENCODE_INLINE_DEFS);
+ if (PROPERTY_READONLY (property))
+ obstack_grow (&util_obstack, ",r", 2);
+
+ if (PROPERTY_ASSIGN_SEMANTICS (property) == OBJC_PROPERTY_COPY)
+ obstack_grow (&util_obstack, ",c", 2);
+
+ if (PROPERTY_GETTER_NAME (property))
+ {
+ obstack_grow (&util_obstack, ",g", 2);
+ string = IDENTIFIER_POINTER (PROPERTY_GETTER_NAME (property));
+ obstack_grow (&util_obstack, string, strlen (string));
+ }
+ if (PROPERTY_SETTER_NAME (property))
+ {
+ obstack_grow (&util_obstack, ",s", 2);
+ string = IDENTIFIER_POINTER (PROPERTY_SETTER_NAME (property));
+ obstack_grow (&util_obstack, string, strlen (string));
+ }
+ if (PROPERTY_IVAR_NAME (property))
+ {
+ obstack_grow (&util_obstack, ",i", 2);
+ string = IDENTIFIER_POINTER (PROPERTY_IVAR_NAME (property));
+ obstack_grow (&util_obstack, string, strlen (string));
+ }
+
+ obstack_1grow (&util_obstack, 0); /* null terminate string */
+ string = XOBFINISH (&util_obstack, char *);
+ obstack_free (&util_obstack, util_firstobj);
+ return get_identifier (string);
+}
+
#include "gt-objc-objc-act.h"
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index b7d8403..f45b4ea 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -1,6 +1,6 @@
/* Declarations for objc-act.c.
Copyright (C) 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009,
- 2010 Free Software Foundation, Inc.
+ 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -28,8 +28,6 @@ bool objc_init (void);
const char *objc_printable_name (tree, int);
tree objc_fold_obj_type_ref (tree, tree);
int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
-tree objc_eh_runtime_type (tree);
-tree objc_eh_personality (void);
/* NB: The remaining public functions are prototyped in c-common.h, for the
benefit of stub-objc.c and objc-act.c. */
@@ -167,6 +165,8 @@ typedef enum objc_property_assign_semantics {
#define CLASS_PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 4)
#define TOTAL_CLASS_RAW_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 5)
+#define CLASS_HAS_EXCEPTION_ATTR(CLASS) ((CLASS)->type.lang_flag_0)
+
#define PROTOCOL_NAME(CLASS) ((CLASS)->type.name)
#define PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0)
#define PROTOCOL_NST_METHODS(CLASS) ((CLASS)->type.minval)
@@ -176,7 +176,6 @@ typedef enum objc_property_assign_semantics {
#define PROTOCOL_OPTIONAL_CLS_METHODS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 2)
#define PROTOCOL_OPTIONAL_NST_METHODS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 3)
-
/* For CATEGORY_INTERFACE_TYPE, CLASS_INTERFACE_TYPE or PROTOCOL_INTERFACE_TYPE */
#define CLASS_PROPERTY_DECL(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 6)
/* For CLASS_IMPLEMENTATION_TYPE or CATEGORY_IMPLEMENTATION_TYPE. */
@@ -215,6 +214,7 @@ typedef enum objc_property_assign_semantics {
= make_tree_vec (OBJC_INFO_SLOT_ELTS); \
} \
while (0)
+
#define DUP_TYPE_OBJC_INFO(DST, SRC) \
do \
{ \
@@ -244,20 +244,21 @@ struct GTY(()) hashed_attribute {
attr next;
tree value;
};
+
struct GTY(()) hashed_entry {
attr list;
hash next;
tree key;
};
+#define SIZEHASHTABLE 257
+
extern GTY ((length ("SIZEHASHTABLE"))) hash *nst_method_hash_list;
extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_method_hash_list;
extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_name_hash_list;
extern GTY ((length ("SIZEHASHTABLE"))) hash *als_name_hash_list;
-#define SIZEHASHTABLE 257
-
/* An array of all the local variables in the current function that
need to be marked as volatile. */
extern GTY(()) VEC(tree,gc) *local_variables_to_volatilize;
@@ -268,8 +269,8 @@ struct GTY(()) imp_entry {
struct imp_entry *next;
tree imp_context;
tree imp_template;
- tree class_decl; /* _OBJC_CLASS_<my_name>; */
- tree meta_decl; /* _OBJC_METACLASS_<my_name>; */
+ tree class_decl; /* _OBJC[_v2]_CLASS/CATEGORY_<my_name>; */
+ tree meta_decl; /* _OBJC[_v2]_METACLASS_<my_name>; */
BOOL_BITFIELD has_cxx_cdtors : 1;
};
@@ -361,6 +362,7 @@ enum objc_tree_index
OCTI_STRING_CLASS_DECL,
OCTI_INTERNAL_CNST_STR_TYPE,
OCTI_SUPER_DECL,
+ OCTI_SUPER_SUPERFIELD_ID,
OCTI_UMSG_NONNIL_DECL,
OCTI_UMSG_NONNIL_STRET_DECL,
OCTI_STORAGE_CLS,
@@ -394,6 +396,10 @@ enum objc_tree_index
OCTI_GET_PROPERTY_STRUCT_DECL,
OCTI_SET_PROPERTY_STRUCT_DECL,
+ /* "V1" stuff. */
+ OCTI_V1_PROP_LIST_TEMPL,
+ OCTI_V1_PROP_NAME_ATTR_CHAIN,
+
OCTI_MAX
};
@@ -433,14 +439,17 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
(TREE_CODE (TYPE) == POINTER_TYPE \
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TYPE)) \
== TREE_TYPE (objc_object_type)))
+
#define IS_CLASS(TYPE) \
(TREE_CODE (TYPE) == POINTER_TYPE \
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TYPE)) \
== TREE_TYPE (objc_class_type)))
+
#define IS_PROTOCOL_QUALIFIED_UNTYPED(TYPE) \
((IS_ID (TYPE) || IS_CLASS (TYPE)) \
&& TYPE_HAS_OBJC_INFO (TREE_TYPE (TYPE)) \
&& TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (TYPE)))
+
#define IS_SUPER(TYPE) \
(TREE_CODE (TYPE) == POINTER_TYPE \
&& TREE_TYPE (TYPE) == objc_super_template)
@@ -549,13 +558,19 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define objc_class_id objc_global_trees[OCTI_CLS_ID]
#define objc_object_name objc_global_trees[OCTI_ID_NAME]
#define objc_class_name objc_global_trees[OCTI_CLASS_NAME]
+
+/* Constant string classes. */
#define constant_string_id objc_global_trees[OCTI_CNST_STR_ID]
#define constant_string_type objc_global_trees[OCTI_CNST_STR_TYPE]
#define constant_string_global_id \
objc_global_trees[OCTI_CNST_STR_GLOB_ID]
#define string_class_decl objc_global_trees[OCTI_STRING_CLASS_DECL]
#define internal_const_str_type objc_global_trees[OCTI_INTERNAL_CNST_STR_TYPE]
+
#define UOBJC_SUPER_decl objc_global_trees[OCTI_SUPER_DECL]
+#define super_superclassfield_id \
+ objc_global_trees[OCTI_SUPER_SUPERFIELD_ID]
+
#define objc_fast_enumeration_state_template \
objc_global_trees[OCTI_FAST_ENUM_STATE_TEMP]
#define objc_enumeration_mutation_decl \
@@ -563,11 +578,168 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
/* Declarations of functions used when synthesizing property
accessors. */
-#define objc_getProperty_decl objc_global_trees[OCTI_GET_PROPERTY_DECL]
-#define objc_setProperty_decl objc_global_trees[OCTI_SET_PROPERTY_DECL]
-#define objc_copyStruct_decl objc_global_trees[OCTI_COPY_STRUCT_DECL]
-#define objc_getPropertyStruct_decl objc_global_trees[OCTI_GET_PROPERTY_STRUCT_DECL]
-#define objc_setPropertyStruct_decl objc_global_trees[OCTI_SET_PROPERTY_STRUCT_DECL]
+#define objc_getProperty_decl objc_global_trees[OCTI_GET_PROPERTY_DECL]
+#define objc_setProperty_decl objc_global_trees[OCTI_SET_PROPERTY_DECL]
+#define objc_copyStruct_decl objc_global_trees[OCTI_COPY_STRUCT_DECL]
+#define objc_getPropertyStruct_decl \
+ objc_global_trees[OCTI_GET_PROPERTY_STRUCT_DECL]
+#define objc_setPropertyStruct_decl \
+ objc_global_trees[OCTI_SET_PROPERTY_STRUCT_DECL]
+
+/* V1 stuff. */
+#define objc_prop_list_ptr objc_global_trees[OCTI_V1_PROP_LIST_TEMPL]
+#define prop_names_attr_chain objc_global_trees[OCTI_V1_PROP_NAME_ATTR_CHAIN]
+
+/* Reserved tag definitions. */
+
+#define OBJECT_TYPEDEF_NAME "id"
+#define CLASS_TYPEDEF_NAME "Class"
+
+#define TAG_OBJECT "objc_object"
+#define TAG_CLASS "objc_class"
+#define TAG_SUPER "objc_super"
+#define TAG_SELECTOR "objc_selector"
+
+#define UTAG_CLASS "_objc_class"
+#define UTAG_IVAR "_objc_ivar"
+#define UTAG_IVAR_LIST "_objc_ivar_list"
+#define UTAG_METHOD "_objc_method"
+#define UTAG_METHOD_LIST "_objc_method_list"
+#define UTAG_CATEGORY "_objc_category"
+#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_METHOD_PROTOTYPE "_objc_method_prototype"
+#define UTAG_METHOD_PROTOTYPE_LIST "_objc__method_prototype_list"
+
+#define PROTOCOL_OBJECT_CLASS_NAME "Protocol"
+
+#define TAG_EXCEPTIONTHROW "objc_exception_throw"
+#define TAG_SYNCENTER "objc_sync_enter"
+#define TAG_SYNCEXIT "objc_sync_exit"
+
+/* Really should be NeXT private. */
+#define UTAG_EXCDATA "_objc_exception_data"
+
+#define TAG_CXX_CONSTRUCT ".cxx_construct"
+#define TAG_CXX_DESTRUCT ".cxx_destruct"
+
+#define TAG_ENUMERATION_MUTATION "objc_enumerationMutation"
+#define TAG_FAST_ENUMERATION_STATE "__objcFastEnumerationState"
+
+typedef enum string_section
+{
+ class_names, /* class, category, protocol, module names */
+ meth_var_names, /* method and variable names */
+ meth_var_types, /* method and variable type descriptors */
+ prop_names_attr /* property names and their attributes. */
+} string_section;
+
+#define METHOD_DEF 0
+#define METHOD_REF 1
+
+/* (Decide if these can ever be validly changed.) */
+#define OBJC_ENCODE_INLINE_DEFS 0
+#define OBJC_ENCODE_DONT_INLINE_DEFS 1
+
+#define BUFSIZE 1024
+#define CLS_FACTORY 0x0001L
+#define CLS_META 0x0002L
+
+/* Runtime metadata flags - ??? apparently unused. */
+
+#define OBJC_MODIFIER_STATIC 0x00000001
+#define OBJC_MODIFIER_FINAL 0x00000002
+#define OBJC_MODIFIER_PUBLIC 0x00000004
+#define OBJC_MODIFIER_PRIVATE 0x00000008
+#define OBJC_MODIFIER_PROTECTED 0x00000010
+#define OBJC_MODIFIER_NATIVE 0x00000020
+#define OBJC_MODIFIER_SYNCHRONIZED 0x00000040
+#define OBJC_MODIFIER_ABSTRACT 0x00000080
+#define OBJC_MODIFIER_VOLATILE 0x00000100
+#define OBJC_MODIFIER_TRANSIENT 0x00000200
+#define OBJC_MODIFIER_NONE_SPECIFIED 0x80000000
+
+#define OBJC_VOID_AT_END void_list_node
+
+/* Exception handling constructs. We begin by having the parser do most
+ of the work and passing us blocks.
+ This allows us to handle different exceptions implementations. */
+
+/* Stack of open try blocks. */
+
+struct objc_try_context
+{
+ struct objc_try_context *outer;
+
+ /* Statements (or statement lists) as processed by the parser. */
+ tree try_body;
+ tree finally_body;
+
+ /* Some file position locations. */
+ location_t try_locus;
+ location_t end_try_locus;
+ location_t end_catch_locus;
+ location_t finally_locus;
+ location_t end_finally_locus;
+
+ /* A STATEMENT_LIST of CATCH_EXPRs, appropriate for sticking into op1
+ of a TRY_CATCH_EXPR. Even when doing Darwin setjmp. */
+ tree catch_list;
+
+ /* The CATCH_EXPR of an open @catch clause. */
+ tree current_catch;
+
+ /* The VAR_DECL holding __builtin_eh_pointer (or equivalent). */
+ tree caught_decl;
+ tree stack_decl;
+ tree rethrow_decl;
+};
+
+/* A small number of routines used by the FE parser and the runtime code
+ generators. Put here as inlines for efficiency in non-lto builds rather
+ than making them externs. */
+
+extern tree objc_create_temporary_var (tree, const char *);
+
+#define objc_is_object_id(TYPE) (OBJC_TYPE_NAME (TYPE) == objc_object_id)
+#define objc_is_class_id(TYPE) (OBJC_TYPE_NAME (TYPE) == objc_class_id)
+
+/* Retrieve category interface CAT_NAME (if any) associated with CLASS. */
+static inline tree
+lookup_category (tree klass, tree cat_name)
+{
+ tree category = CLASS_CATEGORY_LIST (klass);
+
+ while (category && CLASS_SUPER_NAME (category) != cat_name)
+ category = CLASS_CATEGORY_LIST (category);
+ return category;
+}
+
+/* Count only the fields occurring in T. */
+static inline int
+ivar_list_length (tree t)
+{
+ int count = 0;
+
+ for (; t; t = DECL_CHAIN (t))
+ if (TREE_CODE (t) == FIELD_DECL)
+ ++count;
+
+ return count;
+}
+
+static inline tree
+is_ivar (tree decl_chain, tree ident)
+{
+ for ( ; decl_chain; decl_chain = DECL_CHAIN (decl_chain))
+ if (DECL_NAME (decl_chain) == ident)
+ return decl_chain;
+ return NULL_TREE;
+}
#endif /* GCC_OBJC_ACT_H */
diff --git a/gcc/objc/objc-gnu-runtime-abi-01.c b/gcc/objc/objc-gnu-runtime-abi-01.c
new file mode 100644
index 0000000..a13f015
--- /dev/null
+++ b/gcc/objc/objc-gnu-runtime-abi-01.c
@@ -0,0 +1,2265 @@
+/* GNU Runtime (ABI-0/1) private.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Iain Sandoe (split from objc-act.c)
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+
+#ifdef OBJCPLUS
+#include "cp-tree.h"
+#else
+#include "c-tree.h"
+#include "c-lang.h"
+#endif
+
+#include "langhooks.h"
+#include "c-family/c-objc.h"
+#include "objc-act.h"
+
+/* When building Objective-C++, we are not linking against the C front-end
+ and so need to replicate the C tree-construction functions in some way. */
+#ifdef OBJCPLUS
+#define OBJCP_REMAP_FUNCTIONS
+#include "objcp-decl.h"
+#endif /* OBJCPLUS */
+
+#include "toplev.h"
+#include "ggc.h"
+#include "tree-iterator.h"
+
+#include "objc-runtime-hooks.h"
+#include "objc-runtime-shared-support.h"
+
+/* GNU runtime private definitions. */
+#define DEF_CONSTANT_STRING_CLASS_NAME "NXConstantString"
+
+#define TAG_GETCLASS "objc_get_class"
+#define TAG_GETMETACLASS "objc_get_meta_class"
+
+#define TAG_MSGSEND "objc_msg_lookup"
+#define TAG_MSGSENDSUPER "objc_msg_lookup_super"
+
+/* GNU-specific tags. */
+
+#define TAG_EXECCLASS "__objc_exec_class"
+#define TAG_GNUINIT "__objc_gnu_init"
+
+/* The version identifies which language generation and runtime
+ the module (file) was compiled for, and is recorded in the
+ module descriptor. */
+#define OBJC_VERSION 8
+
+#define PROTOCOL_VERSION 2
+
+/* This macro provides a method of removing ambiguity between runtimes
+ when LTO is in use on targets supporting multiple runtimes.
+
+ For example, at present, any target that includes an implementation of
+ the NeXT runtime needs to place Objective-C meta-data into specific
+ named sections. This should _not_ be done for the GNU runtime, and the
+ folowing macro is used to attach Objective-C private attributes that may
+ be used to identify the runtime for which the meta-data are intended. */
+
+#define OBJCMETA(DECL,VERS,KIND) \
+ if (VERS) \
+ DECL_ATTRIBUTES (DECL) = build_tree_list ((VERS), (KIND));
+
+#ifndef TARGET_64BIT
+#define TARGET_64BIT 0
+#endif
+
+static void gnu_runtime_01_initialize (void);
+
+static void build_selector_template (void);
+
+static tree gnu_runtime_abi_01_super_superclassfield_id (void);
+
+static tree gnu_runtime_abi_01_class_decl (tree);
+static tree gnu_runtime_abi_01_metaclass_decl (tree);
+static tree gnu_runtime_abi_01_category_decl (tree);
+static tree gnu_runtime_abi_01_protocol_decl (tree);
+static tree gnu_runtime_abi_01_string_decl (tree, const char *, string_section);
+
+static tree gnu_runtime_abi_01_get_class_reference (tree);
+static tree gnu_runtime_abi_01_build_typed_selector_reference (location_t, tree,
+ tree);
+static tree gnu_runtime_abi_01_get_protocol_reference (location_t, tree);
+static tree gnu_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
+static tree gnu_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
+static tree gnu_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
+
+static tree gnu_runtime_abi_01_receiver_is_class_object (tree);
+static tree gnu_runtime_abi_01_get_arg_type_list_base (tree, int, int);
+static tree gnu_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
+ tree, tree, tree, int);
+
+static bool gnu_runtime_abi_01_setup_const_string_class_decl (void);
+static tree gnu_runtime_abi_01_build_const_string_constructor (location_t, tree,int);
+
+static void objc_generate_v1_gnu_metadata (void);
+
+static tree objc_eh_runtime_type (tree type);
+static tree objc_eh_personality (void);
+static tree objc_build_exc_ptr (struct objc_try_context **);
+static tree build_throw_stmt (location_t, tree, bool);
+static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
+static void finish_catch (struct objc_try_context **, tree);
+static tree finish_try_stmt (struct objc_try_context **);
+
+bool
+objc_gnu_runtime_abi_01_init (objc_runtime_hooks *rthooks)
+{
+ /* GNU runtime does not need the compiler to change code in order to do GC. */
+ if (flag_objc_gc)
+ {
+ warning_at (0, 0, "%<-fobjc-gc%> is ignored for %<-fgnu-runtime%>");
+ flag_objc_gc = 0;
+ }
+
+ /* Although I guess we could, we don't currently support SJLJ exceptions for the
+ GNU runtime. */
+ if (flag_objc_sjlj_exceptions)
+ {
+ inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for %<-fgnu-runtime%>");
+ flag_objc_sjlj_exceptions = 0;
+ }
+
+ rthooks->initialize = gnu_runtime_01_initialize;
+ rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
+ rthooks->tag_getclass = TAG_GETCLASS;
+ rthooks->super_superclassfield_ident = gnu_runtime_abi_01_super_superclassfield_id;
+
+ rthooks->class_decl = gnu_runtime_abi_01_class_decl;
+ rthooks->metaclass_decl = gnu_runtime_abi_01_metaclass_decl;
+ rthooks->category_decl = gnu_runtime_abi_01_category_decl;
+ rthooks->protocol_decl = gnu_runtime_abi_01_protocol_decl;
+ rthooks->string_decl = gnu_runtime_abi_01_string_decl;
+
+ rthooks->get_class_reference = gnu_runtime_abi_01_get_class_reference;
+ rthooks->build_selector_reference = gnu_runtime_abi_01_build_typed_selector_reference;
+ rthooks->get_protocol_reference = gnu_runtime_abi_01_get_protocol_reference;
+ rthooks->build_ivar_reference = gnu_runtime_abi_01_build_ivar_ref;
+ rthooks->get_class_super_ref = gnu_runtime_abi_01_get_class_super_ref;
+ rthooks->get_category_super_ref = gnu_runtime_abi_01_get_category_super_ref;
+
+ rthooks->receiver_is_class_object = gnu_runtime_abi_01_receiver_is_class_object;
+ rthooks->get_arg_type_list_base = gnu_runtime_abi_01_get_arg_type_list_base;
+ rthooks->build_objc_method_call = gnu_runtime_abi_01_build_objc_method_call;
+
+ rthooks->setup_const_string_class_decl =
+ gnu_runtime_abi_01_setup_const_string_class_decl;
+ rthooks->build_const_string_constructor =
+ gnu_runtime_abi_01_build_const_string_constructor;
+
+ rthooks->build_throw_stmt = build_throw_stmt;
+ rthooks->build_exc_ptr = objc_build_exc_ptr;
+ rthooks->begin_catch = begin_catch;
+ rthooks->finish_catch = finish_catch;
+ rthooks->finish_try_stmt = finish_try_stmt;
+
+ rthooks->generate_metadata = objc_generate_v1_gnu_metadata;
+ return true;
+}
+
+static void build_selector_table_decl (void);
+static void build_class_template (void);
+static void build_category_template (void);
+static void build_protocol_template (void);
+
+static GTY(()) tree objc_meta;
+static GTY(()) tree meta_base;
+
+static void gnu_runtime_01_initialize (void)
+{
+ tree type, ftype, IMP_type;
+
+ /* We do not need to mark GNU ObjC metadata for different sections,
+ however, we do need to make sure that it is not mistaken for NeXT
+ metadata. */
+ objc_meta = get_identifier ("OBJC1METG");
+ meta_base = get_identifier ("NONE");
+
+ /* Declare type of selector-objects that represent an operation name. */
+ /* `const struct objc_selector *' */
+ type = xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR));
+ type = build_qualified_type (type, TYPE_QUAL_CONST);
+ objc_selector_type = build_pointer_type (type);
+
+ /* typedef id (*IMP)(id, SEL, ...); */
+ ftype = build_varargs_function_type_list (objc_object_type,
+ objc_object_type,
+ objc_selector_type,
+ NULL_TREE);
+
+ IMP_type = build_pointer_type (ftype);
+
+ build_class_template ();
+ build_super_template ();
+ build_protocol_template ();
+ build_category_template ();
+
+ /* GNU runtime messenger entry points. */
+ /* TREE_NOTHROW is cleared for the message-sending functions,
+ because the function that gets called can throw in Obj-C++, or
+ could itself call something that can throw even in Obj-C. */
+
+ /* IMP objc_msg_lookup (id, SEL); */
+ type = build_function_type_list (IMP_type,
+ objc_object_type,
+ objc_selector_type,
+ NULL_TREE);
+
+ umsg_decl = add_builtin_function (TAG_MSGSEND,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (umsg_decl) = 0;
+
+ /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
+ type = build_function_type_list (IMP_type,
+ objc_super_type,
+ objc_selector_type,
+ NULL_TREE);
+
+ umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (umsg_super_decl) = 0;
+
+ /* The following GNU runtime entry point is called to initialize
+ each module:
+
+ __objc_exec_class (void *); */
+ type = build_function_type_list (void_type_node,
+ ptr_type_node,
+ NULL_TREE);
+
+ execclass_decl = add_builtin_function (TAG_EXECCLASS,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ type = build_function_type_list (objc_object_type,
+ const_string_type_node,
+ NULL_TREE);
+
+ /* id objc_getClass (const char *); */
+ objc_get_class_decl
+ = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ /* id objc_getMetaClass (const char *); */
+ objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS, type,
+ 0, NOT_BUILT_IN, NULL,
+ NULL_TREE);
+
+ /* static SEL _OBJC_SELECTOR_TABLE[]; */
+ build_selector_table_decl ();
+
+ /* Stuff for properties.
+ The codegen relies on this being NULL for GNU. */
+ objc_copyStruct_decl = NULL_TREE;
+
+ /* This is the type of all of the following functions
+ bjc_getPropertyStruct() and objc_setPropertyStruct(). */
+ type = build_function_type_list (void_type_node,
+ ptr_type_node,
+ const_ptr_type_node,
+ ptrdiff_type_node,
+ boolean_type_node,
+ boolean_type_node,
+ NULL_TREE);
+
+ /* Declare the following function:
+ void
+ objc_getPropertyStruct (void *destination, const void *source,
+ ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
+ objc_getPropertyStruct_decl = add_builtin_function ("objc_getPropertyStruct",
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (objc_getPropertyStruct_decl) = 0;
+ /* Declare the following function:
+ void
+ objc_setPropertyStruct (void *destination, const void *source,
+ ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
+ objc_setPropertyStruct_decl = add_builtin_function ("objc_setPropertyStruct",
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (objc_setPropertyStruct_decl) = 0;
+
+ using_eh_for_cleanups ();
+ lang_hooks.eh_runtime_type = objc_eh_runtime_type;
+ lang_hooks.eh_personality = objc_eh_personality;
+}
+
+/* --- templates --- */
+/* struct _objc_selector {
+ SEL sel_id;
+ char *sel_type;
+ }; */
+
+static void
+build_selector_template (void)
+{
+ tree decls, *chain = NULL;
+
+ objc_selector_template = objc_start_struct (get_identifier (UTAG_SELECTOR));
+
+ /* SEL sel_id; */
+ decls = add_field_decl (objc_selector_type, "sel_id", &chain);
+
+ /* char *sel_type; */
+ add_field_decl (string_type_node, "sel_type", &chain);
+
+ objc_finish_struct (objc_selector_template, decls);
+}
+
+/* struct _objc_class {
+ struct _objc_class *isa;
+ struct _objc_class *super_class;
+ char *name;
+ long version;
+ long info;
+ long instance_size;
+ struct _objc_ivar_list *ivars;
+ struct _objc_method_list *methods;
+ struct sarray *dtable;
+ struct _objc_class *subclass_list;
+ struct _objc_class *sibling_class;
+ struct _objc_protocol_list *protocols;
+ void *gc_object_type;
+ }; */
+
+static void
+build_class_template (void)
+{
+ tree ptype, decls, *chain = NULL;
+
+ objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
+
+ /* struct _objc_class *isa; */
+ decls = add_field_decl (build_pointer_type (objc_class_template),
+ "isa", &chain);
+
+ /* struct _objc_class *super_class; */
+ add_field_decl (build_pointer_type (objc_class_template),
+ "super_class", &chain);
+
+ /* char *name; */
+ add_field_decl (string_type_node, "name", &chain);
+
+ /* long version; */
+ add_field_decl (long_integer_type_node, "version", &chain);
+
+ /* long info; */
+ add_field_decl (long_integer_type_node, "info", &chain);
+
+ /* long instance_size; */
+ add_field_decl (long_integer_type_node, "instance_size", &chain);
+
+ /* struct _objc_ivar_list *ivars; */
+ add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
+
+ /* struct _objc_method_list *methods; */
+ add_field_decl (objc_method_list_ptr, "methods", &chain);
+
+ /* struct sarray *dtable; */
+ ptype = build_pointer_type(xref_tag (RECORD_TYPE,
+ get_identifier ("sarray")));
+ add_field_decl (ptype, "dtable", &chain);
+
+ /* struct objc_class *subclass_list; */
+ ptype = build_pointer_type (objc_class_template);
+ add_field_decl (ptype, "subclass_list", &chain);
+
+ /* struct objc_class *sibling_class; */
+ ptype = build_pointer_type (objc_class_template);
+ add_field_decl (ptype, "sibling_class", &chain);
+
+ /* struct _objc_protocol **protocol_list; */
+ ptype = build_pointer_type (build_pointer_type
+ (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_PROTOCOL))));
+ add_field_decl (ptype, "protocol_list", &chain);
+
+ /* void *gc_object_type; */
+ add_field_decl (build_pointer_type (void_type_node),
+ "gc_object_type", &chain);
+
+ objc_finish_struct (objc_class_template, decls);
+}
+
+/* struct _objc_category {
+ char *category_name;
+ char *class_name;
+ struct _objc_method_list *instance_methods;
+ struct _objc_method_list *class_methods;
+ struct _objc_protocol_list *protocols;
+ }; */
+
+static void
+build_category_template (void)
+{
+ tree ptype, decls, *chain = NULL;
+
+ objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
+
+ /* char *category_name; */
+ decls = add_field_decl (string_type_node, "category_name", &chain);
+
+ /* char *class_name; */
+ add_field_decl (string_type_node, "class_name", &chain);
+
+ /* struct _objc_method_list *instance_methods; */
+ add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
+
+ /* struct _objc_method_list *class_methods; */
+ add_field_decl (objc_method_list_ptr, "class_methods", &chain);
+
+ /* struct _objc_protocol **protocol_list; */
+ ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
+ add_field_decl (ptype, "protocol_list", &chain);
+
+ objc_finish_struct (objc_category_template, decls);
+}
+
+/* struct _objc_protocol {
+ struct _objc_class *isa;
+ char *protocol_name;
+ struct _objc_protocol **protocol_list;
+ struct _objc__method_prototype_list *instance_methods;
+ struct _objc__method_prototype_list *class_methods;
+ }; */
+
+static void
+build_protocol_template (void)
+{
+ tree ptype, decls, *chain = NULL;
+
+ objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
+
+ /* struct _objc_class *isa; */
+ ptype = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_CLASS)));
+ decls = add_field_decl (ptype, "isa", &chain);
+
+ /* char *protocol_name; */
+ add_field_decl (string_type_node, "protocol_name", &chain);
+
+ /* struct _objc_protocol **protocol_list; */
+ ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
+ add_field_decl (ptype, "protocol_list", &chain);
+
+ /* struct _objc__method_prototype_list *instance_methods; */
+ add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
+
+ /* struct _objc__method_prototype_list *class_methods; */
+ add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
+
+ objc_finish_struct (objc_protocol_template, decls);
+}
+
+/* --- names, decls + identifers --- */
+
+static void
+build_selector_table_decl (void)
+{
+ tree temp;
+
+ build_selector_template ();
+ temp = build_array_type (objc_selector_template, NULL_TREE);
+
+ UOBJC_SELECTOR_TABLE_decl = start_var_decl (temp, "_OBJC_SELECTOR_TABLE");
+ OBJCMETA (UOBJC_SELECTOR_TABLE_decl, objc_meta, meta_base);
+}
+
+
+static tree
+gnu_runtime_abi_01_super_superclassfield_id (void)
+{
+ if (!super_superclassfield_id)
+ super_superclassfield_id = get_identifier ("super_class");
+ return super_superclassfield_id;
+}
+
+
+static tree
+gnu_runtime_abi_01_class_decl (tree klass)
+{
+ tree decl;
+ char buf[BUFSIZE];
+ snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass)));
+ decl = start_var_decl (objc_class_template, buf);
+ OBJCMETA (decl, objc_meta, meta_base);
+ return decl;
+}
+
+static tree
+gnu_runtime_abi_01_metaclass_decl (tree klass)
+{
+ tree decl;
+ char buf[BUFSIZE];
+ snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass)));
+ decl = start_var_decl (objc_class_template, buf);
+ OBJCMETA (decl, objc_meta, meta_base);
+ return decl;
+}
+
+static tree
+gnu_runtime_abi_01_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)));
+ decl = start_var_decl (objc_category_template, buf);
+ OBJCMETA (decl, objc_meta, meta_base);
+ return decl;
+}
+
+static tree
+gnu_runtime_abi_01_protocol_decl (tree p)
+{
+ tree decl;
+ char buf[BUFSIZE];
+
+ /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
+ snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+ decl = start_var_decl (objc_protocol_template, buf);
+ OBJCMETA (decl, objc_meta, meta_base);
+ return decl;
+}
+
+static tree
+gnu_runtime_abi_01_string_decl (tree type, const char *name,
+ string_section where ATTRIBUTE_UNUSED)
+{
+ tree decl = start_var_decl (type, name);
+ OBJCMETA (decl, objc_meta, meta_base);
+ return decl;
+}
+
+/* --- entry --- */
+
+static tree
+gnu_runtime_abi_01_get_class_reference (tree ident)
+{
+ tree params;
+
+ add_class_reference (ident);
+
+ params = build_tree_list (NULL_TREE, my_build_string_pointer
+ (IDENTIFIER_LENGTH (ident) + 1,
+ IDENTIFIER_POINTER (ident)));
+
+/* assemble_external (objc_get_class_decl);*/
+ return build_function_call (input_location, objc_get_class_decl, params);
+}
+
+/* Used by get_arg_type_list.
+ Return the types for receiver & _cmd at the start of a method argument list.
+ context is either METHOD_DEF or METHOD_REF, saying whether we are trying
+ to define a method or call one. superflag says this is for a send to super.
+ meth may be NULL, in the case that there is no prototype. */
+
+static tree
+gnu_runtime_abi_01_get_arg_type_list_base (tree meth, int context,
+ int superflag ATTRIBUTE_UNUSED)
+{
+ tree arglist;
+
+ /* Receiver type. */
+ if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
+ arglist = build_tree_list (NULL_TREE, objc_instance_type);
+ else
+ arglist = build_tree_list (NULL_TREE, objc_object_type);
+
+ /* Selector type - will eventually change to `int'. */
+ chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
+ return arglist;
+}
+
+/* Unused for GNU runtime. */
+static tree
+gnu_runtime_abi_01_receiver_is_class_object (tree a ATTRIBUTE_UNUSED)
+{
+ return NULL_TREE;
+}
+
+/* sel_ref_chain is a list whose "value" fields will be instances of
+ identifier_node that represent the selector. LOC is the location of
+ the @selector. */
+
+static tree
+gnu_runtime_abi_01_build_typed_selector_reference (location_t loc, tree ident,
+ tree prototype)
+{
+ tree *chain = &sel_ref_chain;
+ tree expr;
+ int index = 0;
+
+ while (*chain)
+ {
+ /* When we do a lookup for @selector () we have no idea of the
+ prototype - so match the first we find. */
+ if (TREE_VALUE (*chain) == ident
+ && (!prototype || TREE_PURPOSE (*chain) == prototype))
+ goto return_at_index;
+
+ index++;
+ chain = &TREE_CHAIN (*chain);
+ }
+
+ *chain = tree_cons (prototype, ident, NULL_TREE);
+
+ /* TODO: Use a vec and keep this in it to (a) avoid re-creating and
+ (b) provide better diagnostics for the first time an undefined
+ selector is used. */
+ return_at_index:
+ expr = build_unary_op (loc, ADDR_EXPR,
+ build_array_ref (loc, UOBJC_SELECTOR_TABLE_decl,
+ build_int_cst (NULL_TREE, index)),
+ 1);
+ return convert (objc_selector_type, expr);
+}
+
+/* Build a tree expression to send OBJECT the operation SELECTOR,
+ looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
+ assuming the method has prototype METHOD_PROTOTYPE.
+ (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
+ LOC is the location of the expression to build.
+ Use METHOD_PARAMS as list of args to pass to the method.
+ If SUPER_FLAG is nonzero, we look up the superclass's method. */
+
+static tree
+build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
+ tree lookup_object, tree selector,
+ tree method_params)
+{
+ tree sender = (super_flag ? umsg_super_decl
+ : (flag_objc_direct_dispatch ? umsg_fast_decl
+ : umsg_decl));
+ tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
+ VEC(tree, gc) *parms;
+ VEC(tree, gc) *tv;
+ 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 method_param_types =
+ get_arg_type_list (method_prototype, METHOD_REF, super_flag);
+ tree ftype = build_function_type (ret_type, method_param_types);
+ tree sender_cast;
+ tree method, t;
+
+ 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. */
+ parms = VEC_alloc (tree, gc, nparm + 2);
+ tv = VEC_alloc (tree, gc, 2);
+
+ /* First, call the lookup function to get a pointer to the method,
+ then cast the pointer, then call it with the method arguments. */
+ VEC_quick_push (tree, tv, lookup_object);
+ VEC_quick_push (tree, tv, selector);
+ method = build_function_call_vec (loc, sender, tv, NULL);
+ VEC_free (tree, gc, tv);
+
+ /* Pass the appropriate object to the method. */
+ VEC_quick_push (tree, parms, (super_flag ? self_decl : lookup_object));
+
+ /* Pass the selector to the method. */
+ VEC_quick_push (tree, parms, selector);
+ /* Now append the remainder of the parms. */
+ if (nparm)
+ for (; method_params; method_params = TREE_CHAIN (method_params))
+ VEC_quick_push (tree, parms, 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);
+ t = build_function_call_vec (loc, t, parms, NULL);
+ VEC_free (tree, gc, parms);
+ return t;
+}
+
+static tree
+gnu_runtime_abi_01_build_objc_method_call (location_t loc,
+ tree method_prototype,
+ tree receiver,
+ tree rtype ATTRIBUTE_UNUSED,
+ tree sel_name,
+ tree method_params,
+ int super ATTRIBUTE_UNUSED)
+{
+ tree selector =
+ gnu_runtime_abi_01_build_typed_selector_reference (loc,
+ sel_name,
+ method_prototype);
+
+ return build_objc_method_call (loc, super, method_prototype, receiver,
+ selector, method_params);
+}
+
+static tree
+gnu_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
+{
+ tree expr, protocol_struct_type, *chain;
+ if (!PROTOCOL_FORWARD_DECL (p))
+ PROTOCOL_FORWARD_DECL (p) = gnu_runtime_abi_01_protocol_decl (p);
+
+ expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
+
+ /* ??? Ideally we'd build the reference with objc_protocol_type directly,
+ if we have it, rather than converting it here. */
+ expr = convert (objc_protocol_type, expr);
+
+ /* The @protocol() expression is being compiled into a pointer to a
+ statically allocated instance of the Protocol class. To become
+ usable at runtime, the 'isa' pointer of the instance need to be
+ fixed up at runtime by the runtime library, to point to the
+ actual 'Protocol' class. */
+
+ /* For the GNU runtime, put the static Protocol instance in the list
+ of statically allocated instances, so that we make sure that its
+ 'isa' pointer is fixed up at runtime by the GNU runtime library
+ to point to the Protocol class (at runtime, when loading the
+ module, the GNU runtime library loops on the statically allocated
+ instances (as found in the defs field in objc_symtab) and fixups
+ all the 'isa' pointers of those objects). */
+
+ /* This type is a struct containing the fields of a Protocol
+ object. (Cfr. objc_protocol_type instead is the type of a pointer
+ to such a struct). */
+ protocol_struct_type = xref_tag (RECORD_TYPE,
+ get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
+
+ /* Look for the list of Protocol statically allocated instances
+ to fixup at runtime. Create a new list to hold Protocol
+ statically allocated instances, if the list is not found. At
+ present there is only another list, holding NSConstantString
+ static instances to be fixed up at runtime. */
+
+ for (chain = &objc_static_instances;
+ *chain && TREE_VALUE (*chain) != protocol_struct_type;
+ chain = &TREE_CHAIN (*chain));
+
+ if (!*chain)
+ {
+ *chain = tree_cons (NULL_TREE, protocol_struct_type, NULL_TREE);
+ add_objc_string (OBJC_TYPE_NAME (protocol_struct_type),
+ class_names);
+ }
+
+ /* Add this statically allocated instance to the Protocol list. */
+ TREE_PURPOSE (*chain) = tree_cons (NULL_TREE,
+ PROTOCOL_FORWARD_DECL (p),
+ TREE_PURPOSE (*chain));
+ return expr;
+}
+
+/* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */
+
+static tree
+gnu_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
+ tree base, tree id)
+{
+ return objc_build_component_ref (base, id);
+}
+
+/* We build super class references as we need them (but keep them once
+ built for the sake of efficiency). */
+
+static tree
+gnu_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
+ struct imp_entry *imp, bool inst_meth)
+{
+ if (inst_meth)
+ {
+ if (!ucls_super_ref)
+ ucls_super_ref =
+ objc_build_component_ref (imp->class_decl,
+ get_identifier ("super_class"));
+ return ucls_super_ref;
+ }
+ else
+ {
+ if (!uucls_super_ref)
+ uucls_super_ref =
+ objc_build_component_ref (imp->meta_decl,
+ get_identifier ("super_class"));
+ return uucls_super_ref;
+ }
+}
+
+static tree
+gnu_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
+ struct imp_entry *imp, bool inst_meth)
+{
+ tree super_name = CLASS_SUPER_NAME (imp->imp_template);
+ tree super_class;
+
+ add_class_reference (super_name);
+ super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
+/* assemble_external (super_class);*/
+ super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
+ IDENTIFIER_POINTER (super_name));
+ /* super_class = get_{meta_}class("CLASS_SUPER_NAME"); */
+ return build_function_call (input_location,
+ super_class,
+ build_tree_list (NULL_TREE, super_name));
+}
+
+static bool
+gnu_runtime_abi_01_setup_const_string_class_decl (void)
+{
+ /* Do nothing, and create no error. */
+ return true;
+}
+
+/* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */
+
+static GTY(()) int num_static_inst;
+
+static tree
+objc_add_static_instance (tree constructor, tree class_decl)
+{
+ tree *chain, decl;
+ char buf[BUFSIZE];
+
+ /* 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 = tree_cons (NULL_TREE, class_decl, NULL_TREE);
+ add_objc_string (OBJC_TYPE_NAME (class_decl), class_names);
+ }
+
+ snprintf (buf, BUFSIZE, "_OBJC_INSTANCE_%d", num_static_inst++);
+ decl = build_decl (input_location,
+ VAR_DECL, get_identifier (buf), class_decl);
+ TREE_STATIC (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ TREE_USED (decl) = 1;
+ DECL_INITIAL (decl) = constructor;
+ DECL_CONTEXT (decl) = NULL;
+ OBJCMETA (decl, objc_meta, meta_base);
+
+ /* We may be writing something else just now.
+ Postpone till end of input. */
+ DECL_DEFER_OUTPUT (decl) = 1;
+ pushdecl_top_level (decl);
+ rest_of_decl_compilation (decl, 1, 0);
+
+ /* Add the DECL to the head of this CLASS' list. */
+ TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain));
+
+ return decl;
+}
+
+static tree
+gnu_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
+ int length)
+{
+ tree constructor, fields;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* GNU: (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length }) */
+ fields = TYPE_FIELDS (internal_const_str_type);
+ CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, 0));
+
+ fields = DECL_CHAIN (fields);
+ CONSTRUCTOR_APPEND_ELT (v, fields, build_unary_op (loc,
+ ADDR_EXPR, string, 1));
+
+ fields = DECL_CHAIN (fields);
+ CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
+ constructor = objc_build_constructor (internal_const_str_type, v);
+
+ constructor = objc_add_static_instance (constructor, constant_string_type);
+ return constructor;
+}
+
+/* --- metadata - module initializer --- */
+
+/* The GNU runtime requires us to provide a static initializer function
+ for each module:
+
+ static void __objc_gnu_init (void) {
+ __objc_exec_class (&L_OBJC_MODULES);
+ } */
+
+
+static void
+build_module_initializer_routine (void)
+{
+ tree body;
+
+#ifdef OBJCPLUS
+ push_lang_context (lang_name_c); /* extern "C" */
+#endif
+
+ objc_push_parm (build_decl (input_location,
+ PARM_DECL, NULL_TREE, void_type_node));
+#ifdef OBJCPLUS
+ objc_start_function (get_identifier (TAG_GNUINIT),
+ build_function_type_list (void_type_node, NULL_TREE),
+ NULL_TREE, NULL_TREE);
+#else
+ objc_start_function (get_identifier (TAG_GNUINIT),
+ build_function_type_list (void_type_node, NULL_TREE),
+ NULL_TREE, objc_get_parm_info (0));
+#endif
+ body = c_begin_compound_stmt (true);
+ add_stmt (build_function_call
+ (input_location,
+ execclass_decl,
+ build_tree_list
+ (NULL_TREE,
+ build_unary_op (input_location, ADDR_EXPR,
+ UOBJC_MODULES_decl, 0))));
+ add_stmt (c_end_compound_stmt (input_location, body, true));
+
+ TREE_PUBLIC (current_function_decl) = 0;
+
+#ifndef OBJCPLUS
+ /* For Objective-C++, we will need to call __objc_gnu_init
+ from objc_generate_static_init_call() below. */
+ DECL_STATIC_CONSTRUCTOR (current_function_decl) = 1;
+#endif
+
+ GNU_INIT_decl = current_function_decl;
+ finish_function ();
+
+#ifdef OBJCPLUS
+ pop_lang_context ();
+#endif
+}
+
+#ifdef OBJCPLUS
+/* Return 1 if the __objc_gnu_init function has been synthesized and needs
+ to be called by the module initializer routine. */
+
+int
+objc_static_init_needed_p (void)
+{
+ return (GNU_INIT_decl != NULL_TREE);
+}
+
+/* Generate a call to the __objc_gnu_init initializer function. */
+
+tree
+objc_generate_static_init_call (tree ctors ATTRIBUTE_UNUSED)
+{
+ add_stmt (build_stmt (input_location, EXPR_STMT,
+ build_function_call (input_location,
+ GNU_INIT_decl, NULL_TREE)));
+
+ return ctors;
+}
+#endif /* OBJCPLUS */
+
+/* --- Output GNU Meta-data --- */
+
+static void
+generate_classref_translation_entry (tree chain)
+{
+ tree expr, decl, type;
+
+ decl = TREE_PURPOSE (chain);
+ type = TREE_TYPE (decl);
+
+ expr = add_objc_string (TREE_VALUE (chain), class_names);
+ expr = convert (type, expr); /* cast! */
+
+ /* This is a class reference. It is re-written by the runtime,
+ but will be optimized away unless we force it. */
+ DECL_PRESERVE_P (decl) = 1;
+ OBJCMETA (decl, objc_meta, meta_base);
+ finish_var_decl (decl, expr);
+ return;
+}
+
+
+static void
+handle_impent (struct imp_entry *impent)
+{
+ char *string;
+
+/* objc_implementation_context = impent->imp_context;
+ implementation_template = impent->imp_template;*/
+
+ switch (TREE_CODE (impent->imp_context))
+ {
+ case CLASS_IMPLEMENTATION_TYPE:
+ {
+ const char *const class_name =
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
+
+ string = (char *) alloca (strlen (class_name) + 30);
+
+ sprintf (string, "__objc_class_name_%s", class_name);
+ break;
+ }
+ case CATEGORY_IMPLEMENTATION_TYPE:
+ {
+ const char *const class_name =
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context));
+ const char *const class_super_name =
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context));
+
+ string = (char *) alloca (strlen (class_name)
+ + strlen (class_super_name) + 30);
+
+ /* Do the same for categories. Even though no references to
+ these symbols are generated automatically by the compiler,
+ it gives you a handle to pull them into an archive by
+ hand. */
+ sprintf (string, "*__objc_category_name_%s_%s", class_name, class_super_name);
+ break;
+ }
+ default:
+ return;
+ }
+
+ {
+ tree decl, init;
+
+ init = integer_zero_node;
+ decl = build_decl (input_location,
+ VAR_DECL, get_identifier (string), TREE_TYPE (init));
+ TREE_PUBLIC (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ TREE_USED (decl) = 1;
+ TREE_CONSTANT (decl) = 1;
+ DECL_CONTEXT (decl) = NULL_TREE;
+ DECL_ARTIFICIAL (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ DECL_INITIAL (decl) = error_mark_node; /* A real initializer is coming... */
+ /* We must force the reference. */
+ DECL_PRESERVE_P (decl) = 1;
+
+ finish_var_decl(decl, init) ;
+ }
+}
+
+tree
+build_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
+ tree inst_methods, tree class_methods)
+{
+ tree expr, ttyp;
+ location_t loc;
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ /* TODO: pass the loc in or find it from args. */
+ loc = input_location;
+ ttyp = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_CLASS)));
+ /* Filling the "isa" in with a version allows the runtime system to
+ detect this ... */
+ expr = build_int_cst (ttyp, PROTOCOL_VERSION);
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
+
+ ttyp = objc_method_proto_list_ptr;
+ if (inst_methods)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ if (class_methods)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ return objc_build_constructor (type, inits);
+}
+
+static tree
+generate_protocol_list (tree i_or_p, tree klass_ctxt)
+{
+ tree array_type, ptype, refs_decl, lproto, e, plist;
+ VEC(constructor_elt,gc) *v = NULL;
+ char buf[BUFSIZE];
+ int size = 0;
+
+ switch (TREE_CODE (i_or_p))
+ {
+ case CLASS_INTERFACE_TYPE:
+ case CATEGORY_INTERFACE_TYPE:
+ plist = CLASS_PROTOCOL_LIST (i_or_p);
+ break;
+ case PROTOCOL_INTERFACE_TYPE:
+ plist = PROTOCOL_LIST (i_or_p);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Compute size. */
+ for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
+ if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
+ && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
+ size++;
+
+ /* Build initializer. */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
+ e = build_int_cst (build_pointer_type (objc_protocol_template), size);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
+
+ for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
+ {
+ tree pval = TREE_VALUE (lproto);
+
+ if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
+ && PROTOCOL_FORWARD_DECL (pval))
+ {
+ tree fwref = PROTOCOL_FORWARD_DECL (pval);
+ location_t loc = DECL_SOURCE_LOCATION (fwref) ;
+ e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
+ }
+ }
+
+ /* static struct objc_protocol *refs[n]; */
+
+ switch (TREE_CODE (i_or_p))
+ {
+ case PROTOCOL_INTERFACE_TYPE:
+ snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
+ break;
+ case CLASS_INTERFACE_TYPE:
+ snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
+ break;
+ case CATEGORY_INTERFACE_TYPE:
+ snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ ptype = build_pointer_type (objc_protocol_template);
+ array_type = build_sized_array_type (ptype, size + 3);
+ refs_decl = start_var_decl (array_type, buf);
+ OBJCMETA (refs_decl, objc_meta, meta_base);
+ finish_var_decl (refs_decl,
+ objc_build_constructor (TREE_TYPE (refs_decl), v));
+
+ return refs_decl;
+}
+
+static tree
+generate_v1_meth_descriptor_table (tree chain, tree protocol, const char *prefix)
+{
+ tree method_list_template, initlist, decl;
+ int size;
+ VEC(constructor_elt,gc) *v = NULL;
+ char buf[BUFSIZE];
+
+ if (!chain || !prefix)
+ return NULL_TREE;
+
+ if (!objc_method_prototype_template)
+ objc_method_prototype_template = build_method_prototype_template ();
+
+ size = list_length (chain);
+ method_list_template =
+ build_method_prototype_list_template (objc_method_prototype_template,
+ size);
+ snprintf (buf, BUFSIZE, "%s_%s", prefix,
+ IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
+
+ decl = start_var_decl (method_list_template, buf);
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
+ initlist =
+ build_descriptor_table_initializer (objc_method_prototype_template,
+ chain);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
+ OBJCMETA (decl, objc_meta, meta_base);
+ finish_var_decl (decl, objc_build_constructor (method_list_template, v));
+ return decl;
+}
+
+/* For each protocol which was referenced either from a @protocol()
+ expression, or because a class/category implements it (then a
+ pointer to the protocol is stored in the struct describing the
+ class/category), we create a statically allocated instance of the
+ Protocol class. The code is written in such a way as to generate
+ as few Protocol objects as possible; we generate a unique Protocol
+ instance for each protocol, and we don't generate a Protocol
+ instance if the protocol is never referenced (either from a
+ @protocol() or from a class/category implementation). These
+ statically allocated objects can be referred to via the static
+ (that is, private to this module) symbols _OBJC_PROTOCOL_n.
+
+ The statically allocated Protocol objects that we generate here
+ need to be fixed up at runtime in order to be used: the 'isa'
+ pointer of the objects need to be set up to point to the 'Protocol'
+ class, as known at runtime.
+
+ The GNU runtime fixes up all protocols before user code from the module
+ is executed; it requires pointers to those symbols
+ to be put in the objc_symtab (which is then passed as argument to
+ the function __objc_exec_class() which the compiler sets up to be
+ executed automatically when the module is loaded); setup of those
+ Protocol objects happen in two ways in the GNU runtime: all
+ Protocol objects referred to by a class or category implementation
+ are fixed up when the class/category is loaded; all Protocol
+ objects referred to by a @protocol() expression are added by the
+ compiler to the list of statically allocated instances to fixup
+ (the same list holding the statically allocated constant string
+ objects). Because, as explained above, the compiler generates as
+ few Protocol objects as possible, some Protocol object might end up
+ being referenced multiple times when compiled with the GNU runtime,
+ and end up being fixed up multiple times at runtime initialization.
+ But that doesn't hurt, it's just a little inefficient. */
+
+static void
+generate_protocols (void)
+{
+ tree p, encoding;
+ tree decl;
+ tree initlist, protocol_name_expr, refs_decl, refs_expr;
+
+ /* If a protocol was directly referenced, pull in indirect references. */
+ for (p = protocol_chain; p; p = TREE_CHAIN (p))
+ if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
+ generate_protocol_references (PROTOCOL_LIST (p));
+
+ for (p = protocol_chain; p; p = TREE_CHAIN (p))
+ {
+ tree nst_methods = PROTOCOL_NST_METHODS (p);
+ tree cls_methods = PROTOCOL_CLS_METHODS (p);
+
+ /* If protocol wasn't referenced, don't generate any code. */
+ decl = PROTOCOL_FORWARD_DECL (p);
+
+ if (!decl)
+ continue;
+
+ /* Make sure we link in the Protocol class. */
+ add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
+
+ while (nst_methods)
+ {
+ if (! METHOD_ENCODING (nst_methods))
+ {
+ encoding = encode_method_prototype (nst_methods);
+ METHOD_ENCODING (nst_methods) = encoding;
+ }
+ nst_methods = DECL_CHAIN (nst_methods);
+ }
+
+ UOBJC_INSTANCE_METHODS_decl =
+ generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
+ "_OBJC_PROTOCOL_INSTANCE_METHODS");
+
+ while (cls_methods)
+ {
+ if (! METHOD_ENCODING (cls_methods))
+ {
+ encoding = encode_method_prototype (cls_methods);
+ METHOD_ENCODING (cls_methods) = encoding;
+ }
+
+ cls_methods = DECL_CHAIN (cls_methods);
+ }
+
+ UOBJC_CLASS_METHODS_decl =
+ generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
+ "_OBJC_PROTOCOL_CLASS_METHODS");
+/* generate_method_descriptors (p);*/
+
+ if (PROTOCOL_LIST (p))
+ refs_decl = generate_protocol_list (p, NULL_TREE);
+ else
+ refs_decl = 0;
+
+ /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
+ protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
+
+ if (refs_decl)
+ refs_expr = convert (build_pointer_type (build_pointer_type
+ (objc_protocol_template)),
+ build_unary_op (input_location,
+ ADDR_EXPR, refs_decl, 0));
+ else
+ refs_expr = build_int_cst (NULL_TREE, 0);
+
+ /* UOBJC_INSTANCE_METHODS_decl/UOBJC_CLASS_METHODS_decl are set
+ by generate_method_descriptors, which is called above. */
+ initlist = build_protocol_initializer (TREE_TYPE (decl),
+ protocol_name_expr, refs_expr,
+ UOBJC_INSTANCE_METHODS_decl,
+ UOBJC_CLASS_METHODS_decl);
+ finish_var_decl (decl, initlist);
+ }
+}
+
+static tree
+generate_dispatch_table (tree chain, const char *name)
+{
+ tree decl, method_list_template, initlist;
+ VEC(constructor_elt,gc) *v = NULL;
+ int size = list_length (chain);
+
+ if (!objc_method_template)
+ objc_method_template = build_method_template ();
+
+ method_list_template = build_method_list_template (objc_method_template,
+ size);
+ initlist = build_dispatch_table_initializer (objc_method_template, chain);
+
+ decl = start_var_decl (method_list_template, name);
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (integer_type_node, size));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
+
+ OBJCMETA (decl, objc_meta, meta_base);
+ finish_var_decl (decl,
+ objc_build_constructor (TREE_TYPE (decl), v));
+
+ return decl;
+}
+
+/* Init a category. */
+static tree
+build_category_initializer (tree type, tree cat_name, tree class_name,
+ tree inst_methods, tree class_methods,
+ tree protocol_list)
+{
+ tree expr, ltyp;
+ location_t loc;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* TODO: pass the loc in or find it from args. */
+ /* TODO: pass the loc in or find it from args. */
+ loc = UNKNOWN_LOCATION;
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
+
+ ltyp = objc_method_list_ptr;
+ if (inst_methods)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ if (class_methods)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* protocol_list = */
+ ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
+ if (protocol_list)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ return objc_build_constructor (type, v);
+}
+
+/* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
+
+static void
+generate_category (struct imp_entry *impent)
+{
+ tree initlist, cat_name_expr, class_name_expr;
+ tree protocol_decl, category, cat_decl;
+ tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
+ tree cat = impent->imp_context;
+ char buf[BUFSIZE];
+
+ cat_decl = impent->class_decl;
+
+ add_class_reference (CLASS_NAME (cat));
+ cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
+
+ class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
+
+ category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
+
+ if (category && CLASS_PROTOCOL_LIST (category))
+ {
+ generate_protocol_references (CLASS_PROTOCOL_LIST (category));
+ protocol_decl = generate_protocol_list (category, cat);
+ }
+ else
+ protocol_decl = 0;
+
+ if (CLASS_NST_METHODS (cat))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (cat)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
+ inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf);
+ }
+
+ if (CLASS_CLS_METHODS (cat))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (cat)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
+ class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf);
+ }
+
+ initlist = build_category_initializer (TREE_TYPE (cat_decl),
+ cat_name_expr, class_name_expr,
+ inst_methods, class_methods,
+ protocol_decl);
+ /* Finish and initialize the forward decl. */
+ finish_var_decl (cat_decl, initlist);
+ impent->class_decl = cat_decl;
+}
+
+/* struct _objc_class {
+ struct objc_class *isa;
+ struct objc_class *super_class;
+ char *name;
+ long version;
+ long info;
+ long instance_size;
+ struct objc_ivar_list *ivars;
+ struct objc_method_list *methods;
+ if (flag_next_runtime)
+ struct objc_cache *cache;
+ else {
+ struct sarray *dtable;
+ struct objc_class *subclass_list;
+ struct objc_class *sibling_class;
+ }
+ struct objc_protocol_list *protocols;
+ if (flag_next_runtime)
+ void *sel_id;
+ void *gc_object_type;
+ }; */
+
+static tree
+build_shared_structure_initializer (tree type, tree isa, tree super,
+ tree name, tree size, int status,
+ tree dispatch_table, tree ivar_list,
+ tree protocol_list)
+{
+ tree expr, ltyp;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* isa = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
+
+ /* super_class = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
+
+ /* name = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
+
+ /* version = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (long_integer_type_node, 0));
+
+ /* info = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (long_integer_type_node, status));
+
+ /* instance_size = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ convert (long_integer_type_node, size));
+
+ /* objc_ivar_list = */
+ if (!ivar_list)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (objc_ivar_list_ptr, 0));
+ else
+ {
+ expr = convert (objc_ivar_list_ptr,
+ build_unary_op (input_location, ADDR_EXPR,
+ ivar_list, 0));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+
+ /* objc_method_list = */
+ if (!dispatch_table)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ convert (objc_method_list_ptr, null_pointer_node));
+ else
+ {
+ expr = convert (objc_method_list_ptr,
+ build_unary_op (input_location, ADDR_EXPR,
+ dispatch_table, 0));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+
+ 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));
+
+ /* 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));
+ }
+
+ /* protocol_list = */
+ ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
+ if (! protocol_list)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (ltyp, 0));
+ else
+ {
+ expr = convert (ltyp,
+ build_unary_op (input_location, ADDR_EXPR,
+ protocol_list, 0));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+
+ 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));
+
+ return objc_build_constructor (type, v);
+}
+
+
+static tree
+generate_ivars_list (tree chain, const char *name)
+{
+ tree initlist, ivar_list_template, decl;
+ int size;
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ if (!chain)
+ return NULL_TREE;
+
+ if (!objc_ivar_template)
+ objc_ivar_template = build_ivar_template ();
+
+ size = ivar_list_length (chain);
+
+ generating_instance_variables = 1;
+ ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
+ initlist = build_ivar_list_initializer (objc_ivar_template, chain);
+ generating_instance_variables = 0;
+
+ decl = start_var_decl (ivar_list_template, name);
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
+
+ OBJCMETA (decl, objc_meta, meta_base);
+ finish_var_decl (decl,
+ objc_build_constructor (TREE_TYPE (decl), inits));
+
+ return decl;
+}
+
+/* static struct objc_class _OBJC_METACLASS_Foo={ ... };
+ static struct objc_class _OBJC_CLASS_Foo={ ... }; */
+
+static void
+generate_class_structures (struct imp_entry *impent)
+{
+ tree name_expr, super_expr, root_expr, class_decl, meta_decl;
+ tree my_root_id, my_super_id;
+ tree cast_type, initlist, protocol_decl;
+ tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
+ tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
+ location_t loc;
+ char buf[BUFSIZE];
+ int cls_flags = 0 ;
+
+/* objc_implementation_context = impent->imp_context;
+ implementation_template = impent->imp_template;*/
+ class_decl = impent->class_decl;
+ meta_decl = impent->meta_decl;
+/* UOBJC_CLASS_decl = impent->class_decl;
+ UOBJC_METACLASS_decl = impent->meta_decl;*/
+
+ loc = DECL_SOURCE_LOCATION (impent->class_decl);
+
+ my_super_id = CLASS_SUPER_NAME (impent->imp_template);
+ if (my_super_id)
+ {
+ add_class_reference (my_super_id);
+
+ /* Compute "my_root_id" - this is required for code generation.
+ the "isa" for all meta class structures points to the root of
+ the inheritance hierarchy (e.g. "__Object")... */
+ my_root_id = my_super_id;
+ do
+ {
+ tree my_root_int = lookup_interface (my_root_id);
+
+ if (my_root_int && CLASS_SUPER_NAME (my_root_int))
+ my_root_id = CLASS_SUPER_NAME (my_root_int);
+ else
+ break;
+ }
+ while (1);
+ }
+ else
+ /* No super class. */
+ my_root_id = CLASS_NAME (impent->imp_template);
+
+ cast_type = build_pointer_type (objc_class_template);
+ name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
+ class_names);
+
+ /* Install class `isa' and `super' pointers at runtime. */
+ if (my_super_id)
+ super_expr = add_objc_string (my_super_id, class_names);
+ else
+ super_expr = null_pointer_node;
+
+ super_expr = build_c_cast (loc, cast_type, super_expr);
+
+ root_expr = add_objc_string (my_root_id, class_names);
+ root_expr = build_c_cast (loc, cast_type, root_expr);
+
+ if (CLASS_PROTOCOL_LIST (impent->imp_template))
+ {
+ generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
+ protocol_decl = generate_protocol_list (impent->imp_template,
+ impent->imp_context);
+ }
+ else
+ protocol_decl = NULL_TREE;
+
+ if (CLASS_CLS_METHODS (impent->imp_context))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
+ buf);
+ }
+
+ if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
+ && (chain = TYPE_FIELDS (objc_class_template)))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ class_ivars = generate_ivars_list (chain, buf);
+ }
+
+ /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
+
+ initlist =
+ build_shared_structure_initializer
+ (TREE_TYPE (meta_decl),
+ root_expr, super_expr, name_expr,
+ convert (integer_type_node,
+ TYPE_SIZE_UNIT (objc_class_template)),
+ CLS_META, class_methods, class_ivars,
+ protocol_decl);
+
+ finish_var_decl (meta_decl, initlist);
+ impent->meta_decl = meta_decl;
+
+ /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
+ if (CLASS_NST_METHODS (impent->imp_context))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
+ buf);
+ }
+
+ if ((chain = CLASS_IVARS (impent->imp_template)))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ inst_ivars = generate_ivars_list (chain, buf);
+ }
+
+ initlist =
+ build_shared_structure_initializer
+ (TREE_TYPE (class_decl),
+ build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
+ super_expr, name_expr,
+ convert (integer_type_node,
+ TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE
+ (impent->imp_template))),
+ CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
+ protocol_decl);
+
+ finish_var_decl (class_decl, initlist);
+ impent->class_decl = class_decl;
+}
+
+/* --- Output GNU Metadata --- */
+
+/* TODO: Make this into an array of refs. */
+static void
+handle_class_ref (tree chain)
+{
+ const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
+ char *string = (char *) alloca (strlen (name) + 30);
+ tree decl;
+ tree exp;
+
+ sprintf (string, "__objc_class_name_%s", name);
+
+ /* Make a decl for this name, so we can use its address in a tree. */
+ decl = build_decl (input_location,
+ VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node));
+ DECL_EXTERNAL (decl) = 1;
+ TREE_PUBLIC (decl) = 1;
+ DECL_CONTEXT (decl) = NULL_TREE;
+ finish_var_decl (decl, 0);
+
+ /* Make a decl for the address. */
+ sprintf (string, "__objc_class_ref_%s", name);
+ exp = build1 (ADDR_EXPR, string_type_node, decl);
+ decl = build_decl (input_location,
+ VAR_DECL, get_identifier (string), string_type_node);
+ TREE_STATIC (decl) = 1;
+ TREE_USED (decl) = 1;
+ DECL_READ_P (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_INITIAL (decl) = error_mark_node;
+
+ /* We must force the reference. */
+ DECL_PRESERVE_P (decl) = 1;
+
+ DECL_CONTEXT (decl) = NULL_TREE;
+ finish_var_decl (decl, exp);
+}
+
+static tree
+get_proto_encoding (tree proto)
+{
+ tree encoding;
+ if (proto)
+ {
+ if (! METHOD_ENCODING (proto))
+ {
+ encoding = encode_method_prototype (proto);
+ METHOD_ENCODING (proto) = encoding;
+ }
+ else
+ encoding = METHOD_ENCODING (proto);
+
+ return add_objc_string (encoding, meth_var_types);
+ }
+ else
+ return build_int_cst (NULL_TREE, 0);
+}
+
+static void
+build_gnu_selector_translation_table (void)
+{
+ tree chain, expr;
+ VEC(constructor_elt,gc) *inits = NULL;
+ VEC(constructor_elt,gc) *v ;
+
+ /* Cause the selector table (previously forward-declared)
+ to be actually output. */
+
+ for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
+ {
+ tree encoding;
+ if (warn_selector)
+ {
+ /* TODO: improve on the location for the diagnostic. */
+ location_t loc = input_location;
+ diagnose_missing_method (TREE_VALUE (chain), loc);
+ }
+
+ v = NULL;
+ expr = build_selector (TREE_VALUE (chain));
+ encoding = get_proto_encoding (TREE_PURPOSE (chain));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, encoding);
+ expr = objc_build_constructor (objc_selector_template, v);
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+ } /* each element in the chain */
+
+ /* List terminator. */
+ v = NULL;
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
+ expr = objc_build_constructor (objc_selector_template, v);
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+ expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
+ inits);
+ finish_var_decl (UOBJC_SELECTOR_TABLE_decl, expr);
+}
+
+/* Output references to all statically allocated objects. Return the DECL
+ for the array built. */
+
+static void
+generate_static_references (void)
+{
+ tree expr = NULL_TREE;
+ tree class_name, klass, decl;
+ tree cl_chain, in_chain, type
+ = build_array_type (build_pointer_type (void_type_node), NULL_TREE);
+ int num_inst, num_class;
+ char buf[BUFSIZE];
+ VEC(constructor_elt,gc) *decls = NULL;
+
+ 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++)
+ {
+ VEC(constructor_elt,gc) *v = NULL;
+
+ for (num_inst = 0, in_chain = TREE_PURPOSE (cl_chain);
+ in_chain; num_inst++, in_chain = TREE_CHAIN (in_chain));
+
+ snprintf (buf, BUFSIZE, "_OBJC_STATIC_INSTANCES_%d", num_class);
+ decl = start_var_decl (type, buf);
+
+ /* Output {class_name, ...}. */
+ klass = TREE_VALUE (cl_chain);
+ class_name = get_objc_string_decl (OBJC_TYPE_NAME (klass), class_names);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_unary_op (input_location,
+ 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 (input_location,
+ ADDR_EXPR, TREE_VALUE (in_chain), 1);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+
+ /* Output {..., NULL}. */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
+
+ expr = objc_build_constructor (TREE_TYPE (decl), v);
+ OBJCMETA (decl, objc_meta, meta_base);
+ finish_var_decl (decl, expr);
+ CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE,
+ build_unary_op (input_location,
+ ADDR_EXPR, decl, 1));
+ }
+
+ CONSTRUCTOR_APPEND_ELT (decls, NULL_TREE, build_int_cst (NULL_TREE, 0));
+ expr = objc_build_constructor (type, decls);
+ static_instances_decl = start_var_decl (type, "_OBJC_STATIC_INSTANCES");
+ OBJCMETA (static_instances_decl, objc_meta, meta_base);
+ finish_var_decl (static_instances_decl, expr);
+}
+
+/* Create the initial value for the `defs' field of _objc_symtab.
+ This is a CONSTRUCTOR. */
+
+static tree
+init_def_list (tree type)
+{
+ tree expr;
+ struct imp_entry *impent;
+ location_t loc;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ if (imp_count)
+ for (impent = imp_list; impent; impent = impent->next)
+ {
+ if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
+ {
+ loc = DECL_SOURCE_LOCATION (impent->class_decl);
+ expr = build_unary_op (loc,
+ ADDR_EXPR, impent->class_decl, 0);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+ }
+
+ if (cat_count)
+ for (impent = imp_list; impent; impent = impent->next)
+ {
+ if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
+ {
+ loc = DECL_SOURCE_LOCATION (impent->class_decl);
+ expr = build_unary_op (loc,
+ ADDR_EXPR, impent->class_decl, 0);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+ }
+
+ loc = UNKNOWN_LOCATION;
+ /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */
+ if (static_instances_decl)
+ expr = build_unary_op (loc, ADDR_EXPR, static_instances_decl, 0);
+ else
+ expr = integer_zero_node;
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ return objc_build_constructor (type, v);
+}
+
+/* Take care of defining and initializing _OBJC_SYMBOLS. */
+
+/* Predefine the following data type:
+
+ struct _objc_symtab
+ {
+ long sel_ref_cnt;
+ SEL *refs;
+ short cls_def_cnt;
+ short cat_def_cnt;
+ void *defs[cls_def_cnt + cat_def_cnt];
+ }; */
+
+static void
+build_objc_symtab_template (void)
+{
+ tree fields, array_type, *chain = NULL;
+ int index;
+
+ objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
+
+ /* long sel_ref_cnt; */
+ fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
+
+ /* SEL *refs; */
+ add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
+
+ /* short cls_def_cnt; */
+ add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
+
+ /* short cat_def_cnt; */
+ add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
+
+ if (TARGET_64BIT)
+ add_field_decl (integer_type_node, "_explicit_padder", &chain);
+
+ /* void *defs[imp_count + cat_count (+ 1)]; */
+ /* NB: The index is one less than the size of the array. */
+ index = imp_count + cat_count;
+ array_type = build_sized_array_type (ptr_type_node, index + 1);
+ add_field_decl (array_type, "defs", &chain);
+
+ objc_finish_struct (objc_symtab_template, fields);
+}
+/* Construct the initial value for all of _objc_symtab. */
+
+static tree
+init_objc_symtab (tree type)
+{
+ tree field, expr, ltyp;
+ location_t loc;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ loc = UNKNOWN_LOCATION;
+
+ /* sel_ref_cnt = { ..., 5, ... } */
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (long_integer_type_node, 0));
+
+ /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
+
+ ltyp = build_pointer_type (objc_selector_type);
+ if (sel_ref_chain)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR,
+ UOBJC_SELECTOR_TABLE_decl, 1));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* cls_def_cnt = { ..., 5, ... } */
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (short_integer_type_node, imp_count));
+
+ /* cat_def_cnt = { ..., 5, ... } */
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (short_integer_type_node, cat_count));
+ if (TARGET_64BIT)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (integer_type_node, 0));
+
+ /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
+
+ field = TYPE_FIELDS (type);
+ if (TARGET_64BIT)
+ field = DECL_CHAIN (field);
+ field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
+
+ return objc_build_constructor (type, v);
+}
+
+/* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
+ and initialized appropriately. */
+
+static void
+generate_objc_symtab_decl (void)
+{
+ build_objc_symtab_template ();
+ UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
+ OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_base);
+ finish_var_decl (UOBJC_SYMBOLS_decl,
+ init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
+}
+
+static void
+objc_generate_v1_gnu_metadata (void)
+{
+ struct imp_entry *impent;
+ tree chain;
+
+ /* Process the static instances here because initialization of objc_symtab
+ depends on them. */
+ if (objc_static_instances)
+ generate_static_references ();
+
+ objc_implementation_context =
+ implementation_template =
+ UOBJC_CLASS_decl =
+ UOBJC_METACLASS_decl = NULL_TREE;
+
+ for (impent = imp_list; impent; impent = impent->next)
+ {
+ /* If -gen-decls is present, Dump the @interface of each class.
+ TODO: Dump the classes in the order they were found, rather than in
+ reverse order as we are doing now. */
+ if (flag_gen_declaration)
+ dump_interface (gen_declaration_file, impent->imp_context);
+
+ /* all of the following reference the string pool... */
+ if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
+ generate_class_structures (impent);
+ else
+ generate_category (impent);
+ }
+
+ /* If we are using an array of selectors, we must always
+ finish up the array decl even if no selectors were used. */
+ build_gnu_selector_translation_table ();
+
+ if (protocol_chain)
+ generate_protocols ();
+
+ /* Arrange for ObjC data structures to be initialized at run time. */
+ generate_objc_symtab_decl ();
+ /* Make sure that the meta-data are identified as being GNU-runtime. */
+ build_module_descriptor (OBJC_VERSION,
+ build_tree_list (objc_meta, meta_base));
+ build_module_initializer_routine ();
+
+ /* Dump the class references. This forces the appropriate classes
+ to be linked into the executable image, preserving unix archive
+ semantics. This can be removed when we move to a more dynamically
+ linked environment. */
+
+ for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
+ {
+ handle_class_ref (chain);
+ if (TREE_PURPOSE (chain))
+ generate_classref_translation_entry (chain);
+ }
+
+ for (impent = imp_list; impent; impent = impent->next)
+ handle_impent (impent);
+
+ generate_strings ();
+}
+
+/* --- exceptions --- */
+
+static GTY(()) tree objc_eh_personality_decl;
+
+static tree
+objc_eh_runtime_type (tree type)
+{
+ tree ident, eh_id, decl, str;
+
+ if (type == error_mark_node
+ || errorcount || sorrycount)
+ {
+ /* Use 'ErrorMarkNode' as class name when error_mark_node is found
+ to prevent an ICE. Note that we know that the compiler will
+ terminate with an error and this 'ErrorMarkNode' class name will
+ never be actually used. */
+ ident = get_identifier ("ErrorMarkNode");
+ goto make_err_class;
+ }
+
+ if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
+ /* We don't want to identify 'id' for GNU. Instead, build a 0
+ entry in the exceptions table. */
+ return null_pointer_node;
+
+ if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
+ {
+#ifdef OBJCPLUS
+ /* This routine is also called for c++ catch clauses; in which case,
+ we use the c++ typeinfo decl. */
+ return build_eh_type_type (type);
+#else
+ error ("non-objective-c type '%T' cannot be caught", type);
+ ident = get_identifier ("ErrorMarkNode");
+ goto make_err_class;
+#endif
+ }
+ else
+ ident = OBJC_TYPE_NAME (TREE_TYPE (type));
+
+make_err_class:
+ /* If this class was already referenced, then it will be output during
+ meta-data emission, so we don't need to do it here. */
+ decl = get_objc_string_decl (ident, class_names);
+ eh_id = add_objc_string (ident, class_names);
+ if (!decl)
+ {
+ /* Not found ... so we need to build it - from the freshly-entered id. */
+ decl = get_objc_string_decl (ident, class_names);
+ str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
+ IDENTIFIER_POINTER (ident));
+ /* We have to finalize this var here, because this might be called after
+ all the other metadata strings have been emitted. */
+ finish_var_decl (decl, str);
+ }
+ return eh_id;
+}
+
+static tree
+objc_eh_personality (void)
+{
+ if (!objc_eh_personality_decl)
+#ifndef OBJCPLUS
+ objc_eh_personality_decl = build_personality_function ("gnu_objc");
+#else
+ objc_eh_personality_decl = build_personality_function ("gxx");
+#endif
+ return objc_eh_personality_decl;
+}
+
+/* -- interfaces --- */
+
+static tree
+build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
+{
+ tree t;
+ VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
+ /* A throw is just a call to the runtime throw function with the
+ object as a parameter. */
+ VEC_quick_push (tree, parms, throw_expr);
+ t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
+ VEC_free (tree, gc, parms);
+ return add_stmt (t);
+}
+
+/* Build __builtin_eh_pointer. */
+
+static tree
+objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
+{
+ tree t;
+ t = built_in_decls[BUILT_IN_EH_POINTER];
+ t = build_call_expr (t, 1, integer_zero_node);
+ return fold_convert (objc_object_type, t);
+}
+
+static tree
+begin_catch (struct objc_try_context **cur_try_context, tree type,
+ tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
+{
+ tree t;
+ /* Record the data for the catch in the try context so that we can
+ finalize it later. */
+ if (ellipsis)
+ t = build_stmt (input_location, CATCH_EXPR, NULL, compound);
+ else
+ t = build_stmt (input_location, CATCH_EXPR, type, compound);
+ (*cur_try_context)->current_catch = t;
+
+ /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
+ t = objc_build_exc_ptr (cur_try_context);
+ t = convert (TREE_TYPE (decl), t);
+ return build2 (MODIFY_EXPR, void_type_node, decl, t);
+}
+
+static void
+finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
+{
+ append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
+}
+
+static tree
+finish_try_stmt (struct objc_try_context **cur_try_context)
+{
+ struct objc_try_context *c = *cur_try_context;
+ tree stmt = c->try_body;
+ if (c->catch_list)
+ stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
+ if (c->finally_body)
+ stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
+ return stmt;
+}
+
+#include "gt-objc-objc-gnu-runtime-abi-01.h"
diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c
index e4ae292..fd657765 100644
--- a/gcc/objc/objc-lang.c
+++ b/gcc/objc/objc-lang.c
@@ -1,5 +1,5 @@
/* Language-dependent hooks for Objective-C.
- Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010
+ Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010, 2011
Free Software Foundation, Inc.
Contributed by Ziemowit Laski <zlaski@apple.com>
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "langhooks-def.h"
#include "c-objc-common.h"
+#include "c-lang.h"
enum c_language_kind c_language = clk_objc;
static void objc_init_ts (void);
@@ -51,13 +52,6 @@ static void objc_init_ts (void);
#undef LANG_HOOKS_INIT_TS
#define LANG_HOOKS_INIT_TS objc_init_ts
-#ifndef OBJCPLUS
-#undef LANG_HOOKS_EH_PERSONALITY
-#define LANG_HOOKS_EH_PERSONALITY objc_eh_personality
-#undef LANG_HOOKS_EH_RUNTIME_TYPE
-#define LANG_HOOKS_EH_RUNTIME_TYPE objc_eh_runtime_type
-#endif
-
/* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
diff --git a/gcc/objc/objc-next-metadata-tags.h b/gcc/objc/objc-next-metadata-tags.h
new file mode 100644
index 0000000..db0026e
--- /dev/null
+++ b/gcc/objc/objc-next-metadata-tags.h
@@ -0,0 +1,172 @@
+/* Declarations for meta-data attribute tags.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Iain Sandoe
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* These are identifiers used to flag meta-data attributes such that they
+ survive LTO and might be placed in correct sections for the target. */
+
+enum objc_runtime_tree_index
+{
+ OCTI_RT_OBJC_META,
+ OCTI_RT_META_BASE,
+
+ OCTI_RT_META_CLASS,
+ OCTI_RT_META_METACLASS,
+ OCTI_RT_META_CATEGORY,
+ OCTI_RT_META_PROTOCOL,
+
+ OCTI_RT_META_CLASS_CLS_VARS,
+ OCTI_RT_META_CLASS_NST_VARS,
+
+ OCTI_RT_META_CLASS_CLS_METH,
+ OCTI_RT_META_CLASS_NST_METH,
+ OCTI_RT_META_CATEG_CLS_METH,
+ OCTI_RT_META_CATEG_NST_METH,
+ OCTI_RT_META_PROTO_CLS_METH,
+ OCTI_RT_META_PROTO_NST_METH,
+
+ OCTI_RT_META_CLASS_PROT,
+ OCTI_RT_META_CATEG_PROT,
+ OCTI_RT_META_PROT_REFS,
+
+ OCTI_RT_META_MSG_REFS,
+ OCTI_RT_META_SEL_REFS,
+
+ OCTI_RT_META_CLSLST_REFS,
+ OCTI_RT_META_CLASS_REF,
+ OCTI_RT_META_SUPER_REF,
+ OCTI_RT_META_CLSLST_NLZY_LAB,
+ OCTI_RT_META_CLSLST_LAB,
+ OCTI_RT_META_LAB_PROTOLIST,
+ OCTI_RT_META_LAB_NLZY_CAT,
+ OCTI_RT_META_LAB_CAT,
+
+ OCTI_RT_META_PROPERTY_LIST,
+ OCTI_RT_META_PROTOCOL_EXT,
+ OCTI_RT_META_CLASS_EXT,
+
+ OCTI_RT_META_CLASS_NAME,
+ OCTI_RT_META_METHD_NAME,
+ OCTI_RT_META_METHD_TYPE,
+ OCTI_RT_META_PROPN_ATTR,
+
+ OCTI_RT_META_MODULES,
+ OCTI_RT_META_SYMTAB,
+ OCTI_RT_META_INFO,
+
+ OCTI_RT_META_EHTYPE,
+
+ OCTI_RT_META_CONST_STR,
+
+ OCTI_RT_META_MAX
+};
+
+/* Tags for the META data so that the backend can put them in the correct
+ sections for targets/runtimes (Darwin/NeXT) that require this.
+ This information also survives LTO - which might produce mixed language
+ output. */
+
+/* Objective-C meta data attribute tag */
+#define objc_meta objc_rt_trees[OCTI_RT_OBJC_META]
+/* Attribute values, base = default section. */
+#define meta_base objc_rt_trees[OCTI_RT_META_BASE]
+
+ /* CLASS. */
+#define meta_class objc_rt_trees[OCTI_RT_META_CLASS]
+ /* METACLASS. */
+#define meta_metaclass objc_rt_trees[OCTI_RT_META_METACLASS]
+ /* CLASS. */
+#define meta_category objc_rt_trees[OCTI_RT_META_CATEGORY]
+ /* PROTOCOL. */
+#define meta_protocol objc_rt_trees[OCTI_RT_META_PROTOCOL]
+
+ /* Class class vars section. */
+#define meta_clac_vars objc_rt_trees[OCTI_RT_META_CLASS_CLS_VARS]
+ /* Class instance vars section. */
+#define meta_clai_vars objc_rt_trees[OCTI_RT_META_CLASS_NST_VARS]
+ /* Class class methods section. */
+#define meta_clac_meth objc_rt_trees[OCTI_RT_META_CLASS_CLS_METH]
+ /* Class instance methods section. */
+#define meta_clai_meth objc_rt_trees[OCTI_RT_META_CLASS_NST_METH]
+ /* Category class methods section. */
+#define meta_catc_meth objc_rt_trees[OCTI_RT_META_CATEG_CLS_METH]
+ /* Category instance methods section. */
+#define meta_cati_meth objc_rt_trees[OCTI_RT_META_CATEG_NST_METH]
+#define meta_proto_cls_meth \
+ objc_rt_trees[OCTI_RT_META_PROTO_CLS_METH]
+#define meta_proto_nst_meth \
+ objc_rt_trees[OCTI_RT_META_PROTO_NST_METH]
+
+ /* Class protocols. */
+#define meta_clas_prot objc_rt_trees[OCTI_RT_META_CLASS_PROT]
+ /* Category protocols. */
+#define meta_catg_prot objc_rt_trees[OCTI_RT_META_CATEG_PROT]
+ /* Protocol references. */
+#define meta_proto_ref objc_rt_trees[OCTI_RT_META_PROT_REFS]
+
+ /* Message refs. */
+#define meta_mref objc_rt_trees[OCTI_RT_META_MSG_REFS]
+ /* Selector refs. */
+#define meta_sel_refs objc_rt_trees[OCTI_RT_META_SEL_REFS]
+
+ /* Class list refs. */
+#define meta_class_ref objc_rt_trees[OCTI_RT_META_CLSLST_REFS]
+#define meta_class_reference \
+ objc_rt_trees[OCTI_RT_META_CLASS_REF]
+#define meta_superclass_ref \
+ objc_rt_trees[OCTI_RT_META_SUPER_REF]
+ /* Class list Label. */
+#define meta_label_classlist \
+ objc_rt_trees[OCTI_RT_META_CLSLST_LAB]
+ /* Class list Label (non lazy). */
+#define meta_label_nonlazy_classlist \
+ objc_rt_trees[OCTI_RT_META_CLSLST_NLZY_LAB]
+#define meta_label_categorylist \
+ objc_rt_trees[OCTI_RT_META_LAB_CAT]
+#define meta_label_nonlazy_categorylist \
+ objc_rt_trees[OCTI_RT_META_LAB_NLZY_CAT]
+
+#define meta_label_protocollist \
+ objc_rt_trees[OCTI_RT_META_LAB_PROTOLIST]
+
+
+/* V1 - property list. */
+#define meta_proplist objc_rt_trees[OCTI_RT_META_PROPERTY_LIST]
+#define meta_protocol_extension \
+ objc_rt_trees[OCTI_RT_META_PROTOCOL_EXT]
+#define meta_class_extension \
+ objc_rt_trees[OCTI_RT_META_CLASS_EXT]
+ /* String sections. */
+#define meta_class_name objc_rt_trees[OCTI_RT_META_CLASS_NAME]
+#define meta_meth_name objc_rt_trees[OCTI_RT_META_METHD_NAME]
+#define meta_meth_type objc_rt_trees[OCTI_RT_META_METHD_TYPE]
+#define meta_prop_name_attr \
+ objc_rt_trees[OCTI_RT_META_PROPN_ATTR]
+
+#define meta_modules objc_rt_trees[OCTI_RT_META_MODULES]
+#define meta_symtab objc_rt_trees[OCTI_RT_META_SYMTAB]
+#define meta_info objc_rt_trees[OCTI_RT_META_INFO]
+
+#define meta_ehtype objc_rt_trees[OCTI_RT_META_EHTYPE]
+
+#define meta_const_str objc_rt_trees[OCTI_RT_META_CONST_STR]
+
+#define OBJCMETA(DECL,VERS,KIND) \
+ if (VERS) \
+ DECL_ATTRIBUTES (DECL) = build_tree_list ((VERS), (KIND));
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
new file mode 100644
index 0000000..2cfa862
--- /dev/null
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -0,0 +1,2969 @@
+/* Next Runtime (ABI-0/1) private.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Iain Sandoe (split from objc-act.c)
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This implements the original NeXT ABI (0) used for m32 code and indicated
+ by module version 6. It also implements the small number of additions made
+ for properties and optional protocol methods as ABI=1
+ (module version 7). */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+
+#ifdef OBJCPLUS
+#include "cp-tree.h"
+#else
+#include "c-tree.h"
+#include "c-lang.h"
+#endif
+#include "langhooks.h"
+#include "c-family/c-objc.h"
+#include "objc-act.h"
+
+/* When building Objective-C++, we are not linking against the C front-end
+ and so need to replicate the C tree-construction functions in some way. */
+#ifdef OBJCPLUS
+#define OBJCP_REMAP_FUNCTIONS
+#include "objcp-decl.h"
+#endif /* OBJCPLUS */
+
+#include "ggc.h"
+#include "target.h"
+#include "output.h"
+#include "tree-iterator.h"
+
+#include "objc-runtime-hooks.h"
+#include "objc-runtime-shared-support.h"
+
+/* NeXT ABI 0 and 1 private definitions. */
+#define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
+
+#define TAG_GETCLASS "objc_getClass"
+#define TAG_GETMETACLASS "objc_getMetaClass"
+
+#define TAG_MSGSEND "objc_msgSend"
+#define TAG_MSGSENDSUPER "objc_msgSendSuper"
+#define TAG_MSGSEND_STRET "objc_msgSend_stret"
+#define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
+
+/* NeXT-specific tags. */
+
+#define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
+#define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
+#define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
+#define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
+#define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
+#define TAG_EXCEPTIONMATCH "objc_exception_match"
+#define TAG_SETJMP "_setjmp"
+
+#define TAG_ASSIGNIVAR "objc_assign_ivar"
+#define TAG_ASSIGNGLOBAL "objc_assign_global"
+#define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast"
+
+/* Branch entry points. All that matters here are the addresses;
+ functions with these names do not really exist in libobjc. */
+
+#define TAG_MSGSEND_FAST "objc_msgSend_Fast"
+#define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast"
+
+/* The version identifies which language generation and runtime
+ the module (file) was compiled for, and is recorded in the
+ module descriptor. */
+#define OBJC_VERSION (flag_objc_abi >= 1 ? 7 : 6)
+
+#define UTAG_CLASS_EXT "_objc_class_ext"
+#define UTAG_PROPERTY_LIST "_prop_list_t"
+#define UTAG_PROTOCOL_EXT "_objc_protocol_extension"
+
+#define CLS_HAS_CXX_STRUCTORS 0x2000L
+
+/* rt_trees identifiers - shared between NeXT implementations. These allow
+ the FE to tag meta-data in a manner that survives LTO and can be used when
+ the runtime requires that certain meta-data items appear in particular
+ named sections. */
+
+#include "objc-next-metadata-tags.h"
+extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
+
+static void next_runtime_01_initialize (void);
+
+static tree next_runtime_abi_01_super_superclassfield_id (void);
+
+static tree next_runtime_abi_01_class_decl (tree);
+static tree next_runtime_abi_01_metaclass_decl (tree);
+static tree next_runtime_abi_01_category_decl (tree);
+static tree next_runtime_abi_01_protocol_decl (tree);
+static tree next_runtime_abi_01_string_decl (tree, const char *, string_section);
+
+static tree next_runtime_abi_01_get_class_reference (tree);
+static tree next_runtime_abi_01_build_selector_reference (location_t, tree, tree);
+static tree next_runtime_abi_01_get_protocol_reference (location_t, tree);
+static tree next_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
+static tree next_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
+static tree next_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
+
+static tree next_runtime_abi_01_receiver_is_class_object (tree);
+static tree next_runtime_abi_01_get_arg_type_list_base (tree, int, int);
+static tree next_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
+ tree, tree, tree, int);
+static bool next_runtime_abi_01_setup_const_string_class_decl (void);
+static tree next_runtime_abi_01_build_const_string_constructor (location_t, tree, int);
+
+static void objc_generate_v1_next_metadata (void);
+
+static void build_next_objc_exception_stuff (void);
+static tree objc_eh_runtime_type (tree type);
+static tree objc_eh_personality (void);
+static tree build_throw_stmt (location_t, tree, bool);
+static tree objc_build_exc_ptr (struct objc_try_context **);
+static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
+static void finish_catch (struct objc_try_context **, tree);
+static tree finish_try_stmt (struct objc_try_context **);
+
+bool
+objc_next_runtime_abi_01_init (objc_runtime_hooks *rthooks)
+{
+ if (flag_objc_exceptions
+ && !flag_objc_sjlj_exceptions)
+ {
+ warning_at (UNKNOWN_LOCATION, OPT_Wall,
+ "%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
+ "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> < 2");
+ }
+
+ rthooks->initialize = next_runtime_01_initialize;
+ rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
+ rthooks->tag_getclass = TAG_GETCLASS;
+ rthooks->super_superclassfield_ident = next_runtime_abi_01_super_superclassfield_id;
+
+ rthooks->class_decl = next_runtime_abi_01_class_decl;
+ rthooks->metaclass_decl = next_runtime_abi_01_metaclass_decl;
+ rthooks->category_decl = next_runtime_abi_01_category_decl;
+ rthooks->protocol_decl = next_runtime_abi_01_protocol_decl;
+ rthooks->string_decl = next_runtime_abi_01_string_decl;
+
+ rthooks->get_class_reference = next_runtime_abi_01_get_class_reference;
+ rthooks->build_selector_reference = next_runtime_abi_01_build_selector_reference;
+ rthooks->get_protocol_reference = next_runtime_abi_01_get_protocol_reference;
+ rthooks->build_ivar_reference = next_runtime_abi_01_build_ivar_ref;
+ rthooks->get_class_super_ref = next_runtime_abi_01_get_class_super_ref;
+ rthooks->get_category_super_ref = next_runtime_abi_01_get_category_super_ref;
+
+ rthooks->receiver_is_class_object = next_runtime_abi_01_receiver_is_class_object;
+ rthooks->get_arg_type_list_base = next_runtime_abi_01_get_arg_type_list_base;
+ rthooks->build_objc_method_call = next_runtime_abi_01_build_objc_method_call;
+
+ rthooks->setup_const_string_class_decl =
+ next_runtime_abi_01_setup_const_string_class_decl;
+ rthooks->build_const_string_constructor =
+ next_runtime_abi_01_build_const_string_constructor;
+
+ rthooks->build_throw_stmt = build_throw_stmt;
+ rthooks->build_exc_ptr = objc_build_exc_ptr;
+ rthooks->begin_catch = begin_catch;
+ rthooks->finish_catch = finish_catch;
+ rthooks->finish_try_stmt = finish_try_stmt;
+
+ rthooks->generate_metadata = objc_generate_v1_next_metadata;
+ return true;
+}
+
+/* We need a way to convey what kind of meta-data are represented by a given
+ variable, since each type is expected (by the runtime) to be found in a
+ specific named section. The solution must be usable with LTO.
+
+ The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
+ satisfactory for LTO & ABI-2. We now tag ObjC meta-data with identification
+ attributes in the front end. The back-end may choose to act on these as it
+ requires. */
+
+static void
+next_runtime_abi_01_init_metadata_attributes (void)
+{
+ if (!objc_meta)
+ objc_meta = get_identifier ("OBJC1META");
+
+ if (!meta_base)
+ meta_base = get_identifier ("V1_BASE");
+
+ meta_class = get_identifier ("V1_CLAS");
+ meta_metaclass = get_identifier ("V1_META");
+ meta_category = get_identifier ("V1_CATG");
+ meta_protocol = get_identifier ("V1_PROT");
+
+ meta_clac_vars = get_identifier ("V1_CLCV");
+ meta_clai_vars = get_identifier ("V1_CLIV");
+
+ meta_clac_meth = get_identifier ("V1_CLCM");
+ meta_clai_meth = get_identifier ("V1_CLIM");
+ meta_catc_meth = get_identifier ("V1_CACM");
+ meta_cati_meth = get_identifier ("V1_CAIM");
+ meta_proto_cls_meth = get_identifier ("V1_PCLM");
+ meta_proto_nst_meth = get_identifier ("V1_PNSM");
+
+ meta_clas_prot = get_identifier ("V1_CLPR");
+ meta_catg_prot = get_identifier ("V1_CAPR");
+
+ meta_class_reference = get_identifier ("V1_CLRF");
+ meta_proto_ref = get_identifier ("V1_PRFS");
+ meta_sel_refs = get_identifier ("V1_SRFS");
+
+ meta_class_name = get_identifier ("V1_CLSN");
+ meta_meth_name = get_identifier ("V1_METN");
+ meta_meth_type = get_identifier ("V1_METT");
+ meta_prop_name_attr = get_identifier ("V1_STRG");
+
+ meta_modules = get_identifier ("V1_MODU");
+ meta_symtab = get_identifier ("V1_SYMT");
+ meta_info = get_identifier ("V1_INFO");
+
+ meta_proplist = get_identifier ("V1_PLST");
+ meta_protocol_extension = get_identifier ("V1_PEXT");
+ meta_class_extension = get_identifier ("V1_CEXT");
+
+ meta_const_str = get_identifier ("V1_CSTR");
+}
+
+static void build_v1_class_template (void);
+static void build_v1_category_template (void);
+static void build_v1_protocol_template (void);
+
+static void next_runtime_01_initialize (void)
+{
+ tree type;
+
+#ifdef OBJCPLUS
+ /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by default. */
+ if (!global_options_set.x_flag_objc_call_cxx_cdtors)
+ global_options.x_flag_objc_call_cxx_cdtors = 1;
+#endif
+
+ /* Set up attributes to be attached to the meta-data so that they
+ will be placed in the correct sections. */
+ next_runtime_abi_01_init_metadata_attributes ();
+
+ if (flag_objc_abi >= 1)
+ objc_prop_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier ("_prop_list_t")));
+
+ /* Declare type of selector-objects that represent an operation name. */
+ /* `struct objc_selector *' */
+ objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (TAG_SELECTOR)));
+
+ build_v1_class_template ();
+ build_super_template ();
+ build_v1_protocol_template ();
+ build_v1_category_template ();
+
+ /* NB: In order to call one of the ..._stret (struct-returning)
+ functions, the function *MUST* first be cast to a signature that
+ corresponds to the actual ObjC method being invoked. This is
+ what is done by the build_objc_method_call() routine below. */
+
+ /* id objc_msgSend (id, SEL, ...); */
+ /* id objc_msgSendNonNil (id, SEL, ...); */
+ /* id objc_msgSend_stret (id, SEL, ...); */
+ /* id objc_msgSendNonNil_stret (id, SEL, ...); */
+ type = build_varargs_function_type_list (objc_object_type,
+ objc_object_type,
+ objc_selector_type,
+ NULL_TREE);
+
+ umsg_decl = add_builtin_function (TAG_MSGSEND,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ umsg_nonnil_decl = add_builtin_function (TAG_MSGSEND_NONNIL,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ umsg_stret_decl = add_builtin_function (TAG_MSGSEND_STRET,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ umsg_nonnil_stret_decl = add_builtin_function (TAG_MSGSEND_NONNIL_STRET,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ /* These can throw, because the function that gets called can throw
+ in Obj-C++, or could itself call something that can throw even
+ in Obj-C. */
+ TREE_NOTHROW (umsg_decl) = 0;
+ TREE_NOTHROW (umsg_nonnil_decl) = 0;
+ TREE_NOTHROW (umsg_stret_decl) = 0;
+ TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
+
+ /* id objc_msgSend_Fast (id, SEL, ...)
+ __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
+#ifdef OFFS_MSGSEND_FAST
+ umsg_fast_decl = add_builtin_function (TAG_MSGSEND_FAST,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (umsg_fast_decl) = 0;
+ DECL_ATTRIBUTES (umsg_fast_decl)
+ = tree_cons (get_identifier ("hard_coded_address"),
+ build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
+ NULL_TREE);
+#else
+ /* No direct dispatch available. */
+ umsg_fast_decl = umsg_decl;
+#endif
+
+ /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
+ /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
+ type = build_varargs_function_type_list (objc_object_type,
+ objc_super_type,
+ objc_selector_type,
+ NULL_TREE);
+ umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ umsg_super_stret_decl = add_builtin_function (TAG_MSGSENDSUPER_STRET,
+ type, 0, NOT_BUILT_IN, 0,
+ NULL_TREE);
+ TREE_NOTHROW (umsg_super_decl) = 0;
+ TREE_NOTHROW (umsg_super_stret_decl) = 0;
+
+ type = build_function_type_list (objc_object_type,
+ const_string_type_node,
+ NULL_TREE);
+
+ /* id objc_getClass (const char *); */
+ objc_get_class_decl
+ = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ /* id objc_getMetaClass (const char *); */
+ objc_get_meta_class_decl
+ = add_builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+
+ /* This is the type of all of the following functions objc_copyStruct(). */
+ type = build_function_type_list (void_type_node,
+ ptr_type_node,
+ const_ptr_type_node,
+ ptrdiff_type_node,
+ boolean_type_node,
+ boolean_type_node,
+ NULL_TREE);
+ /* Declare the following function:
+ void
+ objc_copyStruct (void *destination, const void *source,
+ ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
+ objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (objc_copyStruct_decl) = 0;
+ objc_getPropertyStruct_decl = NULL_TREE;
+ objc_setPropertyStruct_decl = NULL_TREE;
+
+ build_next_objc_exception_stuff ();
+ if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
+ using_eh_for_cleanups ();
+ lang_hooks.eh_runtime_type = objc_eh_runtime_type;
+ lang_hooks.eh_personality = objc_eh_personality;
+}
+
+/* --- templates --- */
+
+/* struct _objc_class {
+ struct _objc_class *isa;
+ struct _objc_class *super_class;
+ char *name;
+ long version;
+ long info;
+ long instance_size;
+ struct _objc_ivar_list *ivars;
+ struct _objc_method_list *methods;
+ struct objc_cache *cache;
+ struct _objc_protocol_list *protocols;
+ #if ABI=1
+ const char *ivar_layout;
+ struct _objc_class_ext *ext;
+ #else
+ void *sel_id;
+ void *gc_object_type;
+ #endif
+ }; */
+
+/* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT runtime.
+ We generate them for ABI==0 to maintain backward binary compatibility. */
+
+static void
+build_v1_class_template (void)
+{
+ tree ptype, decls, *chain = NULL;
+
+ objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
+
+ /* struct _objc_class *isa; */
+ decls = add_field_decl (build_pointer_type (objc_class_template),
+ "isa", &chain);
+
+ /* struct _objc_class *super_class; */
+ add_field_decl (build_pointer_type (objc_class_template),
+ "super_class", &chain);
+
+ /* char *name; */
+ add_field_decl (string_type_node, "name", &chain);
+
+ /* long version; */
+ add_field_decl (long_integer_type_node, "version", &chain);
+
+ /* long info; */
+ add_field_decl (long_integer_type_node, "info", &chain);
+
+ /* long instance_size; */
+ add_field_decl (long_integer_type_node, "instance_size", &chain);
+
+ /* struct _objc_ivar_list *ivars; */
+ add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
+
+ /* struct _objc_method_list *methods; */
+ add_field_decl (objc_method_list_ptr, "methods", &chain);
+
+ /* struct objc_cache *cache; */
+ ptype = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier ("objc_cache")));
+ add_field_decl (ptype, "cache", &chain);
+
+ /* struct _objc_protocol **protocol_list; */
+ ptype = build_pointer_type (build_pointer_type
+ (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_PROTOCOL))));
+ add_field_decl (ptype, "protocol_list", &chain);
+
+ if (flag_objc_abi >= 1)
+ {
+ /* const char *ivar_layout; */
+ add_field_decl (const_string_type_node, "ivar_layout", &chain);
+
+ /* struct _objc_class_ext *ext; */
+ ptype = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_CLASS_EXT)));
+ add_field_decl (ptype, "ext", &chain);
+ }
+ else
+ {
+ /* void *sel_id; */
+ add_field_decl (build_pointer_type (void_type_node), "sel_id", &chain);
+ /* void *gc_object_type; */
+ add_field_decl (build_pointer_type (void_type_node), "gc_object_type",
+ &chain);
+ }
+
+ objc_finish_struct (objc_class_template, decls);
+}
+
+/* struct _objc_category {
+ char *category_name;
+ char *class_name;
+ struct _objc_method_list *instance_methods;
+ struct _objc_method_list *class_methods;
+ struct _objc_protocol_list *protocols;
+ if ABI=1
+ uint32_t size; // sizeof (struct _objc_category)
+ struct _objc_property_list *instance_properties; // category's own @property decl.
+ END
+ }; */
+
+static void
+build_v1_category_template (void)
+{
+ tree ptype, decls, *chain = NULL;
+
+ objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
+
+ /* char *category_name; */
+ decls = add_field_decl (string_type_node, "category_name", &chain);
+
+ /* char *class_name; */
+ add_field_decl (string_type_node, "class_name", &chain);
+
+ /* struct _objc_method_list *instance_methods; */
+ add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
+
+ /* struct _objc_method_list *class_methods; */
+ add_field_decl (objc_method_list_ptr, "class_methods", &chain);
+
+ /* struct _objc_protocol **protocol_list; */
+ ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
+ add_field_decl (ptype, "protocol_list", &chain);
+
+ if (flag_objc_abi >= 1)
+ {
+ add_field_decl (integer_type_node, "size", &chain);
+
+ /* struct _objc_property_list *instance_properties;
+ This field describes a category's @property declarations.
+ Properties from inherited protocols are not included. */
+ ptype = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_PROPERTY_LIST)));
+ add_field_decl (ptype, "instance_properties", &chain);
+ }
+ objc_finish_struct (objc_category_template, decls);
+}
+
+/* Begin code generation for protocols...
+ Modified for ObjC #1 extensions. */
+
+/* struct _objc_protocol {
+ IF ABI=1
+ struct _objc_protocol_extension *isa;
+ ElSE
+ struct _objc_class *isa;
+
+ char *protocol_name;
+ struct _objc_protocol **protocol_list;
+ struct _objc__method_prototype_list *instance_methods;
+ struct _objc__method_prototype_list *class_methods;
+ }; */
+
+static void
+build_v1_protocol_template (void)
+{
+ tree ptype, decls, *chain = NULL;
+
+ objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
+
+ if (flag_objc_abi >= 1)
+ /* struct _objc_protocol_extension *isa; */
+ ptype = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_PROTOCOL_EXT)));
+ else
+ /* struct _objc_class *isa; */
+ ptype = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_CLASS)));
+
+ decls = add_field_decl (ptype, "isa", &chain);
+
+ /* char *protocol_name; */
+ add_field_decl (string_type_node, "protocol_name", &chain);
+
+ /* struct _objc_protocol **protocol_list; */
+ ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
+ add_field_decl (ptype, "protocol_list", &chain);
+
+ /* struct _objc__method_prototype_list *instance_methods; */
+ add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
+
+ /* struct _objc__method_prototype_list *class_methods; */
+ add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
+
+ objc_finish_struct (objc_protocol_template, decls);
+}
+
+/* --- names, decls identifers --- */
+
+static tree
+next_runtime_abi_01_super_superclassfield_id (void)
+{
+ if (!super_superclassfield_id)
+ super_superclassfield_id = get_identifier ("super_class");
+ return super_superclassfield_id;
+}
+
+static tree
+next_runtime_abi_01_class_decl (tree klass)
+{
+ tree decl;
+ char buf[BUFSIZE];
+ snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass)));
+ decl = start_var_decl (objc_class_template, buf);
+ OBJCMETA (decl, objc_meta, meta_class);
+ return decl;
+}
+
+static tree
+next_runtime_abi_01_metaclass_decl (tree klass)
+{
+ tree decl;
+ char buf[BUFSIZE];
+ snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass)));
+ decl = start_var_decl (objc_class_template, buf);
+ OBJCMETA (decl, objc_meta, meta_metaclass);
+ return decl;
+}
+
+static tree
+next_runtime_abi_01_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)));
+ decl = start_var_decl (objc_category_template, buf);
+ OBJCMETA (decl, objc_meta, meta_category);
+ return decl;
+}
+
+static tree
+next_runtime_abi_01_protocol_decl (tree p)
+{
+ tree decl;
+ char buf[BUFSIZE];
+
+ /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
+
+ snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
+ decl = start_var_decl (objc_protocol_template, buf);
+ OBJCMETA (decl, objc_meta, meta_protocol);
+ return decl;
+}
+
+static tree
+next_runtime_abi_01_string_decl (tree type, const char *name, string_section where)
+{
+ tree var = start_var_decl (type, name);
+ switch (where)
+ {
+ case class_names:
+ OBJCMETA (var, objc_meta, meta_class_name);
+ break;
+ case meth_var_names:
+ OBJCMETA (var, objc_meta, meta_meth_name);
+ break;
+ case meth_var_types:
+ OBJCMETA (var, objc_meta, meta_meth_type);
+ break;
+ case prop_names_attr:
+ OBJCMETA (var, objc_meta, meta_prop_name_attr);
+ break;
+ default:
+ OBJCMETA (var, objc_meta, meta_base);
+ break;
+ }
+ return var;
+}
+
+/* --- entry --- */
+
+static GTY(()) int class_reference_idx;
+
+static tree
+build_class_reference_decl (void)
+{
+ tree decl;
+ char buf[BUFSIZE];
+
+ sprintf (buf, "_OBJC_ClassRefs_%d", class_reference_idx++);
+ decl = start_var_decl (objc_class_type, buf);
+
+ return decl;
+}
+
+static tree
+next_runtime_abi_01_get_class_reference (tree ident)
+{
+ if (!flag_zero_link)
+ {
+ tree *chain;
+ tree decl;
+
+ for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
+ if (TREE_VALUE (*chain) == ident)
+ {
+ if (! TREE_PURPOSE (*chain))
+ TREE_PURPOSE (*chain) = build_class_reference_decl ();
+
+ return TREE_PURPOSE (*chain);
+ }
+
+ decl = build_class_reference_decl ();
+ *chain = tree_cons (decl, ident, NULL_TREE);
+ return decl;
+ }
+ else
+ {
+ tree params;
+
+ add_class_reference (ident);
+
+ params = build_tree_list (NULL_TREE,
+ my_build_string_pointer
+ (IDENTIFIER_LENGTH (ident) + 1,
+ IDENTIFIER_POINTER (ident)));
+
+ return build_function_call (input_location, objc_get_class_decl, params);
+ }
+}
+
+/* Used by get_arg_type_list.
+ Return the types for receiver & _cmd at the start of a method argument list.
+ context is either METHOD_DEF or METHOD_REF, saying whether we are trying
+ to define a method or call one. superflag says this is for a send to super.
+ meth may be NULL, in the case that there is no prototype. */
+
+static tree
+next_runtime_abi_01_get_arg_type_list_base (tree meth, int context, int superflag)
+{
+ tree arglist;
+
+ /* Receiver type. */
+ if (superflag)
+ arglist = build_tree_list (NULL_TREE, objc_super_type);
+ else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
+ arglist = build_tree_list (NULL_TREE, objc_instance_type);
+ else
+ arglist = build_tree_list (NULL_TREE, objc_object_type);
+
+ /* Selector type - will eventually change to `int'. */
+ chainon (arglist, build_tree_list (NULL_TREE, objc_selector_type));
+ return arglist;
+}
+
+static tree
+next_runtime_abi_01_receiver_is_class_object (tree receiver)
+{
+ if (TREE_CODE (receiver) == VAR_DECL
+ && IS_CLASS (TREE_TYPE (receiver)))
+ {
+ /* The receiver is a variable created by build_class_reference_decl. */
+ tree chain = cls_ref_chain ;
+ /* Look up the identifier in the relevant chain. */
+ for (; chain; chain = TREE_CHAIN (chain))
+ if (TREE_PURPOSE (chain) == receiver)
+ return TREE_VALUE (chain);
+ }
+ return NULL_TREE;
+}
+
+static tree
+build_selector_reference_decl (tree ident)
+{
+ tree decl;
+ char *t, buf[BUFSIZE];
+
+ snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
+ t = buf;
+ while (*t)
+ {
+ if (*t==':')
+ *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
+ t++;
+ }
+ decl = start_var_decl (objc_selector_type, buf);
+ OBJCMETA (decl, objc_meta, meta_sel_refs);
+ return decl;
+}
+
+static tree
+next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
+ tree ident,
+ tree proto ATTRIBUTE_UNUSED)
+{
+ tree *chain = &sel_ref_chain;
+ tree expr;
+
+ while (*chain)
+ {
+ if (TREE_VALUE (*chain) == ident)
+ return TREE_PURPOSE (*chain);
+
+ chain = &TREE_CHAIN (*chain);
+ }
+
+ expr = build_selector_reference_decl (ident);
+
+ *chain = tree_cons (expr, ident, NULL_TREE);
+
+ return expr;
+}
+
+/* Build a tree expression to send OBJECT the operation SELECTOR,
+ looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
+ assuming the method has prototype METHOD_PROTOTYPE.
+ (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
+ LOC is the location of the expression to build.
+ Use METHOD_PARAMS as list of args to pass to the method.
+ If SUPER_FLAG is nonzero, we look up the superclass's method. */
+
+static tree
+build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
+ tree lookup_object, tree selector,
+ tree method_params)
+{
+ tree sender, sender_cast, method, t;
+ tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
+ VEC(tree, 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 method_param_types =
+ get_arg_type_list (method_prototype, METHOD_REF, super_flag);
+ tree ftype = build_function_type (ret_type, method_param_types);
+
+ 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. */
+ parms = VEC_alloc (tree, gc, 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))
+ sender = (super_flag ? umsg_super_stret_decl
+ : flag_nil_receivers ? umsg_stret_decl
+ : umsg_nonnil_stret_decl);
+ else
+ sender = (super_flag ? umsg_super_decl
+ : (flag_nil_receivers ? (flag_objc_direct_dispatch
+ ? umsg_fast_decl
+ : umsg_decl)
+ : umsg_nonnil_decl));
+ method = build_fold_addr_expr_loc (loc, sender);
+
+ /* Pass the object to the method. */
+ VEC_quick_push (tree, parms, lookup_object);
+ /* Pass the selector to the method. */
+ VEC_quick_push (tree, parms, selector);
+ /* Now append the remainder of the parms. */
+ if (nparm)
+ for (; method_params; method_params = TREE_CHAIN (method_params))
+ VEC_quick_push (tree, parms, 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);
+ t = build_function_call_vec (loc, t, parms, NULL);
+ VEC_free (tree, gc, parms);
+ return t;
+}
+
+static tree
+next_runtime_abi_01_build_objc_method_call (location_t loc,
+ tree method_prototype,
+ tree receiver,
+ tree rtype ATTRIBUTE_UNUSED,
+ tree sel_name,
+ tree method_params,
+ int super)
+{
+ tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name,
+ NULL_TREE);
+
+ return build_objc_method_call (loc, super, method_prototype,
+ receiver, selector, method_params);
+}
+
+static tree
+next_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
+{
+ tree expr;
+
+ if (!PROTOCOL_FORWARD_DECL (p))
+ PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_01_protocol_decl (p);
+
+ expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
+ return convert (objc_protocol_type, expr);
+}
+
+/* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */
+
+static tree
+next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
+ tree base, tree id)
+{
+ return objc_build_component_ref (base, id);
+}
+
+/* We build super class references as we need them (but keep them once
+ built for the sake of efficiency). */
+
+static tree
+next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
+ struct imp_entry *imp, bool inst_meth)
+{
+ if (inst_meth)
+ {
+ if (!ucls_super_ref)
+ ucls_super_ref =
+ objc_build_component_ref (imp->class_decl,
+ get_identifier ("super_class"));
+ return ucls_super_ref;
+ }
+ else
+ {
+ if (!uucls_super_ref)
+ uucls_super_ref =
+ objc_build_component_ref (imp->meta_decl,
+ get_identifier ("super_class"));
+ return uucls_super_ref;
+ }
+}
+
+static tree
+next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
+ struct imp_entry *imp, bool inst_meth)
+{
+ tree super_name = CLASS_SUPER_NAME (imp->imp_template);
+ tree super_class;
+
+ if (!flag_zero_link)
+ {
+ super_class = objc_get_class_reference (super_name);
+
+ 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;
+ }
+
+ /* else do it the slow way. */
+ add_class_reference (super_name);
+ super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
+/* assemble_external (super_class);*/
+ 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));
+}
+
+static bool
+next_runtime_abi_01_setup_const_string_class_decl (void)
+{
+ if (!constant_string_global_id)
+ {
+ /* Hopefully, this should not represent a serious limitation. */
+ char buf[BUFSIZE];
+ snprintf (buf, BUFSIZE, "_%sClassReference", constant_string_class_name);
+ constant_string_global_id = get_identifier (buf);
+ }
+
+ string_class_decl = lookup_name (constant_string_global_id);
+
+ return (string_class_decl != NULL_TREE);
+}
+
+static tree
+next_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
+ int length)
+{
+ tree constructor, fields, var;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
+ fields = TYPE_FIELDS (internal_const_str_type);
+ CONSTRUCTOR_APPEND_ELT (v, fields,
+ build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
+
+ fields = DECL_CHAIN (fields);
+ CONSTRUCTOR_APPEND_ELT (v, fields,
+ build_unary_op (loc, ADDR_EXPR, string, 1));
+
+ /* ??? check if this should be long. */
+ fields = DECL_CHAIN (fields);
+ CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
+ constructor = objc_build_constructor (internal_const_str_type, v);
+
+ var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
+ DECL_INITIAL (var) = constructor;
+ TREE_STATIC (var) = 1;
+ DECL_CONTEXT (var) = NULL;
+ OBJCMETA (var, objc_meta, meta_const_str);
+ return var;
+}
+
+/* --- metadata templates --- */
+
+/* This routine builds the following type:
+ struct _prop_t {
+ const char * const name; // property name
+ const char * const attributes; // comma-delimited, encoded,
+ // property attributes
+ };
+*/
+
+static GTY(()) tree objc_v1_property_template;
+
+static tree
+build_v1_property_template (void)
+{
+ tree prop_record;
+ tree decls, *chain = NULL;
+
+ prop_record = objc_start_struct (get_identifier ("_prop_t"));
+ /* const char * name */
+ decls = add_field_decl (string_type_node, "name", &chain);
+
+ /* const char * attribute */
+ add_field_decl (string_type_node, "attribute", &chain);
+
+ objc_finish_struct (prop_record, decls);
+ return prop_record;
+}
+
+/* Build the following type:
+
+ struct _objc_protocol_extension
+ {
+ uint32_t size; // sizeof (struct _objc_protocol_extension)
+ struct objc_method_list *optional_instance_methods;
+ struct objc_method_list *optional_class_methods;
+ struct objc_prop_list *instance_properties;
+ }
+*/
+
+static GTY(()) tree objc_protocol_extension_template;
+
+static void
+build_v1_objc_protocol_extension_template (void)
+{
+ tree decls, *chain = NULL;
+
+ objc_protocol_extension_template =
+ objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT));
+
+ /* uint32_t size; */
+ decls = add_field_decl (integer_type_node, "size", &chain);
+
+ /* struct objc_method_list *optional_instance_methods; */
+ add_field_decl (objc_method_list_ptr, "optional_instance_methods", &chain);
+
+ /* struct objc_method_list *optional_class_methods; */
+ add_field_decl (objc_method_list_ptr, "optional_class_methods", &chain);
+
+ /* struct objc_prop_list *instance_properties; */
+ add_field_decl (objc_prop_list_ptr, "instance_properties", &chain);
+
+ objc_finish_struct (objc_protocol_extension_template, decls);
+}
+
+/* This routine build following struct type:
+ struct _objc_class_ext
+ {
+ uint32_t size; // sizeof(struct _objc_class_ext)
+ const char *weak_ivar_layout;
+ struct _prop_list_t *properties;
+ }
+*/
+
+static GTY(()) tree objc_class_ext_template;
+
+static void
+build_objc_class_ext_template (void)
+{
+ tree ptrt, decls, *chain = NULL;
+
+ objc_class_ext_template = objc_start_struct (get_identifier (UTAG_CLASS_EXT));
+
+ /* uint32_t size; */
+ decls = add_field_decl (integer_type_node, "size", &chain);
+
+ /* const char *weak_ivar_layout; */
+ add_field_decl (const_string_type_node, "weak_ivar_layout", &chain);
+
+ /* struct _prop_list_t *properties; */
+ ptrt = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier(UTAG_PROPERTY_LIST)));
+ add_field_decl (ptrt, "properties", &chain);
+
+ objc_finish_struct (objc_class_ext_template, decls);
+}
+
+static void
+build_metadata_templates (void)
+{
+
+ if (!objc_method_template)
+ objc_method_template = build_method_template ();
+
+
+
+}
+
+/* --- emit metadata --- */
+
+static tree
+generate_v1_meth_descriptor_table (tree chain, tree protocol,
+ const char *prefix, tree attr)
+{
+ tree method_list_template, initlist, decl;
+ int size;
+ VEC(constructor_elt,gc) *v = NULL;
+ char buf[BUFSIZE];
+
+ if (!chain || !prefix)
+ return NULL_TREE;
+
+ if (!objc_method_prototype_template)
+ objc_method_prototype_template = build_method_prototype_template ();
+
+ size = list_length (chain);
+ method_list_template =
+ build_method_prototype_list_template (objc_method_prototype_template,
+ size);
+ snprintf (buf, BUFSIZE, "%s_%s", prefix,
+ IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
+
+ decl = start_var_decl (method_list_template, buf);
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
+ initlist =
+ build_descriptor_table_initializer (objc_method_prototype_template,
+ chain);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
+ /* Get into the right section. */
+ OBJCMETA (decl, objc_meta, attr);
+ finish_var_decl (decl, objc_build_constructor (method_list_template, v));
+ return decl;
+}
+
+/* Build protocol ext =
+ {size, opt_instance_meth, opt_class_meth, instance_props};
+ or NULL_TREE if none are present. */
+
+static tree
+generate_v1_objc_protocol_extension (tree proto_interface,
+ tree opt_instance_meth,
+ tree opt_class_meth,
+ tree instance_props)
+{
+ int size;
+ location_t loc;
+ VEC(constructor_elt,gc) *v = NULL;
+ tree decl, expr;
+ char buf[BUFSIZE];
+
+ /* If there are no extensions, then don't bother... */
+ if (!opt_instance_meth && !opt_class_meth && !instance_props)
+ return NULL_TREE;
+
+ if (!objc_protocol_extension_template)
+ build_v1_objc_protocol_extension_template ();
+
+ /* uint32_t size */
+ size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
+
+ /* Try for meaningful diagnostics. */
+ loc = DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface));
+
+ /* struct objc_method_list *optional_instance_methods; */
+ if (opt_instance_meth)
+ expr = convert (objc_method_list_ptr,
+ build_unary_op (loc, ADDR_EXPR, opt_instance_meth, 0));
+ else
+ expr = convert (objc_method_list_ptr, null_pointer_node);
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* struct objc_method_list *optional_class_methods; */
+ if (opt_class_meth)
+ expr = convert (objc_method_list_ptr,
+ build_unary_op (loc, ADDR_EXPR, opt_class_meth, 0));
+ else
+ expr = convert (objc_method_list_ptr, null_pointer_node);
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ /* struct objc_prop_list *instance_properties; */
+ if (instance_props)
+ expr = convert (objc_prop_list_ptr,
+ build_unary_op (loc, ADDR_EXPR, instance_props, 0));
+ else
+ expr = convert (objc_prop_list_ptr, null_pointer_node);
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ snprintf (buf, BUFSIZE, "_OBJC_ProtocolExt_%s",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface)));
+
+ decl = start_var_decl (objc_protocol_extension_template, buf);
+ expr = objc_build_constructor (TREE_TYPE (decl), v);
+ OBJCMETA (decl, objc_meta, meta_protocol_extension);
+ finish_var_decl (decl, expr);
+ return decl;
+}
+
+/* This routine builds the following type:
+ struct _prop_list_t {
+ uint32_t entsize; // sizeof (struct _prop_t)
+ uint32_t prop_count;
+ struct _prop_t prop_list [prop_count];
+ }
+*/
+
+static tree
+build_v1_property_list_template (tree list_type, int size)
+{
+ tree property_list_t_record;
+ tree array_type, decls, *chain = NULL;
+
+ /* anonymous. */
+ property_list_t_record = objc_start_struct (NULL_TREE);
+
+ /* uint32_t const entsize */
+ decls = add_field_decl (integer_type_node, "entsize", &chain);
+
+ /* int prop_count */
+ add_field_decl (integer_type_node, "prop_count", &chain);
+
+ /* struct _prop_t prop_list[]; */
+ array_type = build_sized_array_type (list_type, size);
+ add_field_decl (array_type, "prop_list", &chain);
+
+ objc_finish_struct (property_list_t_record, decls);
+ return property_list_t_record;
+}
+
+/* This routine builds the initializer list to initialize the
+ 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
+
+static tree
+build_v1_property_table_initializer (tree type, tree context)
+{
+ tree x;
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
+ x = CLASS_PROPERTY_DECL (context);
+ else
+ x = IMPL_PROPERTY_DECL (context);
+
+ for (; x; x = TREE_CHAIN (x))
+ {
+ VEC(constructor_elt,gc) *elemlist = NULL;
+ tree attribute, name_ident = PROPERTY_NAME (x);
+
+ CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
+ add_objc_string (name_ident, prop_names_attr));
+
+ attribute = objc_v2_encode_prop_attr (x);
+ CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
+ add_objc_string (attribute, prop_names_attr));
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ objc_build_constructor (type, elemlist));
+ }
+
+ return objc_build_constructor (build_array_type (type, 0),inits);
+}
+
+/* This routine builds the 'struct _prop_list_t' variable declaration and
+ initializes it with its initializer list. TYPE is 'struct _prop_list_t',
+ NAME is the internal name of this variable, SIZE is number of properties
+ for this class and LIST is the initializer list for its 'prop_list' field. */
+
+static tree
+generate_v1_property_table (tree context, tree klass_ctxt)
+{
+ tree x, decl, initlist, property_list_template;
+ bool is_proto = false;
+ VEC(constructor_elt,gc) *inits = NULL;
+ int init_val, size = 0;
+ char buf[BUFSIZE];
+
+ if (context)
+ {
+ gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
+ x = CLASS_PROPERTY_DECL (context);
+ is_proto = true;
+ }
+ else
+ x = IMPL_PROPERTY_DECL (klass_ctxt);
+
+ for (; x; x = TREE_CHAIN (x))
+ size++;
+
+ if (size == 0)
+ return NULL_TREE;
+
+ if (!objc_v1_property_template)
+ objc_v1_property_template = build_v1_property_template ();
+
+ property_list_template =
+ build_v1_property_list_template (objc_v1_property_template,
+ size);
+ initlist = build_v1_property_table_initializer (objc_v1_property_template,
+ is_proto ? context
+ : klass_ctxt);
+
+ init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template));
+ if (is_proto)
+ snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
+ else
+ snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
+
+ decl = start_var_decl (property_list_template, buf);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, init_val));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
+ x = objc_build_constructor (TREE_TYPE (decl), inits);
+ OBJCMETA (decl, objc_meta, meta_proplist);
+ finish_var_decl (decl, x);
+ return decl;
+}
+
+static tree
+generate_v1_protocol_list (tree i_or_p, tree klass_ctxt)
+{
+ tree array_type, ptype, refs_decl, lproto, e, plist, attr;
+ int size = 0;
+ VEC(constructor_elt,gc) *v = NULL;
+ char buf[BUFSIZE];
+
+ switch (TREE_CODE (i_or_p))
+ {
+ case CLASS_INTERFACE_TYPE:
+ case CATEGORY_INTERFACE_TYPE:
+ plist = CLASS_PROTOCOL_LIST (i_or_p);
+ break;
+ case PROTOCOL_INTERFACE_TYPE:
+ plist = PROTOCOL_LIST (i_or_p);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Compute size. */
+ for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
+ if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
+ && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
+ size++;
+
+ /* Build initializer. */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
+ e = build_int_cst (build_pointer_type (objc_protocol_template), size);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
+
+ for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
+ {
+ tree pval = TREE_VALUE (lproto);
+
+ if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
+ && PROTOCOL_FORWARD_DECL (pval))
+ {
+ tree fwref = PROTOCOL_FORWARD_DECL (pval);
+ location_t loc = DECL_SOURCE_LOCATION (fwref) ;
+ e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
+ }
+ }
+
+ /* static struct objc_protocol *refs[n]; */
+ switch (TREE_CODE (i_or_p))
+ {
+ case PROTOCOL_INTERFACE_TYPE:
+ snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
+ attr = meta_proto_ref;
+ break;
+ case CLASS_INTERFACE_TYPE:
+ snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
+ attr = meta_clas_prot;
+ break;
+ case CATEGORY_INTERFACE_TYPE:
+ snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
+ attr = meta_catg_prot;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ ptype = build_pointer_type (objc_protocol_template);
+ array_type = build_sized_array_type (ptype, size + 3);
+ refs_decl = start_var_decl (array_type, buf);
+
+ OBJCMETA (refs_decl, objc_meta, attr);
+ finish_var_decl (refs_decl,
+ objc_build_constructor (TREE_TYPE (refs_decl), v));
+
+ return refs_decl;
+}
+
+static tree
+build_v1_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
+ tree inst_methods, tree class_methods,
+ tree protocol_ext)
+{
+ tree expr, ttyp;
+ location_t loc;
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ if (!objc_protocol_extension_template)
+ build_v1_objc_protocol_extension_template ();
+
+ /* TODO: find a better representation of location from the inputs. */
+ loc = UNKNOWN_LOCATION;
+ ttyp = build_pointer_type (objc_protocol_extension_template);
+ /* Instead of jamming the protocol version number into the isa, we pass
+ either a pointer to the protocol extension - or NULL. */
+ if (protocol_ext)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, protocol_ext, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
+
+ ttyp = objc_method_proto_list_ptr;
+ if (inst_methods)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ if (class_methods)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ return objc_build_constructor (type, inits);
+}
+
+/* An updated version of generate_protocols () that emit the protocol
+ extension for ABI=1. */
+
+/* For each protocol which was referenced either from a @protocol()
+ expression, or because a class/category implements it (then a
+ pointer to the protocol is stored in the struct describing the
+ class/category), we create a statically allocated instance of the
+ Protocol class. The code is written in such a way as to generate
+ as few Protocol objects as possible; we generate a unique Protocol
+ instance for each protocol, and we don't generate a Protocol
+ instance if the protocol is never referenced (either from a
+ @protocol() or from a class/category implementation). These
+ statically allocated objects can be referred to via the static
+ (that is, private to this module) symbols _OBJC_PROTOCOL_n.
+
+ The statically allocated Protocol objects that we generate here
+ need to be fixed up at runtime in order to be used: the 'isa'
+ pointer of the objects need to be set up to point to the 'Protocol'
+ class, as known at runtime.
+
+ The NeXT runtime fixes up all protocols at program startup time,
+ before main() is entered. It uses a low-level trick to look up all
+ those symbols, then loops on them and fixes them up. */
+
+/* TODO: finish getting rid of passing stuff around in globals. */
+
+static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl;
+static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl;
+static GTY(()) tree V1_ProtocolExt_decl;
+static GTY(()) tree V1_Property_decl;
+
+static void
+generate_v1_protocols (void)
+{
+ tree p;
+
+ /* If a protocol was directly referenced, pull in indirect references. */
+ for (p = protocol_chain; p; p = TREE_CHAIN (p))
+ if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
+ generate_protocol_references (PROTOCOL_LIST (p));
+
+ for (p = protocol_chain; p; p = TREE_CHAIN (p))
+ {
+ tree decl, encoding, initlist, protocol_name_expr;
+ tree refs_type, refs_decl, refs_expr;
+ location_t loc;
+ tree nst_methods = PROTOCOL_NST_METHODS (p);
+ tree cls_methods = PROTOCOL_CLS_METHODS (p);
+
+ /* If protocol wasn't referenced, don't generate any code. */
+ decl = PROTOCOL_FORWARD_DECL (p);
+
+ if (!decl)
+ continue;
+
+ /* Make sure we link in the Protocol class. */
+ add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
+
+ while (nst_methods)
+ {
+ if (! METHOD_ENCODING (nst_methods))
+ {
+ encoding = encode_method_prototype (nst_methods);
+ METHOD_ENCODING (nst_methods) = encoding;
+ }
+ nst_methods = TREE_CHAIN (nst_methods);
+ }
+
+ UOBJC_INSTANCE_METHODS_decl =
+ generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
+ "_OBJC_ProtocolInstanceMethods",
+ meta_proto_nst_meth);
+
+ while (cls_methods)
+ {
+ if (! METHOD_ENCODING (cls_methods))
+ {
+ encoding = encode_method_prototype (cls_methods);
+ METHOD_ENCODING (cls_methods) = encoding;
+ }
+
+ cls_methods = TREE_CHAIN (cls_methods);
+ }
+
+ UOBJC_CLASS_METHODS_decl =
+ generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
+ "_OBJC_ProtocolClassMethods",
+ meta_proto_cls_meth);
+
+ /* There should be no optional methods for ABI-0 - but we need to
+ check all this here before the lists are made. */
+ nst_methods = PROTOCOL_OPTIONAL_NST_METHODS (p);
+ while (nst_methods)
+ {
+ if (! METHOD_ENCODING (nst_methods))
+ {
+ encoding = encode_method_prototype (nst_methods);
+ METHOD_ENCODING (nst_methods) = encoding;
+ }
+ nst_methods = TREE_CHAIN (nst_methods);
+ }
+
+ V1_Protocol_OPT_NST_METHODS_decl =
+ generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
+ "_OBJC_OptionalProtocolInstanceMethods",
+ meta_proto_nst_meth);
+
+ cls_methods = PROTOCOL_OPTIONAL_CLS_METHODS (p);
+ while (cls_methods)
+ {
+ if (! METHOD_ENCODING (cls_methods))
+ {
+ encoding = encode_method_prototype (cls_methods);
+ METHOD_ENCODING (cls_methods) = encoding;
+ }
+
+ cls_methods = TREE_CHAIN (cls_methods);
+ }
+
+ V1_Protocol_OPT_CLS_METHODS_decl =
+ generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
+ "_OBJC_OptionalProtocolClassMethods",
+ meta_proto_cls_meth);
+
+ if (PROTOCOL_LIST (p))
+ refs_decl = generate_v1_protocol_list (p, objc_implementation_context);
+ else
+ refs_decl = 0;
+
+ /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
+ protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
+ /* TODO: more locations to be fixed up... */
+ loc = UNKNOWN_LOCATION;
+ refs_type =
+ build_pointer_type (build_pointer_type (objc_protocol_template));
+ if (refs_decl)
+ refs_expr = convert (refs_type,
+ build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
+ else
+ refs_expr = convert (refs_type, null_pointer_node);
+
+ if (flag_objc_abi < 1)
+ {
+ /* Original ABI. */
+ initlist =
+ build_protocol_initializer (TREE_TYPE (decl),
+ protocol_name_expr, refs_expr,
+ UOBJC_INSTANCE_METHODS_decl,
+ UOBJC_CLASS_METHODS_decl);
+ finish_var_decl (decl, initlist);
+ continue;
+ }
+
+ /* else - V1 extensions. */
+
+ V1_Property_decl =
+ generate_v1_property_table (p, NULL_TREE);
+
+ V1_ProtocolExt_decl =
+ generate_v1_objc_protocol_extension (p,
+ V1_Protocol_OPT_NST_METHODS_decl,
+ V1_Protocol_OPT_CLS_METHODS_decl,
+ V1_Property_decl);
+
+ initlist = build_v1_protocol_initializer (TREE_TYPE (decl),
+ protocol_name_expr, refs_expr,
+ UOBJC_INSTANCE_METHODS_decl,
+ UOBJC_CLASS_METHODS_decl,
+ V1_ProtocolExt_decl);
+ finish_var_decl (decl, initlist);
+ }
+}
+
+static tree
+generate_dispatch_table (tree chain, const char *name, tree attr)
+{
+ tree decl, method_list_template, initlist;
+ VEC(constructor_elt,gc) *v = NULL;
+ int size;;
+
+ if (!chain || !name || !(size = list_length (chain)))
+ return NULL_TREE;
+
+ if (!objc_method_template)
+ objc_method_template = build_method_template ();
+
+ method_list_template = build_method_list_template (objc_method_template,
+ size);
+ initlist = build_dispatch_table_initializer (objc_method_template, chain);
+
+ decl = start_var_decl (method_list_template, name);
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (integer_type_node, size));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
+
+ OBJCMETA (decl, objc_meta, attr);
+ finish_var_decl (decl,
+ objc_build_constructor (TREE_TYPE (decl), v));
+
+ return decl;
+}
+
+/* Init a category. */
+static tree
+build_v1_category_initializer (tree type, tree cat_name, tree class_name,
+ tree inst_methods, tree class_methods,
+ tree protocol_list, tree property_list,
+ location_t loc)
+{
+ tree expr, ltyp;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
+
+ ltyp = objc_method_list_ptr;
+ if (inst_methods)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ if (class_methods)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* protocol_list = */
+ ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
+ if (protocol_list)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ if (flag_objc_abi >= 1)
+ {
+ int val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template));
+ expr = build_int_cst (NULL_TREE, val);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ ltyp = objc_prop_list_ptr;
+ if (property_list)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+
+ return objc_build_constructor (type, v);
+}
+
+/* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
+/* TODO: get rid of passing stuff around in globals. */
+static void
+generate_v1_category (struct imp_entry *impent)
+{
+ tree initlist, cat_name_expr, class_name_expr;
+ tree protocol_decl, category, cat_decl;
+ tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
+ tree cat = impent->imp_context;
+ location_t loc;
+ char buf[BUFSIZE];
+
+ cat_decl = impent->class_decl;
+ loc = DECL_SOURCE_LOCATION (cat_decl);
+
+ add_class_reference (CLASS_NAME (cat));
+ cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
+ class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
+
+ category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
+
+ if (category && CLASS_PROTOCOL_LIST (category))
+ {
+ generate_protocol_references (CLASS_PROTOCOL_LIST (category));
+ protocol_decl = generate_v1_protocol_list (category, cat);
+ }
+ else
+ protocol_decl = 0;
+
+ if (flag_objc_abi >= 1)
+ V1_Property_decl = generate_v1_property_table (NULL_TREE, cat);
+ else
+ V1_Property_decl = NULL_TREE;
+
+ if (CLASS_NST_METHODS (cat))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (cat)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
+ inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf,
+ meta_cati_meth);
+ }
+
+ if (CLASS_CLS_METHODS (cat))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (cat)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
+ class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf,
+ meta_catc_meth);
+ }
+
+ initlist = build_v1_category_initializer (TREE_TYPE (cat_decl),
+ cat_name_expr, class_name_expr,
+ inst_methods, class_methods,
+ protocol_decl, V1_Property_decl,
+ loc);
+
+ finish_var_decl (cat_decl, initlist);
+ impent->class_decl = cat_decl;
+}
+
+/* This routine builds the class extension used by v1 NeXT.
+*/
+
+static tree
+generate_objc_class_ext (tree property_list, tree context)
+{
+ tree decl, expr, ltyp;
+ tree weak_ivar_layout_tree;
+ int size;
+ location_t loc;
+ VEC(constructor_elt,gc) *v = NULL;
+ char buf[BUFSIZE];
+
+ /* TODO: pass the loc in or find it from args. */
+ loc = UNKNOWN_LOCATION;
+
+ /* const char *weak_ivar_layout
+ TODO: Figure the ivar layouts out... */
+ weak_ivar_layout_tree = NULL_TREE;
+
+ if (!property_list && !weak_ivar_layout_tree)
+ return NULL_TREE;
+
+ if (!objc_class_ext_template)
+ build_objc_class_ext_template ();
+
+ /* uint32_t size */
+ size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
+
+ ltyp = const_string_type_node;
+ if (weak_ivar_layout_tree)
+ expr = convert (ltyp, weak_ivar_layout_tree);
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* struct _prop_list_t *properties; */
+ ltyp = objc_prop_list_ptr;
+ if (property_list)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ snprintf (buf, BUFSIZE, "_OBJC_ClassExt_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (context)));
+ decl = start_var_decl (objc_class_ext_template, buf);
+ expr = objc_build_constructor (TREE_TYPE (decl), v);
+ OBJCMETA (decl, objc_meta, meta_class_extension);
+ finish_var_decl (decl, expr);
+ return decl;
+}
+
+/* struct _objc_class {
+ struct objc_class *isa;
+ struct objc_class *super_class;
+ char *name;
+ long version;
+ long info;
+ long instance_size;
+ struct objc_ivar_list *ivars;
+ struct objc_method_list *methods;
+ struct objc_cache *cache;
+ struct objc_protocol_list *protocols;
+ #if ABI >= 1
+ const char *ivar_layout;
+ struct _objc_class_ext *ext;
+ #else
+ void *sel_id;
+ void *gc_object_type;
+ #endif
+ }; */
+
+static tree
+build_v1_shared_structure_initializer (tree type, tree isa, tree super,
+ tree name, tree size, int status,
+ tree dispatch_table, tree ivar_list,
+ tree protocol_list, tree class_ext)
+{
+ tree expr, ltyp;
+ location_t loc;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* TODO: fish the location out of the input data. */
+ loc = UNKNOWN_LOCATION;
+
+ /* isa = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
+
+ /* super_class = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
+
+ /* name = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
+
+ /* version = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (long_integer_type_node, 0));
+
+ /* info = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (long_integer_type_node, status));
+
+ /* instance_size = */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ convert (long_integer_type_node, size));
+
+ /* objc_ivar_list = */
+ ltyp = objc_ivar_list_ptr;
+ if (ivar_list)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivar_list, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* objc_method_list = */
+ ltyp = objc_method_list_ptr;
+ if (dispatch_table)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, dispatch_table, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ 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));
+
+ /* protocol_list = */
+ ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
+ if (protocol_list)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ if (flag_objc_abi >= 1)
+ {
+ /* TODO: figure out the ivar_layout stuff. */
+ expr = convert (const_string_type_node, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ if (!objc_class_ext_template)
+ build_objc_class_ext_template ();
+ ltyp = build_pointer_type (objc_class_ext_template);
+ if (class_ext)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_ext, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+ else
+ {
+ /* sel_id = NULL */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
+
+ /* gc_object_type = NULL */
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
+ }
+ return objc_build_constructor (type, v);
+}
+
+static tree
+generate_ivars_list (tree chain, const char *name, tree attr)
+{
+ tree initlist, ivar_list_template, decl;
+ int size;
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ if (!chain)
+ return NULL_TREE;
+
+ if (!objc_ivar_template)
+ objc_ivar_template = build_ivar_template ();
+
+ size = ivar_list_length (chain);
+
+ generating_instance_variables = 1;
+ ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
+ initlist = build_ivar_list_initializer (objc_ivar_template, chain);
+ generating_instance_variables = 0;
+
+ decl = start_var_decl (ivar_list_template, name);
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
+
+ OBJCMETA (decl, objc_meta, attr);
+ finish_var_decl (decl,
+ objc_build_constructor (TREE_TYPE (decl), inits));
+
+ return decl;
+}
+
+/* static struct objc_class _OBJC_METACLASS_Foo={ ... };
+ static struct objc_class _OBJC_CLASS_Foo={ ... }; */
+
+static void
+generate_v1_class_structs (struct imp_entry *impent)
+{
+ tree name_expr, super_expr, root_expr, class_decl, meta_decl;
+ tree my_root_id, my_super_id;
+ tree cast_type, initlist, protocol_decl;
+ tree class_ext_decl = NULL_TREE, props = NULL_TREE;
+ tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
+ tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
+ int cls_flags;
+ location_t loc;
+ char buf[BUFSIZE];
+
+/* objc_implementation_context = impent->imp_context;
+ implementation_template = impent->imp_template;*/
+ class_decl = impent->class_decl;
+ meta_decl = impent->meta_decl;
+ cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ;
+
+ loc = DECL_SOURCE_LOCATION (impent->class_decl);
+
+ if (flag_objc_abi >= 1)
+ {
+ /* ABI=1 additions. */
+ props = generate_v1_property_table (NULL_TREE, impent->imp_context);
+ class_ext_decl = generate_objc_class_ext (props, impent->imp_context);
+ }
+
+ my_super_id = CLASS_SUPER_NAME (impent->imp_template);
+ if (my_super_id)
+ {
+ add_class_reference (my_super_id);
+
+ /* Compute "my_root_id" - this is required for code generation.
+ the "isa" for all meta class structures points to the root of
+ the inheritance hierarchy (e.g. "__Object")... */
+ my_root_id = my_super_id;
+ do
+ {
+ tree my_root_int = lookup_interface (my_root_id);
+
+ if (my_root_int && CLASS_SUPER_NAME (my_root_int))
+ my_root_id = CLASS_SUPER_NAME (my_root_int);
+ else
+ break;
+ }
+ while (1);
+ super_expr = add_objc_string (my_super_id, class_names);
+ }
+ else
+ {
+ /* No super class. */
+ my_root_id = CLASS_NAME (impent->imp_template);
+ super_expr = null_pointer_node;
+ }
+
+ /* Install class `isa' and `super' pointers at runtime. */
+ cast_type = build_pointer_type (objc_class_template);
+ super_expr = build_c_cast (loc, cast_type, super_expr);
+
+ root_expr = add_objc_string (my_root_id, class_names);
+ root_expr = build_c_cast (loc, cast_type, root_expr);
+
+ if (CLASS_PROTOCOL_LIST (impent->imp_template))
+ {
+ generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
+ protocol_decl = generate_v1_protocol_list (impent->imp_template,
+ impent->imp_context);
+ }
+ else
+ protocol_decl = NULL_TREE;
+
+ if (CLASS_CLS_METHODS (impent->imp_context))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
+ buf, meta_clac_meth);
+ }
+
+ if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
+ && (chain = TYPE_FIELDS (objc_class_template)))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ class_ivars = generate_ivars_list (chain, buf, meta_clac_vars);
+ }
+ /* TODO: get rid of hidden passing of stuff in globals. */
+ /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists(). */
+
+ name_expr = add_objc_string (CLASS_NAME (impent->imp_template), class_names);
+
+ /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
+
+ initlist = build_v1_shared_structure_initializer
+ (TREE_TYPE (meta_decl),
+ root_expr, super_expr, name_expr,
+ convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
+ CLS_META, class_methods, class_ivars,
+ protocol_decl, NULL_TREE);
+
+ finish_var_decl (meta_decl, initlist);
+ impent->meta_decl = meta_decl;
+
+ /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
+ if (CLASS_NST_METHODS (impent->imp_context))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
+ buf, meta_clai_meth);
+ }
+
+ if ((chain = CLASS_IVARS (impent->imp_template)))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ inst_ivars = generate_ivars_list (chain, buf, meta_clai_vars);
+ }
+
+ initlist = build_v1_shared_structure_initializer
+ (TREE_TYPE (class_decl),
+ build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
+ super_expr, name_expr,
+ convert (integer_type_node,
+ TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent->imp_template))),
+ CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
+ protocol_decl, class_ext_decl);
+
+ finish_var_decl (class_decl, initlist);
+ impent->class_decl = class_decl;
+}
+
+/* --- Output NeXT V1 Metadata --- */
+
+/* Create the initial value for the `defs' field of _objc_symtab.
+ This is a CONSTRUCTOR. */
+
+static tree
+init_def_list (tree type)
+{
+ tree expr;
+ location_t loc;
+ struct imp_entry *impent;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ if (imp_count)
+ for (impent = imp_list; impent; impent = impent->next)
+ {
+ if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
+ {
+ loc = DECL_SOURCE_LOCATION (impent->class_decl);
+ expr = build_unary_op (loc,
+ ADDR_EXPR, impent->class_decl, 0);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+ }
+
+ if (cat_count)
+ for (impent = imp_list; impent; impent = impent->next)
+ {
+ if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
+ {
+ loc = DECL_SOURCE_LOCATION (impent->class_decl);
+ expr = build_unary_op (loc,
+ ADDR_EXPR, impent->class_decl, 0);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+ }
+ }
+
+ return objc_build_constructor (type, v);
+}
+
+/* Take care of defining and initializing _OBJC_SYMBOLS. */
+
+/* Predefine the following data type:
+
+ struct _objc_symtab
+ {
+ long sel_ref_cnt;
+ SEL *refs;
+ short cls_def_cnt;
+ short cat_def_cnt;
+ void *defs[cls_def_cnt + cat_def_cnt];
+ }; */
+
+static void
+build_objc_symtab_template (void)
+{
+ tree fields, *chain = NULL;
+
+ objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
+
+ /* long sel_ref_cnt; */
+ fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
+
+ /* SEL *refs; */
+ add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
+
+ /* short cls_def_cnt; */
+ add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
+
+ /* short cat_def_cnt; */
+ add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
+
+ if (imp_count || cat_count)
+ {
+ /* void *defs[imp_count + cat_count (+ 1)]; */
+ /* NB: The index is one less than the size of the array. */
+ int index = imp_count + cat_count;
+ tree array_type = build_sized_array_type (ptr_type_node, index);
+ add_field_decl (array_type, "defs", &chain);
+ }
+
+ objc_finish_struct (objc_symtab_template, fields);
+}
+/* Construct the initial value for all of _objc_symtab. */
+
+static tree
+init_objc_symtab (tree type)
+{
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* sel_ref_cnt = { ..., 5, ... } */
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (long_integer_type_node, 0));
+
+ /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ convert (build_pointer_type (objc_selector_type),
+ integer_zero_node));
+
+ /* cls_def_cnt = { ..., 5, ... } */
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (short_integer_type_node, imp_count));
+
+ /* cat_def_cnt = { ..., 5, ... } */
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (short_integer_type_node, cat_count));
+
+ /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
+
+ if (imp_count || cat_count)
+ {
+ tree field = TYPE_FIELDS (type);
+ field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
+ }
+
+ return objc_build_constructor (type, v);
+}
+
+/* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
+ and initialized appropriately. */
+
+static void
+generate_objc_symtab_decl (void)
+{
+ build_objc_symtab_template ();
+ UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_Symbols");
+ /* Allow the runtime to mark meta-data such that it can be assigned to target
+ specific sections by the back-end. */
+ OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_symtab);
+ finish_var_decl (UOBJC_SYMBOLS_decl,
+ init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
+}
+
+
+static void
+handle_next_class_ref (tree chain)
+{
+ const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
+ char *string = (char *) alloca (strlen (name) + 30);
+
+ sprintf (string, ".objc_class_name_%s", name);
+
+#ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
+ ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
+#else
+ return ; /* NULL build for targets other than Darwin. */
+#endif
+}
+
+static void
+handle_next_impent (struct imp_entry *impent)
+{
+ char buf[BUFSIZE];
+
+ switch (TREE_CODE (impent->imp_context))
+ {
+ case CLASS_IMPLEMENTATION_TYPE:
+ snprintf (buf, BUFSIZE, ".objc_class_name_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ break;
+ case CATEGORY_IMPLEMENTATION_TYPE:
+ snprintf (buf, BUFSIZE, "*.objc_category_name_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
+ break;
+ default:
+ return;
+ }
+
+#ifdef ASM_DECLARE_CLASS_REFERENCE
+ ASM_DECLARE_CLASS_REFERENCE (asm_out_file, buf);
+#else
+ return ; /* NULL build for targets other than Darwin. */
+#endif
+}
+
+static void
+generate_classref_translation_entry (tree chain)
+{
+ tree expr, decl, type;
+
+ decl = TREE_PURPOSE (chain);
+ type = TREE_TYPE (decl);
+
+ expr = add_objc_string (TREE_VALUE (chain), class_names);
+ expr = convert (type, expr); /* cast! */
+
+ /* This is a class reference. It is re-written by the runtime,
+ but will be optimized away unless we force it. */
+ DECL_PRESERVE_P (decl) = 1;
+ OBJCMETA (decl, objc_meta, meta_class_reference);
+ finish_var_decl (decl, expr);
+ return;
+}
+
+
+/* The Fix-and-Continue functionality available in Mac OS X 10.3 and
+ later requires that ObjC translation units participating in F&C be
+ specially marked. The following routine accomplishes this. */
+
+/* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
+
+static void
+generate_objc_image_info (void)
+{
+ tree decl;
+ int flags
+ = ((flag_replace_objc_classes && imp_count ? 1 : 0)
+ | (flag_objc_gc ? 2 : 0));
+ VEC(constructor_elt,gc) *v = NULL;
+ tree array_type;
+
+ array_type = build_sized_array_type (integer_type_node, 2);
+
+ decl = start_var_decl (array_type, "_OBJC_ImageInfo");
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags));
+ /* The runtime wants this and refers to it in a manner hidden from the compiler.
+ So we must force the output. */
+ DECL_PRESERVE_P (decl) = 1;
+ OBJCMETA (decl, objc_meta, meta_info);
+ finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v));
+}
+
+static void
+objc_generate_v1_next_metadata (void)
+{
+ struct imp_entry *impent;
+ tree chain, attr;
+ long vers;
+
+ if (objc_static_instances)
+ gcc_unreachable (); /* Not for NeXT */
+
+ build_metadata_templates ();
+ objc_implementation_context =
+ implementation_template =
+ UOBJC_CLASS_decl =
+ UOBJC_METACLASS_decl = NULL_TREE;
+
+ for (impent = imp_list; impent; impent = impent->next)
+ {
+
+ /* If -gen-decls is present, Dump the @interface of each class.
+ TODO: Dump the classes in the order they were found, rather than in
+ reverse order as we are doing now. */
+ if (flag_gen_declaration)
+ dump_interface (gen_declaration_file, impent->imp_context);
+
+ /* all of the following reference the string pool... */
+ if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
+ generate_v1_class_structs (impent);
+ else
+ generate_v1_category (impent);
+ }
+
+ /* If we are using an array of selectors, we must always
+ finish up the array decl even if no selectors were used. */
+ build_next_selector_translation_table ();
+
+ if (protocol_chain)
+ generate_v1_protocols ();
+
+ /* Pass summary information to the runtime. */
+ if (imp_count || cat_count)
+ generate_objc_symtab_decl ();
+
+ vers = OBJC_VERSION;
+ attr = build_tree_list (objc_meta, meta_modules);
+ build_module_descriptor (vers, attr);
+
+ /* This conveys information on GC usage and zero-link. */
+ generate_objc_image_info ();
+
+ /* Dump the class references. This forces the appropriate classes
+ to be linked into the executable image, preserving unix archive
+ semantics. This can be removed when we move to a more dynamically
+ linked environment. */
+
+ for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
+ {
+ handle_next_class_ref (chain);
+ if (TREE_PURPOSE (chain))
+ generate_classref_translation_entry (chain);
+ }
+
+ for (impent = imp_list; impent; impent = impent->next)
+ handle_next_impent (impent);
+
+ /* Emit the strings tables. */
+ generate_strings ();
+}
+
+/* --- exceptions stuff --- */
+
+/* Predefine the following data type:
+
+ struct _objc_exception_data
+ {
+ int buf[OBJC_JBLEN];
+ void *pointers[4];
+ }; */
+
+/* The following yuckiness should prevent users from having to #include
+ <setjmp.h> in their code... */
+
+/* Define to a harmless positive value so the below code doesn't die. */
+#ifndef OBJC_JBLEN
+#define OBJC_JBLEN 18
+#endif
+
+static void
+build_next_objc_exception_stuff (void)
+{
+ tree decls, temp_type, *chain = NULL;
+
+ objc_exception_data_template
+ = objc_start_struct (get_identifier (UTAG_EXCDATA));
+
+ /* int buf[OBJC_JBLEN]; */
+
+ temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
+ decls = add_field_decl (temp_type, "buf", &chain);
+
+ /* void *pointers[4]; */
+
+ temp_type = build_sized_array_type (ptr_type_node, 4);
+ add_field_decl (temp_type, "pointers", &chain);
+
+ objc_finish_struct (objc_exception_data_template, decls);
+
+ /* int _setjmp(...); */
+ /* If the user includes <setjmp.h>, this shall be superseded by
+ 'int _setjmp(jmp_buf);' */
+ temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
+ objc_setjmp_decl
+ = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+
+ /* id objc_exception_extract(struct _objc_exception_data *); */
+ temp_type
+ = build_function_type_list (objc_object_type,
+ build_pointer_type (objc_exception_data_template),
+ NULL_TREE);
+ objc_exception_extract_decl
+ = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
+ NULL_TREE);
+ /* void objc_exception_try_enter(struct _objc_exception_data *); */
+ /* void objc_exception_try_exit(struct _objc_exception_data *); */
+ temp_type
+ = build_function_type_list (void_type_node,
+ build_pointer_type (objc_exception_data_template),
+ NULL_TREE);
+ objc_exception_try_enter_decl
+ = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
+ NULL_TREE);
+ objc_exception_try_exit_decl
+ = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
+ NULL_TREE);
+
+ /* int objc_exception_match(id, id); */
+ temp_type
+ = build_function_type_list (integer_type_node,
+ objc_object_type, objc_object_type, NULL_TREE);
+ objc_exception_match_decl
+ = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
+ NULL_TREE);
+
+ /* id objc_assign_ivar (id, id, unsigned int); */
+ /* id objc_assign_ivar_Fast (id, id, unsigned int)
+ __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
+ temp_type
+ = build_function_type_list (objc_object_type,
+ objc_object_type,
+ objc_object_type,
+ unsigned_type_node,
+ NULL_TREE);
+ objc_assign_ivar_decl
+ = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+#ifdef OFFS_ASSIGNIVAR_FAST
+ objc_assign_ivar_fast_decl
+ = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
+ NOT_BUILT_IN, NULL, NULL_TREE);
+ DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
+ = tree_cons (get_identifier ("hard_coded_address"),
+ build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
+ NULL_TREE);
+#else
+ /* Default to slower ivar method. */
+ objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
+#endif
+
+ /* id objc_assign_global (id, id *); */
+ /* id objc_assign_strongCast (id, id *); */
+ temp_type = build_function_type_list (objc_object_type,
+ objc_object_type,
+ build_pointer_type (objc_object_type),
+ NULL_TREE);
+ objc_assign_global_decl
+ = add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
+ NULL_TREE);
+ objc_assign_strong_cast_decl
+ = add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
+ NULL_TREE);
+}
+
+/* --- NeXT V1 SJLJ Exceptions --- */
+
+/* Build "objc_exception_try_exit(&_stack)". */
+
+static tree
+next_sjlj_build_try_exit (struct objc_try_context **ctcp)
+{
+ tree t;
+ t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
+ t = tree_cons (NULL, t, NULL);
+ t = build_function_call (input_location,
+ objc_exception_try_exit_decl, t);
+ return t;
+}
+
+/* Build
+ objc_exception_try_enter (&_stack);
+ if (_setjmp(&_stack.buf))
+ ;
+ else
+ ;
+ Return the COND_EXPR. Note that the THEN and ELSE fields are left
+ empty, ready for the caller to fill them in. */
+
+static tree
+next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp)
+{
+ tree t, enter, sj, cond;
+
+ t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
+ t = tree_cons (NULL, t, NULL);
+ enter = build_function_call (input_location,
+ objc_exception_try_enter_decl, t);
+
+ t = objc_build_component_ref ((*ctcp)->stack_decl,
+ get_identifier ("buf"));
+ t = build_fold_addr_expr_loc (input_location, t);
+#ifdef OBJCPLUS
+ /* Convert _setjmp argument to type that is expected. */
+ if (prototype_p (TREE_TYPE (objc_setjmp_decl)))
+ t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
+ else
+ t = convert (ptr_type_node, t);
+#else
+ t = convert (ptr_type_node, t);
+#endif
+ t = tree_cons (NULL, t, NULL);
+ sj = build_function_call (input_location,
+ objc_setjmp_decl, t);
+
+ cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
+ cond = c_common_truthvalue_conversion (input_location, cond);
+
+ return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
+}
+
+/* Build:
+
+ DECL = objc_exception_extract(&_stack); */
+
+static tree
+next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl)
+{
+ tree t;
+
+ t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
+ t = tree_cons (NULL, t, NULL);
+ t = build_function_call (input_location,
+ objc_exception_extract_decl, t);
+ t = convert (TREE_TYPE (decl), t);
+ t = build2 (MODIFY_EXPR, void_type_node, decl, t);
+
+ return t;
+}
+
+/* Build
+ if (objc_exception_match(obj_get_class(TYPE), _caught)
+ BODY
+ else if (...)
+ ...
+ else
+ {
+ _rethrow = _caught;
+ objc_exception_try_exit(&_stack);
+ }
+ from the sequence of CATCH_EXPRs in the current try context. */
+
+static tree
+next_sjlj_build_catch_list (struct objc_try_context **ctcp)
+{
+ tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list);
+ tree catch_seq, t;
+ tree *last = &catch_seq;
+ bool saw_id = false;
+
+ for (; !tsi_end_p (i); tsi_next (&i))
+ {
+ tree stmt = tsi_stmt (i);
+ tree type = CATCH_TYPES (stmt);
+ tree body = CATCH_BODY (stmt);
+
+ if (type != error_mark_node
+ && objc_is_object_id (TREE_TYPE (type)))
+ {
+ *last = body;
+ saw_id = true;
+ break;
+ }
+ else
+ {
+ tree args, cond;
+
+ if (type == error_mark_node)
+ cond = error_mark_node;
+ else
+ {
+ args = tree_cons (NULL, (*ctcp)->caught_decl, NULL);
+ t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
+ args = tree_cons (NULL, t, args);
+ t = build_function_call (input_location,
+ objc_exception_match_decl, args);
+ cond = c_common_truthvalue_conversion (input_location, t);
+ }
+ t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
+ SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
+
+ *last = t;
+ last = &COND_EXPR_ELSE (t);
+ }
+ }
+
+ if (!saw_id)
+ {
+ t = build2 (MODIFY_EXPR, void_type_node, (*ctcp)->rethrow_decl,
+ (*ctcp)->caught_decl);
+ SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
+ append_to_statement_list (t, last);
+
+ t = next_sjlj_build_try_exit (ctcp);
+ SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
+ append_to_statement_list (t, last);
+ }
+
+ return catch_seq;
+}
+
+/* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
+ exception handling. We aim to build:
+
+ {
+ struct _objc_exception_data _stack;
+ id _rethrow = 0;
+ try
+ {
+ objc_exception_try_enter (&_stack);
+ if (_setjmp(&_stack.buf))
+ {
+ id _caught = objc_exception_extract(&_stack);
+ objc_exception_try_enter (&_stack);
+ if (_setjmp(&_stack.buf))
+ _rethrow = objc_exception_extract(&_stack);
+ else
+ CATCH-LIST
+ }
+ else
+ TRY-BLOCK
+ }
+ finally
+ {
+ if (!_rethrow)
+ objc_exception_try_exit(&_stack);
+ FINALLY-BLOCK
+ if (_rethrow)
+ objc_exception_throw(_rethrow);
+ }
+ }
+
+ If CATCH-LIST is empty, we can omit all of the block containing
+ "_caught" except for the setting of _rethrow. Note the use of
+ a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
+ but handles goto and other exits from the block. */
+
+static tree
+next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp)
+{
+ tree rethrow_decl, stack_decl, t;
+ tree catch_seq, try_fin, bind;
+ struct objc_try_context *cur_try_context = *ctcp;
+
+ /* Create the declarations involved. */
+ t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
+ stack_decl = objc_create_temporary_var (t, NULL);
+ cur_try_context->stack_decl = stack_decl;
+
+ rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
+ cur_try_context->rethrow_decl = rethrow_decl;
+ TREE_CHAIN (rethrow_decl) = stack_decl;
+
+ /* Build the outermost variable binding level. */
+ bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
+ SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
+ TREE_SIDE_EFFECTS (bind) = 1;
+
+ /* Initialize rethrow_decl. */
+ t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
+ convert (objc_object_type, null_pointer_node));
+ SET_EXPR_LOCATION (t, cur_try_context->try_locus);
+ append_to_statement_list (t, &BIND_EXPR_BODY (bind));
+
+ /* Build the outermost TRY_FINALLY_EXPR. */
+ try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
+ SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
+ TREE_SIDE_EFFECTS (try_fin) = 1;
+ append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
+
+ /* Create the complete catch sequence. */
+ if (cur_try_context->catch_list)
+ {
+ tree caught_decl = objc_build_exc_ptr (ctcp);
+ catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
+ TREE_SIDE_EFFECTS (catch_seq) = 1;
+
+ t = next_sjlj_build_exc_extract (ctcp, caught_decl);
+ append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
+
+ t = next_sjlj_build_enter_and_setjmp (ctcp);
+ COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
+ COND_EXPR_ELSE (t) = next_sjlj_build_catch_list (ctcp);
+ append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
+ }
+ else
+ catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
+ SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
+
+ /* Build the main register-and-try if statement. */
+ t = next_sjlj_build_enter_and_setjmp (ctcp);
+ SET_EXPR_LOCATION (t, cur_try_context->try_locus);
+ COND_EXPR_THEN (t) = catch_seq;
+ COND_EXPR_ELSE (t) = cur_try_context->try_body;
+ TREE_OPERAND (try_fin, 0) = t;
+
+ /* Build the complete FINALLY statement list. */
+ t = next_sjlj_build_try_exit (ctcp);
+ t = build_stmt (input_location, COND_EXPR,
+ c_common_truthvalue_conversion
+ (input_location, rethrow_decl),
+ NULL, t);
+ SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
+ append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
+
+ append_to_statement_list (cur_try_context->finally_body,
+ &TREE_OPERAND (try_fin, 1));
+
+ t = tree_cons (NULL, rethrow_decl, NULL);
+ t = build_function_call (input_location,
+ objc_exception_throw_decl, t);
+ t = build_stmt (input_location, COND_EXPR,
+ c_common_truthvalue_conversion (input_location,
+ rethrow_decl),
+ t, NULL);
+ SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
+ append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
+
+ return bind;
+}
+
+/* We do not expect this to be used at the moment.
+ If (a) it is possible to implement unwinder exceptions.
+ (b) we do it... then it might be possibly useful.
+*/
+static GTY(()) tree objc_eh_personality_decl;
+
+static tree
+objc_eh_runtime_type (tree type)
+{
+ tree ident, eh_id, decl, str;
+
+ gcc_unreachable ();
+ if (type == error_mark_node)
+ {
+ /* Use 'ErrorMarkNode' as class name when error_mark_node is found
+ to prevent an ICE. Note that we know that the compiler will
+ terminate with an error and this 'ErrorMarkNode' class name will
+ never be actually used. */
+ ident = get_identifier ("ErrorMarkNode");
+ goto make_err_class;
+ }
+
+ if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
+ {
+ ident = get_identifier ("id");
+ goto make_err_class;
+ }
+
+ if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
+ {
+#ifdef OBJCPLUS
+ /* This routine is also called for c++'s catch clause; in which case,
+ we use c++'s typeinfo decl. */
+ return build_eh_type_type (type);
+#else
+ error ("non-objective-c type '%T' cannot be caught", type);
+ ident = get_identifier ("ErrorMarkNode");
+ goto make_err_class;
+#endif
+ }
+ else
+ ident = OBJC_TYPE_NAME (TREE_TYPE (type));
+
+make_err_class:
+ /* If this class was already referenced, then it will be output during
+ meta-data emission, so we don't need to do it here. */
+ decl = get_objc_string_decl (ident, class_names);
+ eh_id = add_objc_string (ident, class_names);
+ if (!decl)
+ {
+ /* Not found ... so we need to build it - from the freshly-entered id. */
+ decl = get_objc_string_decl (ident, class_names);
+ str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
+ IDENTIFIER_POINTER (ident));
+ /* We have to finalize this var here, because this might be called after
+ all the other metadata strings have been emitted. */
+ finish_var_decl (decl, str);
+ }
+ return eh_id;
+}
+
+static tree
+objc_eh_personality (void)
+{
+ if (!objc_eh_personality_decl)
+#ifndef OBJCPLUS
+ objc_eh_personality_decl = build_personality_function ("objc");
+#else
+ objc_eh_personality_decl = build_personality_function ("gxx");
+#endif
+ return objc_eh_personality_decl;
+}
+
+/* --- interfaces --- */
+
+static tree
+build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
+{
+ tree t;
+ VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
+ /* A throw is just a call to the runtime throw function with the
+ object as a parameter. */
+ VEC_quick_push (tree, parms, throw_expr);
+ t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
+ VEC_free (tree, gc, parms);
+ return add_stmt (t);
+}
+
+/* Build __builtin_eh_pointer, or the moral equivalent. In the case
+ of Darwin, we'll arrange for it to be initialized (and associated
+ with a binding) later. */
+
+static tree
+objc_build_exc_ptr (struct objc_try_context **cur_try_context)
+{
+ if (flag_objc_sjlj_exceptions)
+ {
+ tree var = (*cur_try_context)->caught_decl;
+ if (!var)
+ {
+ var = objc_create_temporary_var (objc_object_type, NULL);
+ (*cur_try_context)->caught_decl = var;
+ }
+ return var;
+ }
+ else
+ {
+ tree t;
+ t = built_in_decls[BUILT_IN_EH_POINTER];
+ t = build_call_expr (t, 1, integer_zero_node);
+ return fold_convert (objc_object_type, t);
+ }
+}
+
+static tree
+begin_catch (struct objc_try_context **cur_try_context, tree type,
+ tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
+{
+ tree t;
+ /* Record the data for the catch in the try context so that we can
+ finalize it later. We treat ellipsis the same way as catching
+ with 'id xyz'. */
+ t = build_stmt (input_location, CATCH_EXPR, type, compound);
+ (*cur_try_context)->current_catch = t;
+
+ /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
+ t = objc_build_exc_ptr (cur_try_context);
+ t = convert (TREE_TYPE (decl), t);
+ return build2 (MODIFY_EXPR, void_type_node, decl, t);
+}
+
+static void
+finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
+{
+ append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
+}
+
+static tree
+finish_try_stmt (struct objc_try_context **cur_try_context)
+{
+ tree stmt;
+ struct objc_try_context *c = *cur_try_context;
+ /* If we're doing Darwin setjmp exceptions, build the big nasty. */
+ if (flag_objc_sjlj_exceptions)
+ {
+ bool save = in_late_binary_op;
+ in_late_binary_op = true;
+ if (!c->finally_body)
+ {
+ c->finally_locus = input_location;
+ c->end_finally_locus = input_location;
+ }
+ stmt = next_sjlj_build_try_catch_finally (cur_try_context);
+ in_late_binary_op = save;
+ }
+ else
+ /* This doesn't happen at the moment... but maybe one day... */
+ {
+ /* Otherwise, nest the CATCH inside a FINALLY. */
+ stmt = c->try_body;
+ if (c->catch_list)
+ stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
+ if (c->finally_body)
+ stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
+ }
+ return stmt;
+}
+
+#include "gt-objc-objc-next-runtime-abi-01.h"
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
new file mode 100644
index 0000000..46e5693
--- /dev/null
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -0,0 +1,3750 @@
+/* Next Runtime (ABI-2) private.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ Contributed by Iain Sandoe and based, in part, on an implementation in
+ 'branches/apple/trunk' contributed by Apple Computer Inc.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
+
+ This version is intended to match (logically) output of Apple's 4.2.1
+ compiler.
+
+ References:
+ FSF GCC branches/apple/trunk.
+ objc4-371.2 Open Source release (Apple Computer). (objc-runtime-new.h)
+ gcc_42-5664 Apple Local modifications to GCC (Apple Computer).
+*/
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+
+#ifdef OBJCPLUS
+#include "cp-tree.h"
+#else
+#include "c-tree.h"
+#include "c-lang.h"
+#endif
+#include "langhooks.h"
+#include "c-family/c-objc.h"
+#include "objc-act.h"
+
+/* When building Objective-C++, we are not linking against the C front-end
+ and so need to replicate the C tree-construction functions in some way. */
+#ifdef OBJCPLUS
+#define OBJCP_REMAP_FUNCTIONS
+#include "objcp-decl.h"
+#endif /* OBJCPLUS */
+
+#include "ggc.h"
+#include "target.h"
+#include "obstack.h"
+#include "tree-iterator.h"
+
+/* These are only used for encoding ivars. */
+extern struct obstack util_obstack;
+extern char *util_firstobj;
+
+#include "objc-runtime-hooks.h"
+
+#include "objc-runtime-shared-support.h"
+
+/* ABI 2 Private definitions. */
+#define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
+
+#define TAG_GETCLASS "objc_getClass"
+#define TAG_GETMETACLASS "objc_getMetaClass"
+
+#define TAG_MSGSEND "objc_msgSend"
+#define TAG_MSGSENDSUPER "objc_msgSendSuper"
+#define TAG_MSGSEND_STRET "objc_msgSend_stret"
+#define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
+
+#define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
+#define TAG_V2_EH_TYPE "objc_ehtype_t"
+
+#define UTAG_V2_CLASS "_class_t"
+#define UTAG_V2_CLASS_RO "_class_ro_t"
+#define UTAG_V2_PROTOCOL "_protocol_t"
+#define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
+
+#define UTAG_V2_EH_TYPE "_objc_ehtype_t"
+
+#define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
+
+enum objc_v2_tree_index
+{
+ /* Templates. */
+ OCTI_V2_CLS_TEMPL,
+ OCTI_V2_CAT_TEMPL,
+ OCTI_V2_CLS_RO_TEMPL,
+ OCTI_V2_PROTO_TEMPL,
+ OCTI_V2_IVAR_TEMPL,
+ OCTI_V2_IVAR_LIST_TEMPL,
+ OCTI_V2_MESSAGE_REF_TEMPL,
+ OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
+
+ OCTI_V2_MESSAGE_SELECTOR_TYPE,
+ OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
+ OCTI_V2_IMP_TYPE,
+ OCTI_V2_SUPER_IMP_TYPE,
+
+ OCTI_V2_CACHE_DECL,
+ OCTI_V2_VTABLE_DECL,
+
+ OCTI_V2_PROPERTY_TEMPL,
+
+ /* V2 messaging. */
+ OCTI_V2_UMSG_FIXUP_DECL,
+ OCTI_V2_UMSG_STRET_FIXUP_DECL,
+ OCTI_V2_UMSG_ID_FIXUP_DECL,
+ OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
+ OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
+ OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
+
+ /* Exceptions - related. */
+ OCTI_V2_BEGIN_CATCH_DECL,
+ OCTI_V2_END_CATCH_DECL,
+ OCTI_V2_RETHROW_DECL,
+
+ OCTI_V2_MAX
+};
+
+#define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
+#define objc_v2_class_ro_template \
+ objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
+#define objc_v2_category_template \
+ objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
+#define objc_v2_protocol_template \
+ objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
+
+/* struct message_ref_t */
+#define objc_v2_message_ref_template \
+ objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
+
+#define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
+
+/* struct super_message_ref_t */
+#define objc_v2_super_message_ref_template \
+ objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
+
+/* struct message_ref_t* */
+#define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
+/* struct super_super_message_ref_t */
+#define objc_v2_super_selector_type \
+ objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
+#define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
+#define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
+
+#define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
+#define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
+
+#define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
+#define objc_v2_property_template \
+ objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
+
+/* V2 Messaging */
+
+/* objc_msgSend_fixup_rtp */
+#define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
+/* objc_msgSend_stret_fixup_rtp */
+#define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
+/* objc_msgSendId_fixup_rtp */
+#define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
+/* objc_msgSendId_stret_fixup_rtp */
+#define umsg_id_stret_fixup_decl \
+ objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
+/* objc_msgSendSuper2_fixup_rtp */
+#define umsg_id_super2_fixup_decl \
+ objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
+/* objc_msgSendSuper2_stret_fixup_rtp */
+#define umsg_id_super2_stret_fixup_decl \
+ objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
+
+#define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
+#define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
+#define objc_rethrow_exception_decl \
+ objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
+
+/* rt_trees identifiers - shared between NeXT implementations. These allow
+ the FE to tag meta-data in a manner that survives LTO and can be used when
+ the runtime requires that certain meta-data items appear in particular
+ named sections. */
+
+#include "objc-next-metadata-tags.h"
+extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
+
+/* The OCTI_V2_... enumeration itself is in above. */
+static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
+
+static void next_runtime_02_initialize (void);
+
+static void build_v2_message_ref_templates (void);
+static void build_v2_class_templates (void);
+static void build_v2_super_template (void);
+static void build_v2_category_template (void);
+static void build_v2_protocol_template (void);
+
+static tree next_runtime_abi_02_super_superclassfield_id (void);
+
+static tree next_runtime_abi_02_class_decl (tree);
+static tree next_runtime_abi_02_metaclass_decl (tree);
+static tree next_runtime_abi_02_category_decl (tree);
+static tree next_runtime_abi_02_protocol_decl (tree);
+static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
+
+static tree next_runtime_abi_02_get_class_reference (tree);
+static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
+static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
+static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
+static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
+static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
+
+static tree next_runtime_abi_02_receiver_is_class_object (tree);
+static tree next_runtime_abi_02_get_arg_type_list_base (tree, int, int);
+static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
+ tree, tree, tree, int);
+static bool next_runtime_abi_02_setup_const_string_class_decl (void);
+static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
+
+static tree create_extern_decl (tree, const char *);
+
+static void objc_generate_v2_next_metadata (void);
+static bool objc2_objc_exception_attr (tree);
+
+/* void build_v2_protocol_reference (tree);*/
+static void build_v2_ehtype_template (void);
+static void build_v2_eh_catch_objects (void);
+static tree next_runtime_02_eh_type (tree);
+static tree objc_eh_personality (void);
+static tree build_throw_stmt (location_t, tree, bool);
+static tree objc_build_exc_ptr (struct objc_try_context **);
+static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
+static void finish_catch (struct objc_try_context **, tree);
+static tree finish_try_stmt (struct objc_try_context **);
+
+static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
+
+bool
+objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
+{
+ extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+
+ if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
+ {
+ inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for "
+ "%<-fnext-runtime%> when %<-fobjc-abi-version%> >= 2");
+ flag_objc_sjlj_exceptions = 0;
+ }
+
+ rthooks->initialize = next_runtime_02_initialize;
+ rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
+ rthooks->tag_getclass = TAG_GETCLASS;
+ rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
+
+ rthooks->class_decl = next_runtime_abi_02_class_decl;
+ rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
+ rthooks->category_decl = next_runtime_abi_02_category_decl;
+ rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
+ rthooks->string_decl = next_runtime_abi_02_string_decl;
+
+ rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
+ rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
+ rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
+ rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
+ rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
+ rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
+
+ rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
+ rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
+ rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
+
+ rthooks->setup_const_string_class_decl =
+ next_runtime_abi_02_setup_const_string_class_decl;
+ rthooks->build_const_string_constructor =
+ next_runtime_abi_02_build_const_string_constructor;
+
+ rthooks->build_throw_stmt = build_throw_stmt;
+ rthooks->build_exc_ptr = objc_build_exc_ptr;
+ rthooks->begin_catch = begin_catch;
+ rthooks->finish_catch = finish_catch;
+ rthooks->finish_try_stmt = finish_try_stmt;
+
+ rthooks->generate_metadata = objc_generate_v2_next_metadata;
+ return true;
+}
+
+/* We need a way to convey what kind of meta-data are represented by a given
+ variable, since each type is expected (by the runtime) to be found in a
+ specific named section. The solution must be usable with LTO.
+
+ The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
+ satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
+ identification attributes in the front end. The back-end may choose to act
+ on these as it requires. */
+
+static void
+next_runtime_abi_02_init_metadata_attributes (void)
+{
+ if (!objc_meta)
+ objc_meta = get_identifier ("OBJC2META");
+
+ if (!meta_base)
+ meta_base = get_identifier ("V2_BASE");
+
+ meta_class = get_identifier ("G2_CLAS");
+ meta_metaclass = get_identifier ("G2_META");
+ meta_category =
+ meta_protocol = meta_base;
+
+ meta_clac_vars =
+ meta_clai_vars = meta_base;
+
+ meta_clac_meth =
+ meta_clai_meth =
+ meta_catc_meth =
+ meta_cati_meth =
+ meta_proto_cls_meth =
+ meta_proto_nst_meth = meta_base;
+
+ meta_clas_prot =
+ meta_catg_prot = meta_base;
+
+ meta_sel_refs = get_identifier ("V2_SRFS");
+
+ meta_class_name =
+ meta_meth_name =
+ meta_meth_type =
+ meta_prop_name_attr = get_identifier ("V2_STRG");
+
+ meta_mref = get_identifier ("V2_MREF");
+ meta_class_ref = get_identifier ("V2_CLRF");
+ meta_superclass_ref = get_identifier ("V2_SURF");
+
+ meta_label_classlist = get_identifier ("V2_CLAB");
+ meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
+ meta_label_categorylist = get_identifier ("V2_CALA");
+ meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
+
+ meta_label_protocollist = get_identifier ("V2_PLST");
+ meta_proto_ref = get_identifier ("V2_PRFS");
+
+ meta_info = get_identifier ("V2_INFO");
+
+ meta_ehtype = get_identifier ("V2_EHTY");
+
+ meta_const_str = get_identifier ("V2_CSTR");
+}
+
+static void next_runtime_02_initialize (void)
+{
+ tree type;
+#ifdef OBJCPLUS
+ /* For all objc ABIs -fobjc-call-cxx-cdtors is on by default. */
+ if (!global_options_set.x_flag_objc_call_cxx_cdtors)
+ global_options.x_flag_objc_call_cxx_cdtors = 1;
+#endif
+
+ /* Set up attributes to be attached to the meta-data so that they
+ will be placed in the correct sections. */
+ next_runtime_abi_02_init_metadata_attributes ();
+
+ /* `struct objc_selector *' */
+ objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (TAG_SELECTOR)));
+
+ /* IMP : id (*) (id, _message_ref_t*, ...)
+ SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
+ objc_v2_selector_type. */
+ build_v2_message_ref_templates ();
+
+ objc_v2_ivar_list_ptr =
+ build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier ("_ivar_list_t")));
+
+ objc_prop_list_ptr =
+ build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier ("_prop_list_t")));
+
+ build_v2_class_templates ();
+ build_v2_super_template ();
+ 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,
+ 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,
+ 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,
+ 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,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
+
+ /* id objc_msgSendSuper2_fixup_rtp
+ (struct objc_super *, struct message_ref_t*, ...); */
+ type = build_varargs_function_type_list (objc_object_type,
+ 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,
+ 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);
+ TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
+
+ /* Present in the library, but unused by the FE. */
+ /* Protocol *objc_getProtocol (const char *)
+ type = build_function_type_list (objc_protocol_type,
+ const_string_type_node,
+ NULL_TREE);
+ objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
+
+ UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
+ "_objc_empty_cache");
+
+ UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
+ "_objc_empty_vtable");
+
+ /* id objc_getClass (const char *); */
+ type = build_function_type_list (objc_object_type,
+ const_string_type_node,
+ NULL_TREE);
+ objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ /* id objc_getMetaClass (const char *); */
+ objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+
+ /* This is the type of all of the following functions objc_copyStruct(). */
+ type = build_function_type_list (void_type_node,
+ ptr_type_node,
+ const_ptr_type_node,
+ ptrdiff_type_node,
+ boolean_type_node,
+ boolean_type_node,
+ NULL_TREE);
+ /* Declare the following function:
+ void
+ objc_copyStruct (void *destination, const void *source,
+ ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
+ objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (objc_copyStruct_decl) = 0;
+ objc_getPropertyStruct_decl = NULL_TREE;
+ objc_setPropertyStruct_decl = NULL_TREE;
+
+ gcc_assert (!flag_objc_sjlj_exceptions);
+
+ /* Although we warn that fobjc-exceptions is required for exceptions
+ code, we carry on an create it anyway. */
+
+ /* This can be required, even when exceptions code is not present,
+ when an __attribute__((objc_exception)) is applied to a class. */
+ build_v2_ehtype_template ();
+
+ /* void * objc_begin_catch (void *) */
+ type = build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ OBJC_VOID_AT_END));
+
+ objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (objc2_begin_catch_decl) = 0;
+
+ /* void objc_end_catch () */
+ type = build_function_type (void_type_node, OBJC_VOID_AT_END);
+ objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (objc2_end_catch_decl) = 0;
+
+ /* void objc_exception_rethrow (void) */
+ type = build_function_type (void_type_node, OBJC_VOID_AT_END);
+ objc_rethrow_exception_decl =
+ add_builtin_function ("objc_exception_rethrow",
+ type, 0, NOT_BUILT_IN,
+ NULL, NULL_TREE);
+ TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
+ using_eh_for_cleanups ();
+ lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
+ lang_hooks.eh_personality = objc_eh_personality;
+}
+
+/* NOTE --- templates --- */
+
+/* Set 'objc_v2_message_ref_template' to the data type node for 'struct _message_ref_t'.
+ This needs to be done just once per compilation. Also Set
+ 'objc_v2_super_message_ref_template' to data type node
+ for 'struct _super_message_ref_t'. */
+
+/* struct _message_ref_t {
+ IMP messenger;
+ SEL name;
+ };
+ where IMP is: id (*) (id, _message_ref_t*, ...)
+*/
+
+/* struct _super_message_ref_t {
+ SUPER_IMP messenger;
+ SEL name;
+ };
+ where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
+*/
+
+static void
+build_v2_message_ref_templates (void)
+{
+ tree ptr_message_ref_t;
+ tree decls, *chain = NULL;
+
+ /* struct _message_ref_t {...} */
+ objc_v2_message_ref_template =
+ objc_start_struct (get_identifier ("_message_ref_t"));
+
+ /* IMP messenger; */
+ ptr_message_ref_t =
+ build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier ("_message_ref_t")));
+
+ objc_v2_imp_type =
+ build_pointer_type (build_function_type_list
+ (objc_object_type,
+ objc_object_type,
+ ptr_message_ref_t,
+ NULL_TREE));
+
+ decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
+
+ /* SEL name; */
+ add_field_decl (objc_selector_type, "name", &chain);
+
+ objc_finish_struct (objc_v2_message_ref_template, decls);
+
+ objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
+
+ chain = NULL;
+ /* struct _super_message_ref_t {...} */
+ objc_v2_super_message_ref_template =
+ objc_start_struct (get_identifier ("_super_message_ref_t"));
+
+ /* SUPER_IMP messenger; */
+ ptr_message_ref_t = build_pointer_type
+ (xref_tag (RECORD_TYPE,
+ get_identifier ("_super_message_ref_t")));
+
+ objc_v2_super_imp_type =
+ build_pointer_type (build_function_type_list
+ (objc_object_type,
+ objc_super_type,
+ ptr_message_ref_t,
+ NULL_TREE));
+
+ add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
+
+ /* SEL name; */
+ add_field_decl (objc_selector_type, "name", &chain);
+
+ objc_finish_struct (objc_v2_super_message_ref_template, decls);
+ objc_v2_super_selector_type =
+ build_pointer_type (objc_v2_super_message_ref_template);
+}
+
+/* Build following types which represent each class implementation.
+
+struct class_ro_t {
+ uint32_t const flags;
+ uint32_t const instanceStart;
+ uint32_t const instanceSize;
+#ifdef __LP64__
+ uint32_t const reserved;
+#endif
+ const uint8_t * const ivarLayout;
+ const char *const name;
+ const struct method_list_t * const baseMethods;
+ const struct objc_protocol_list *const baseProtocols;
+ const struct ivar_list_t *const ivars;
+ const uint8_t * const weakIvarLayout;
+ const struct _prop_list_t * const properties;
+};
+
+struct class_t {
+ struct class_t *isa;
+ struct class_t *superclass;
+ void *cache;
+ IMP *vtable;
+
+ ...When this is active - it will point to a rw version, but
+ when we build the meta-data we point it to the ro...
+ struct class_ro_t *data;
+};
+
+*/
+
+static void
+build_v2_class_templates (void)
+{
+ tree cnst_strg_type;
+ tree decls, *chain = NULL;
+
+ /* struct class_ro_t {...} */
+ objc_v2_class_ro_template =
+ objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
+
+ /* uint32_t const flags; */
+ decls = add_field_decl (integer_type_node, "flags", &chain);
+
+ /* uint32_t const instanceStart */
+ add_field_decl (integer_type_node, "instanceStart", &chain);
+
+ /* uint32_t const instanceSize */
+ add_field_decl (integer_type_node, "instanceSize", &chain);
+
+ /* This ABI is currently only used on m64 NeXT, we choose to
+ make the alignment padding explicit. */
+ /* uint32_t const reserved. */
+ add_field_decl (integer_type_node, "reserved", &chain);
+
+ /* const uint8_t * const ivarLayout */
+ cnst_strg_type = build_pointer_type (unsigned_char_type_node);
+ add_field_decl (cnst_strg_type, "ivarLayout", &chain);
+
+ /* const char *const name; */
+ add_field_decl (string_type_node, "name", &chain);
+
+ /* const struct method_list_t * const baseMethods */
+ add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
+
+ /* const struct objc_protocol_list *const baseProtocols */
+ add_field_decl (build_pointer_type
+ (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_V2_PROTOCOL_LIST))),
+ "baseProtocols", &chain);
+
+ /* const struct ivar_list_t *const ivars */
+ add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
+
+ /* const uint8_t * const weakIvarLayout; */
+ add_field_decl (cnst_strg_type, "weakIvarLayout", &chain);
+
+ /* struct _prop_list_t * baseProperties */
+ add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
+
+ objc_finish_struct (objc_v2_class_ro_template, decls);
+
+ chain = NULL;
+ /* struct class_t {...} */
+ objc_v2_class_template =
+ objc_start_struct (get_identifier (UTAG_V2_CLASS));
+
+ /* struct class_t *isa; */
+ decls = add_field_decl (build_pointer_type (objc_v2_class_template),
+ "isa", &chain);
+
+ /* struct class_t * const superclass */
+ add_field_decl (build_pointer_type (objc_v2_class_template),
+ "superclass", &chain);
+
+ /* void *cache; */
+ add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
+
+ /* IMP *vtable; */
+ add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
+
+ /* struct class_ro_t *ro; */
+ add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
+
+ objc_finish_struct (objc_v2_class_template, decls);
+}
+
+/* struct _objc_super {
+ struct _objc_object *self;
+ Class cls;
+ }; */
+
+void
+build_v2_super_template (void)
+{
+ tree decls, *chain = NULL;
+
+ objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
+
+ /* struct _objc_object *self; */
+ decls = add_field_decl (objc_object_type, "self", &chain);
+
+ /* Class cls; */
+ add_field_decl (objc_class_type, "cls", &chain);
+
+ objc_finish_struct (objc_super_template, decls);
+}
+
+/* struct protocol_t {
+ Class isa;
+ const char * const protocol_name;
+ const struct protocol_list_t * const protocol_list;
+ const struct method_list_t * const instance_methods;
+ const struct method_list_t * const class_methods;
+ const struct method_list_t * optionalInstanceMethods;
+ const struct method_list_t * optionalClassMethod
+ const struct _prop_list_t * const properties;
+ const uint32_t size;
+ const uint32_t flags;
+ }
+*/
+static void
+build_v2_protocol_template (void)
+{
+ tree decls, *chain = NULL;
+
+ objc_v2_protocol_template =
+ objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
+
+ /* Class isa; */
+ decls = add_field_decl (objc_object_type, "isa", &chain);
+
+ /* char *protocol_name; */
+ add_field_decl (string_type_node, "protocol_name", &chain);
+
+ /* const struct protocol_list_t * const protocol_list; */
+ add_field_decl (build_pointer_type (objc_v2_protocol_template),
+ "protocol_list", &chain);
+
+ /* const struct method_list_t * const instance_methods; */
+ add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
+
+ /* const struct method_list_t * const class_methods; */
+ add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
+
+ /* const struct method_list_t * optionalInstanceMethods */
+ add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
+
+ /* const struct method_list_t * optionalClassMethods */
+ add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
+
+ /* struct _prop_list_t * properties; */
+ add_field_decl (objc_prop_list_ptr, "properties", &chain);
+
+ /* const uint32_t size; */
+ add_field_decl (integer_type_node, "size", &chain);
+
+ /* const uint32_t flags; */
+ add_field_decl (integer_type_node, "flags", &chain);
+
+ objc_finish_struct (objc_v2_protocol_template, decls);
+}
+
+/* Build type for a category:
+ struct category_t {
+ const char * const name;
+ struct class_t *const cls;
+ const struct method_list_t * const instance_methods;
+ const struct method_list_t * const class_methods;
+ const struct protocol_list_t * const protocols;
+ const struct _prop_list_t * const properties;
+ }
+*/
+
+static void
+build_v2_category_template (void)
+{
+ tree decls, *chain = NULL;
+
+ objc_v2_category_template =
+ objc_start_struct (get_identifier ("_category_t"));
+
+ /* char *name; */
+ decls = add_field_decl (string_type_node, "name", &chain);
+
+ /* struct class_t *const cls; */
+ add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
+
+ /* struct method_list_t *instance_methods; */
+ add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
+
+ /* struct method_list_t *class_methods; */
+ add_field_decl (objc_method_list_ptr, "class_methods", &chain);
+
+ /* struct protocol_list_t *protocol_list; */
+ add_field_decl (build_pointer_type (objc_v2_protocol_template),
+ "protocol_list", &chain );
+
+ /* struct _prop_list_t * properties; */
+ add_field_decl (objc_prop_list_ptr, "properties", &chain);
+
+ objc_finish_struct (objc_v2_category_template, decls);
+}
+
+/* NOTE --- Decls, Identifiers, Names etc. --- */
+
+/* This routine is given a name and returns a matching extern variable if
+ one is found.
+*/
+
+static tree
+hash_name_lookup (hash *hashlist, tree name)
+{
+ hash target;
+
+ target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
+
+ while (target)
+ {
+ if (name == DECL_NAME (target->key))
+ return target->key;
+
+ target = target->next;
+ }
+ return 0;
+}
+
+/* This routine is given an extern variable and enters it in its hash table.
+ Note that hashing is done on its inner IDENTIFIER_NODE node.
+*/
+
+static void
+hash_name_enter (hash *hashlist, tree id)
+{
+ hash obj;
+ int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
+
+ obj = ggc_alloc_hashed_entry ();
+ obj->list = 0;
+ obj->next = hashlist[slot];
+ obj->key = id;
+
+ hashlist[slot] = obj; /* append to front */
+}
+
+/* Create a declaration "extern <type> <name>;"
+ The var will need to be finalized (e.g. by calling finish_var_decl()). */
+
+static tree
+create_extern_decl (tree type, const char *name)
+{
+ tree id = get_identifier (name);
+ tree var = hash_name_lookup (extern_names, id);
+ if (var)
+ return var;
+ /* New name. */
+ var = start_var_decl (type, name);
+ TREE_STATIC (var) = 0;
+ DECL_EXTERNAL (var) = 1;
+ TREE_PUBLIC (var) = 1;
+ hash_name_enter (extern_names, var);
+ return var;
+}
+
+/* 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)
+{
+ tree id = get_identifier (name);
+ tree var = hash_name_lookup (extern_names, id);
+ if (var)
+ {
+ DECL_EXTERNAL (var) = 0;
+ TREE_STATIC (var) = 1;
+ }
+ else
+ {
+ var = start_var_decl (type, name);
+ hash_name_enter (extern_names, var);
+ }
+ 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)
+{
+ tree decl = create_global_decl (type, name);
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ return decl;
+}
+
+/* Irritatingly, we have a different superclass field name for ABI=2. */
+
+static tree
+next_runtime_abi_02_super_superclassfield_id (void)
+{
+ if (!super_superclassfield_id)
+ super_superclassfield_id = get_identifier ("cls");
+ return super_superclassfield_id;
+}
+
+static tree
+next_runtime_abi_02_class_decl (tree klass)
+{
+ tree decl;
+ char buf[BUFSIZE];
+ snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass)));
+ /* ObjC2 classes are extern visible. */
+ decl = create_global_decl (objc_v2_class_template, buf);
+ OBJCMETA (decl, objc_meta, meta_class);
+ return decl;
+}
+
+static tree
+next_runtime_abi_02_metaclass_decl (tree klass)
+{
+ tree decl;
+ char buf[BUFSIZE];
+ snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass)));
+ /* ObjC2 classes are extern visible. */
+ decl = create_global_decl (objc_v2_class_template, buf);
+ OBJCMETA (decl, objc_meta, meta_metaclass);
+ return decl;
+}
+
+static tree
+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)));
+ decl = start_var_decl (objc_v2_category_template, buf);
+ OBJCMETA (decl, objc_meta, meta_category);
+ return decl;
+}
+
+static tree
+next_runtime_abi_02_protocol_decl (tree p)
+{
+ tree decl;
+ char buf[BUFSIZE];
+
+ /* 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);
+ OBJCMETA (decl, objc_meta, meta_protocol);
+ return decl;
+}
+
+static tree
+next_runtime_abi_02_string_decl (tree type, const char *name, string_section where)
+{
+ tree var = start_var_decl (type, name);
+ switch (where)
+ {
+ case class_names:
+ OBJCMETA (var, objc_meta, meta_class_name);
+ break;
+ case meth_var_names:
+ OBJCMETA (var, objc_meta, meta_meth_name);
+ break;
+ case meth_var_types:
+ OBJCMETA (var, objc_meta, meta_meth_type);
+ break;
+ case prop_names_attr:
+ OBJCMETA (var, objc_meta, meta_prop_name_attr);
+ break;
+ default:
+ OBJCMETA (var, objc_meta, meta_base);
+ break;
+ }
+ return var;
+}
+
+/* NOTE --- entry --- */
+
+typedef struct GTY(()) ident_data_tuple {
+ tree ident;
+ tree data;
+} ident_data_tuple ;
+DEF_VEC_O(ident_data_tuple);
+DEF_VEC_ALLOC_O(ident_data_tuple, gc);
+
+/* This routine creates a file scope static variable of type 'Class' to hold
+ the address of a class. */
+
+static tree
+build_v2_class_reference_decl (tree ident)
+{
+ tree decl;
+ char buf[BUFSIZE];
+
+ snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
+ decl = start_var_decl (objc_class_type, buf);
+ OBJCMETA (decl, objc_meta, meta_class_ref);
+ return decl;
+}
+
+/* This routine builds a class refs entry for each class name used.
+ Initially, a (static-ref, IDENT) tuple is added to the list.
+ The ident is replaced with address of the class metadata (of type 'Class')
+ in the output routine. */
+
+static GTY (()) VEC (ident_data_tuple, gc) * classrefs;
+
+static tree
+objc_v2_get_class_reference (tree ident)
+{
+ tree decl;
+ ident_data_tuple e;
+ if (classrefs)
+ {
+ int count;
+ ident_data_tuple *ref;
+ FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
+ {
+ if (ref->ident == ident)
+ {
+ if (!ref->data)
+ ref->data = build_v2_class_reference_decl (ident);
+ return ref->data;
+ }
+ }
+ }
+ else
+ /* Somewhat arbitrary initial provision. */
+ classrefs = VEC_alloc (ident_data_tuple, gc, 16);
+ /* We come here if we don't find the entry - or if the table was yet
+ to be created. */
+ decl = build_v2_class_reference_decl (ident);
+ e.ident = ident;
+ e.data = decl;
+ VEC_safe_push (ident_data_tuple, gc, classrefs, &e);
+ return decl;
+}
+
+static tree
+next_runtime_abi_02_get_class_reference (tree ident)
+{
+ if (!flag_zero_link)
+ return objc_v2_get_class_reference (ident);
+ else
+ {
+ /* We fall back to using objc_getClass (). */
+ VEC(tree,gc) *vec = VEC_alloc (tree, gc, 1);
+ tree t;
+ /* ??? add_class_reference (ident); - is pointless, since the
+ system lib does not export the equivalent symbols. Maybe we
+ need to build a class ref anyway. */
+ t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
+ IDENTIFIER_POINTER (ident));
+ VEC_quick_push (tree, vec, t);
+ t = build_function_call_vec (input_location, objc_get_class_decl,
+ vec, NULL);
+ VEC_free (tree, gc, vec);
+ return t;
+ }
+}
+
+/* Used by get_arg_type_list.
+ Return the types for receiver & _cmd at the start of a method argument list.
+ context is either METHOD_DEF or METHOD_REF, saying whether we are trying
+ to define a method or call one. superflag says this is for a send to super.
+ meth may be NULL, in the case that there is no prototype. */
+
+static tree
+next_runtime_abi_02_get_arg_type_list_base (tree meth, int context, int superflag)
+{
+ tree arglist;
+
+ /* Receiver type. */
+ if (superflag)
+ arglist = build_tree_list (NULL_TREE, objc_super_type);
+ else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
+ arglist = build_tree_list (NULL_TREE, objc_instance_type);
+ else
+ arglist = build_tree_list (NULL_TREE, objc_object_type);
+
+ /* Selector type - will eventually change to `int'. */
+ chainon (arglist, build_tree_list (NULL_TREE,
+ (superflag ? objc_v2_super_selector_type
+ : objc_v2_selector_type)));
+ return arglist;
+}
+
+/* TODO: Merge this with the message refs. */
+static tree
+build_selector_reference_decl (tree ident)
+{
+ tree decl;
+ char *t, buf[BUFSIZE];
+
+ snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
+ t = buf;
+ while (*t)
+ {
+ if (*t==':')
+ *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
+ t++;
+ }
+ decl = start_var_decl (objc_selector_type, buf);
+ OBJCMETA (decl, objc_meta, meta_sel_refs);
+ return decl;
+}
+
+static tree
+next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
+ tree ident,
+ tree proto ATTRIBUTE_UNUSED)
+{
+ tree *chain = &sel_ref_chain;
+ tree expr;
+
+ while (*chain)
+ {
+ if (TREE_VALUE (*chain) == ident)
+ return TREE_PURPOSE (*chain);
+
+ chain = &TREE_CHAIN (*chain);
+ }
+
+ expr = build_selector_reference_decl (ident);
+ *chain = tree_cons (expr, ident, NULL_TREE);
+
+ return expr;
+}
+
+/* Declare a variable of type 'struct message_ref_t'. */
+/* This will be finished in build_v2_message_ref_translation_table ().
+ We take an idea from LLVM in making the names a bit more connected
+ and thus the asm more readable. */
+
+static tree
+build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
+{
+ tree decl;
+ char buf[BUFSIZE], *t;
+ int offset = 12;
+
+ /* Skip past the objc_msgSend it's the same for all... */
+ if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
+ offset++;
+
+ snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
+ &(IDENTIFIER_POINTER (message_func_ident)[offset]),
+ IDENTIFIER_POINTER (sel_name));
+ t = buf;
+ while (*t)
+ {
+ if (*t==':')
+ *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
+ t++;
+ }
+ decl = start_var_decl (objc_v2_message_ref_template, buf);
+ OBJCMETA (decl, objc_meta, meta_mref);
+ return decl;
+}
+
+typedef struct GTY(()) msgref_entry {
+ tree func;
+ tree selname;
+ tree refdecl;
+} msgref_entry;
+DEF_VEC_O(msgref_entry);
+DEF_VEC_ALLOC_O(msgref_entry, gc);
+
+static GTY (()) VEC (msgref_entry, gc) * msgrefs;
+
+/* Build the list of (objc_msgSend_fixup_xxx, selector name) Used later on to
+ initialize the table of 'struct message_ref_t' elements. */
+
+static tree
+build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
+{
+ tree decl;
+ msgref_entry e;
+ if (msgrefs)
+ {
+ int count;
+ msgref_entry *ref;
+ FOR_EACH_VEC_ELT (msgref_entry, msgrefs, count, ref)
+ if (ref->func == message_func_decl && ref->selname == sel_name)
+ return ref->refdecl;
+ }
+ else
+ /* Somewhat arbitrary initial provision. */
+ msgrefs = VEC_alloc (msgref_entry, gc, 32);
+ /* We come here if we don't find a match or at the start. */
+ decl = build_v2_message_reference_decl (sel_name,
+ DECL_NAME (message_func_decl));
+ e.func = message_func_decl;
+ e.selname = sel_name;
+ e.refdecl = decl;
+ VEC_safe_push (msgref_entry, gc, msgrefs, &e);
+ return decl;
+}
+
+static tree
+build_v2_protocollist_ref_decl (tree protocol)
+{
+ tree decl;
+ tree protocol_ident = PROTOCOL_NAME (protocol);
+ char buf[BUFSIZE];
+
+ snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
+ IDENTIFIER_POINTER (protocol_ident));
+ /* TODO: other compiler versions make these hidden & weak. */
+ decl = create_global_decl (objc_protocol_type, buf);
+ /* Let optimizer know that this decl is not removable. */
+ DECL_PRESERVE_P (decl) = 1;
+ OBJCMETA (decl, objc_meta, meta_proto_ref);
+ return decl;
+}
+
+typedef struct GTY(()) prot_list_entry {
+ tree id;
+ tree refdecl;
+} prot_list_entry;
+DEF_VEC_O(prot_list_entry);
+DEF_VEC_ALLOC_O(prot_list_entry, gc);
+static GTY (()) VEC (prot_list_entry, gc) * protrefs;
+
+static tree
+objc_v2_get_protocol_reference (tree ident)
+{
+ tree decl;
+ prot_list_entry e;
+ if (protrefs)
+ {
+ int count;
+ prot_list_entry *ref;
+ FOR_EACH_VEC_ELT (prot_list_entry, protrefs, count, ref)
+ {
+ if (ref->id == ident)
+ {
+ if (!ref->refdecl)
+ ref->refdecl = build_v2_protocollist_ref_decl (ident);
+ return ref->refdecl;
+ }
+ }
+ }
+ else
+ /* Somewhat arbitrary initial provision. */
+ protrefs = VEC_alloc (prot_list_entry, gc, 32);
+ /* We come here if we don't find the entry - or if the table was yet
+ to be created. */
+ decl = build_v2_protocollist_ref_decl (ident);
+ e.id = ident;
+ e.refdecl = decl;
+ VEC_safe_push (prot_list_entry, gc, protrefs, &e);
+ return decl;
+}
+
+static tree
+next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
+ tree p)
+{
+ if (!PROTOCOL_FORWARD_DECL (p))
+ PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
+
+ return objc_v2_get_protocol_reference (p);
+}
+
+/* This routine returns the ivar declaration, if component is a valid ivar field;
+ NULL_TREE otherwise. On finding an ivar, it also returns the class name in CLASS.
+*/
+
+static tree
+objc_is_ivar (tree expr, tree component, tree *klass)
+{
+ tree field = NULL_TREE;
+ tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
+
+ if (TREE_CODE (basetype) == RECORD_TYPE
+ && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
+ {
+ *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
+ if (*klass)
+ {
+ do
+ {
+ tree ivar_chain = CLASS_RAW_IVARS (*klass);
+ if (ivar_chain)
+ {
+ field = is_ivar (ivar_chain, component);
+ if (field != NULL_TREE)
+ break;
+ }
+ *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
+ }
+ while (*klass);
+ }
+ }
+ return field;
+}
+
+static void
+create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
+{
+ tree fname = DECL_NAME (field_decl);
+
+ sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
+ IDENTIFIER_POINTER (fname));
+ return;
+}
+
+/* This routine generates new abi's ivar reference tree. It amounts to generating
+ *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally generate pObj->IVAR
+ OFFSET_IVAR is an 'extern' variable holding the offset for 'IVAR' field. TYPE
+ is type of IVAR field.
+*/
+
+static tree
+objc_v2_build_ivar_ref (tree datum, tree component)
+{
+ tree field, ref, class_name, offset, ftype, expr;
+ char var_offset_name[512];
+
+ field = objc_is_ivar (datum, component, &class_name);
+ if (!field)
+ 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))
+ return NULL_TREE;
+
+ create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field);
+
+ offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
+
+ ftype = TREE_TYPE (field);
+
+ /* (char*)datum */
+ expr = build_c_cast (input_location,
+ string_type_node, build_fold_addr_expr (datum));
+
+ /* (char*)datum + offset */
+ expr = fold_build2_loc (input_location,
+ POINTER_PLUS_EXPR, string_type_node, expr, offset);
+
+ /* (ftype*)((char*)datum + offset) */
+ expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
+
+ /* Finally: *(ftype*)((char*)datum + offset) */
+ ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
+
+ /* We must set type of the resulting expression to be the same as the
+ field type. This is because, build_indirect_ref (...) rebuilds the
+ type which may result in lost information; as in the case of
+ protocol-qualified types (id <protocol> ). */
+ TREE_TYPE (ref) = ftype;
+
+ if (TREE_READONLY (datum) || TREE_READONLY (field))
+ TREE_READONLY (ref) = 1;
+
+ if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
+ TREE_THIS_VOLATILE (ref) = 1;
+
+ if (TREE_DEPRECATED (field))
+ warn_deprecated_use (field, NULL_TREE);
+
+ return ref;
+}
+
+/* IVAR refs are made via an externally referenceable offset and built
+ on the fly. That is, unless they refer to (private) fields in the
+ class stucture. */
+static tree
+next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
+ tree base, tree id)
+{
+ tree ivar;
+ if ((ivar = objc_v2_build_ivar_ref (base, id)))
+ return ivar;
+ return objc_build_component_ref (base, id);
+}
+
+/* [super ...] references are listed here (and built into a table at meta
+ -data emit time). */
+
+static tree
+build_v2_superclass_ref_decl (tree ident, bool inst)
+{
+ tree decl;
+ char buf[BUFSIZE];
+
+ snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
+ IDENTIFIER_POINTER (ident));
+ decl = start_var_decl (objc_class_type, buf);
+ OBJCMETA (decl, objc_meta, meta_superclass_ref);
+ return decl;
+}
+
+static GTY (()) VEC (ident_data_tuple, gc) * class_super_refs;
+static GTY (()) VEC (ident_data_tuple, gc) * metaclass_super_refs;
+
+static tree
+next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
+ struct imp_entry *imp, bool inst_meth)
+{
+ tree decl;
+ ident_data_tuple e;
+ tree id = CLASS_NAME (imp->imp_context);
+ VEC (ident_data_tuple, gc) *list = inst_meth ? class_super_refs
+ : metaclass_super_refs;
+
+ if (list)
+ {
+ int count;
+ ident_data_tuple *ref;
+ FOR_EACH_VEC_ELT (ident_data_tuple, list, count, ref)
+ {
+ if (ref->ident == id)
+ {
+ if (!ref->data)
+ ref->data = build_v2_superclass_ref_decl (id, inst_meth);
+ return ref->data;
+ }
+ }
+ }
+ else
+ {
+ /* Somewhat arbitrary initial provision. */
+ if (inst_meth)
+ list = class_super_refs = VEC_alloc (ident_data_tuple, gc, 16);
+ else
+ list = metaclass_super_refs = VEC_alloc (ident_data_tuple, gc, 16);
+ }
+ /* 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;
+ e.data = decl;
+ VEC_safe_push (ident_data_tuple, gc, list, &e);
+ return decl;
+}
+
+static tree
+next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
+ 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)
+ {
+ 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);
+/* assemble_external (super_class);*/
+ 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));
+}
+
+static tree
+next_runtime_abi_02_receiver_is_class_object (tree receiver)
+{
+ if (TREE_CODE (receiver) == VAR_DECL
+ && IS_CLASS (TREE_TYPE (receiver))
+ && classrefs
+ && VEC_length (ident_data_tuple, classrefs))
+ {
+ int count;
+ ident_data_tuple *ref;
+ /* The receiver is a variable created by build_class_reference_decl. */
+ FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
+ if (ref->data == receiver)
+ return ref->ident;
+ }
+ return NULL_TREE;
+}
+
+/* Assign all arguments in VALUES which have side-effect to a temporary and
+ replaced that argument in VALUES list with the temporary. TYPELIST is the
+ list of argument types. */
+
+static tree
+objc_copy_to_temp_side_effect_params (tree typelist, tree values)
+{
+ tree valtail, typetail;
+ /* skip over receiver and the &_msf_ref types */
+ gcc_assert (TREE_CHAIN (typelist));
+ typetail = TREE_CHAIN (TREE_CHAIN (typelist));
+
+ for (valtail = values; valtail;
+ valtail = TREE_CHAIN (valtail), typetail = TREE_CHAIN (typetail))
+ {
+ tree value = TREE_VALUE (valtail);
+ tree type = typetail ? TREE_VALUE (typetail) : NULL_TREE;
+ if (type == NULL_TREE)
+ break;
+ if (!TREE_SIDE_EFFECTS (value))
+ continue;
+ /* To prevent re-evaluation */
+ value = save_expr (value);
+ add_stmt (value);
+ TREE_VALUE (valtail) = value;
+ }
+ return values;
+}
+
+/* Build the new abi's messaging library call. It looks like:
+ (*_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)
+{
+ tree ret_val;
+ tree sender, rcv_p, t;
+ tree ret_type
+ = (method_prototype
+ ? TREE_VALUE (TREE_TYPE (method_prototype))
+ : objc_object_type);
+ tree method_param_types = get_arg_type_list (method_prototype,
+ METHOD_REF, super_flag);
+
+ tree ftype = build_function_type (ret_type, method_param_types);
+ tree sender_cast;
+
+ 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);
+
+ if (check_for_nil)
+ method_params = objc_copy_to_temp_side_effect_params (method_param_types,
+ method_params);
+
+ /* Get &message_ref_t.messenger */
+ sender = build_c_cast (input_location,
+ build_pointer_type (super_flag
+ ? objc_v2_super_imp_type
+ : objc_v2_imp_type),
+ selector);
+
+ sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
+
+ rcv_p = (super_flag ? objc_super_type : objc_object_type);
+
+ lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
+
+ /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
+ lookup_object = save_expr (lookup_object);
+
+ method_params = tree_cons (NULL_TREE, lookup_object,
+ tree_cons (NULL_TREE, selector,
+ method_params));
+ t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node);
+ ret_val = build_function_call (input_location, t, method_params);
+ 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,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 (input_location, NE_EXPR,
+ lookup_object,
+ fold_convert (rcv_p, integer_zero_node), 1);
+
+#ifdef OBJCPLUS
+ ret_val = build_conditional_expr (ifexp, ret_val, ftree, tf_warning_or_error);
+#else
+ /* ??? CHECKME. */
+ ret_val = build_conditional_expr (input_location,
+ ifexp, 1,
+ ret_val, NULL_TREE,
+ ftree, NULL_TREE);
+#endif
+ }
+ return ret_val;
+}
+
+static tree
+next_runtime_abi_02_build_objc_method_call (location_t loc,
+ tree method_prototype,
+ tree receiver,
+ tree rtype,
+ tree sel_name,
+ 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 future, class
+ declaration marked as weak_import must be nil checked. */
+ if (super
+ || (TREE_CODE (receiver) == VAR_DECL
+ && TREE_TYPE (receiver) == objc_class_type))
+ check_for_nil = false;
+
+ 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)
+ message_func_decl = umsg_id_super2_stret_fixup_decl;
+ else
+ message_func_decl = objc_is_id (rtype)
+ ? umsg_id_stret_fixup_decl
+ : umsg_stret_fixup_decl;
+ }
+ else
+ {
+ if (super)
+ message_func_decl = umsg_id_super2_fixup_decl;
+ else
+ message_func_decl = objc_is_id (rtype)
+ ? umsg_id_fixup_decl
+ : umsg_fixup_decl;
+ }
+
+ selector = build_v2_selector_messenger_reference (sel_name,
+ message_func_decl);
+
+ /* selector = &_msg; */
+ selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
+
+ selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
+ : objc_v2_selector_type),
+ selector);
+
+ /* (*_msg.messenger) (receiver, &_msg, ...); */
+ return build_v2_build_objc_method_call (super, method_prototype,
+ receiver, selector,
+ method_params, check_for_nil);
+}
+
+/* NOTE --- Constant String Class Stuff --- */
+
+static bool
+next_runtime_abi_02_setup_const_string_class_decl (void)
+{
+ if (!constant_string_global_id)
+ {
+ /* Hopefully, this should not represent a serious limitation. */
+ char buf[BUFSIZE];
+ snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
+ constant_string_global_id = get_identifier (buf);
+ }
+
+ string_class_decl = lookup_name (constant_string_global_id);
+
+ /* In OBJC2 abi constant string class reference refers to
+ class name for NSConstantString class. This declaration may not be
+ available yet (in fact it is not in most cases). So, declare an extern
+ OBJC_CLASS_$_NSConstantString in its place. */
+ if (!string_class_decl)
+ string_class_decl =
+ create_extern_decl (objc_v2_class_template,
+ IDENTIFIER_POINTER (constant_string_global_id));
+
+ return (string_class_decl != NULL_TREE);
+}
+
+static tree
+next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
+ int length)
+{
+ tree constructor, fields, var;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
+ fields = TYPE_FIELDS (internal_const_str_type);
+ CONSTRUCTOR_APPEND_ELT (v, fields,
+ build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
+
+ fields = DECL_CHAIN (fields);
+ CONSTRUCTOR_APPEND_ELT (v, fields,
+ build_unary_op (loc, ADDR_EXPR, string, 1));
+
+ /* ??? check if this should be long. */
+ fields = DECL_CHAIN (fields);
+ CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
+ constructor = objc_build_constructor (internal_const_str_type, v);
+
+ var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
+ DECL_INITIAL (var) = constructor;
+ TREE_STATIC (var) = 1;
+ DECL_CONTEXT (var) = NULL;
+ OBJCMETA (var, objc_meta, meta_const_str);
+ return var;
+}
+
+/* NOTE --- NeXT V2 Metadata templates --- */
+
+/* This routine builds the following type:
+ struct _prop_t {
+ const char * const name; // property name
+ const char * const attributes; // comma-delimited, encoded,
+ // property attributes
+ };
+*/
+
+static tree
+build_v2_property_template (void)
+{
+ tree prop_record;
+ tree decls, *chain = NULL;
+
+ prop_record = objc_start_struct (get_identifier ("_prop_t"));
+ /* const char * name */
+ decls = add_field_decl (string_type_node, "name", &chain);
+
+ /* const char * attribute */
+ add_field_decl (string_type_node, "attribute", &chain);
+
+ objc_finish_struct (prop_record, decls);
+ return prop_record;
+}
+
+/* struct ivar_t {
+ unsigned long int *offset;
+ char *name;
+ char *type;
+ uint32_t alignment;
+ uint32_t size;
+ };
+*/
+
+static tree
+build_v2_ivar_t_template (void)
+{
+ tree objc_ivar_id, objc_ivar_record;
+ tree decls, *chain = NULL;
+
+ objc_ivar_id = get_identifier ("_ivar_t");
+ objc_ivar_record = objc_start_struct (objc_ivar_id);
+
+ /* unsigned long int *offset */
+ decls = add_field_decl (build_pointer_type
+ (TREE_TYPE (size_zero_node)), "offset", &chain);
+
+ /* char *name; */
+ add_field_decl (string_type_node, "name", &chain);
+
+ /* char *type; */
+ add_field_decl (string_type_node, "type", &chain);
+
+ /* uint32_t alignment; */
+ add_field_decl (integer_type_node, "alignment", &chain);
+
+ /* uint32_t size; */
+ add_field_decl (integer_type_node, "size", &chain);
+
+ objc_finish_struct (objc_ivar_record, decls);
+ return objc_ivar_record;
+}
+
+static void
+build_metadata_templates (void)
+{
+
+ if (!objc_method_template)
+ objc_method_template = build_method_template ();
+
+ if (!objc_v2_property_template)
+ objc_v2_property_template = build_v2_property_template ();
+
+ if (!objc_v2_ivar_template)
+ objc_v2_ivar_template = build_v2_ivar_t_template ();
+
+}
+
+/* NOTE --- Output NeXT V2 Metadata --- */
+
+/* Routine builds name of Interface's main meta-data of type class_t. */
+
+static char *
+objc_build_internal_classname (tree ident, bool metaclass)
+{
+ static char string[512];
+ snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
+ : "OBJC_CLASS_$",
+ IDENTIFIER_POINTER (ident));
+ return string;
+}
+
+/* Build the name for object of type struct class_ro_t */
+
+static const char *
+newabi_append_ro (const char *name)
+{
+ char *dollar;
+ char *p;
+ static char string[BUFSIZE];
+ dollar = strchr (name, '$');
+ gcc_assert (dollar);
+ p = string;
+ *p = '_'; p++;
+ strncpy (p, name, (int)(dollar - name));
+ p += (int)(dollar - name);
+ sprintf (p, "RO_%s", dollar);
+ return string;
+}
+
+/* Build the struct message_ref_t msg =
+ {objc_msgSend_fixup_xxx, @selector(func)}
+ table.
+*/
+
+static
+void build_v2_message_ref_translation_table (void)
+{
+ int count;
+ msgref_entry *ref;
+
+ if (!msgrefs || !VEC_length (msgref_entry,msgrefs))
+ return;
+
+ FOR_EACH_VEC_ELT (msgref_entry, msgrefs, count, ref)
+ {
+ VEC(constructor_elt,gc) *initializer;
+ tree expr, constructor;
+ tree struct_type = TREE_TYPE (ref->refdecl);
+ location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
+
+ initializer = NULL;
+ /* First 'IMP messenger' field.. */
+ expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
+ expr = convert (objc_v2_imp_type, expr);
+ CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
+
+ /* then.. 'SEL name' field */
+ expr = build_selector (ref->selname);
+ CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
+ constructor = objc_build_constructor (struct_type, initializer);
+ finish_var_decl (ref->refdecl, constructor);
+ }
+}
+
+/* Build decl = initializer; for each externally visible class reference. */
+
+static void
+build_v2_classrefs_table (void)
+{
+ int count;
+ ident_data_tuple *ref;
+
+ if (!classrefs || !VEC_length (ident_data_tuple, classrefs))
+ return;
+
+ FOR_EACH_VEC_ELT (ident_data_tuple, classrefs, count, ref)
+ {
+ tree expr = ref->ident;
+ tree decl = ref->data;
+ /* Interface with no implementation and yet one of its messages has been
+ used. Need to generate a full address-of tree for it here. */
+ if (TREE_CODE (expr) == IDENTIFIER_NODE)
+ {
+ const char *name = objc_build_internal_classname (expr, false);
+ expr = create_extern_decl (objc_v2_class_template, name);
+ expr = convert (objc_class_type, build_fold_addr_expr (expr));
+ }
+ /* The runtime wants this, even if it appears unused, so we must force the
+ output.
+ DECL_PRESERVE_P (decl) = 1; */
+ finish_var_decl (decl, expr);
+ }
+}
+
+/* Build decl = initializer; for each externally visible class reference. */
+
+static void
+build_v2_super_classrefs_table (bool metaclass)
+{
+ int count;
+ ident_data_tuple *ref;
+ VEC (ident_data_tuple, gc) *list = metaclass ? metaclass_super_refs
+ : class_super_refs;
+
+ if (!list || !VEC_length (ident_data_tuple, list))
+ return;
+
+ FOR_EACH_VEC_ELT (ident_data_tuple, list, count, ref)
+ {
+ tree expr = ref->ident;
+ tree decl = ref->data;
+ /* Interface with no implementation and yet one of its messages has been
+ used. Need to generate a full address-of tree for it here. */
+ if (TREE_CODE (expr) == IDENTIFIER_NODE)
+ {
+ const char * name = objc_build_internal_classname (expr, metaclass);
+ expr = create_extern_decl (objc_v2_class_template, name);
+ expr = convert (objc_class_type, build_fold_addr_expr (expr));
+ }
+ finish_var_decl (decl, expr);
+ }
+}
+
+/* Add the global class meta-data declaration to the list which later on
+ ends up in the __class_list section. */
+
+static GTY(()) VEC(tree,gc) *class_list;
+
+static void
+objc_v2_add_to_class_list (tree global_class_decl)
+{
+ if (!class_list)
+ class_list = VEC_alloc (tree, gc, imp_count?imp_count:1);
+ VEC_safe_push (tree, gc, class_list, global_class_decl);
+}
+
+static GTY(()) VEC(tree,gc) *nonlazy_class_list;
+
+/* Add the global class meta-data declaration to the list which later on
+ ends up in the __nonlazy_class section. */
+
+static void
+objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
+{
+ if (!nonlazy_class_list)
+ nonlazy_class_list = VEC_alloc (tree, gc, imp_count?imp_count:1);
+ VEC_safe_push (tree, gc, nonlazy_class_list, global_class_decl);
+}
+
+static GTY(()) VEC(tree,gc) *category_list;
+
+/* Add the category meta-data declaration to the list which later on ends up
+ in the __nonlazy_category section. */
+
+static void
+objc_v2_add_to_category_list (tree decl)
+{
+ if (!category_list)
+ category_list = VEC_alloc (tree, gc, cat_count?cat_count:1);
+ VEC_safe_push (tree, gc, category_list, decl);
+}
+
+static GTY(()) VEC(tree,gc) *nonlazy_category_list;
+
+/* Add the category meta-data declaration to the list which later on ends up
+ in the __category_list section. */
+
+static void
+objc_v2_add_to_nonlazy_category_list (tree decl)
+{
+ if (!nonlazy_category_list)
+ nonlazy_category_list = VEC_alloc (tree, gc, cat_count?cat_count:1);
+ VEC_safe_push (tree, gc, nonlazy_category_list, decl);
+}
+
+static bool
+has_load_impl (tree clsmeth)
+{
+ while (clsmeth)
+ {
+ tree id = METHOD_SEL_NAME (clsmeth);
+ if (IDENTIFIER_LENGTH (id) == 4
+ && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0)
+ return true;
+ clsmeth = DECL_CHAIN (clsmeth);
+ }
+
+ return false;
+}
+
+/* Build a __{class,category}_list section table containing address of all
+ @implemented {class,category} meta-data. */
+
+static void
+build_v2_address_table (VEC(tree,gc) *src, const char *nam, tree attr)
+{
+ int count=0;
+ tree type, decl, expr;
+ VEC(constructor_elt,gc) *initlist = NULL;
+
+ if (!src || !VEC_length(tree,src))
+ return;
+
+ FOR_EACH_VEC_ELT (tree, src, count, decl)
+ {
+#ifndef OBJCPLUS
+ tree purpose = build_int_cst (NULL_TREE, count);
+#else
+ tree purpose = NULL_TREE;
+#endif
+ expr = convert (objc_class_type, build_fold_addr_expr (decl));
+ CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
+ }
+ gcc_assert (count > 0);
+ type = build_array_type (objc_class_type,
+ build_index_type (build_int_cst (NULL_TREE, count - 1)));
+ decl = start_var_decl (type, nam);
+ /* The runtime wants this, even if it appears unused, so we must force the
+ output. */
+ DECL_PRESERVE_P (decl) = 1;
+ expr = objc_build_constructor (type, initlist);
+ OBJCMETA (decl, objc_meta, attr);
+ finish_var_decl (decl, expr);
+}
+
+/* Build decl = initializer;
+ for each protocol referenced in @protocol(MyProt) expression.
+ Refs as built in the entry section above. */
+
+static void
+build_v2_protocol_list_translation_table (void)
+{
+ int count;
+ prot_list_entry *ref;
+
+ if (!protrefs)
+ return;
+
+ FOR_EACH_VEC_ELT (prot_list_entry, protrefs, count, ref)
+ {
+ char buf[BUFSIZE];
+ tree expr;
+ gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
+ snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
+ expr = start_var_decl (objc_v2_protocol_template, buf);
+ expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
+ finish_var_decl (ref->refdecl, expr);
+ }
+ /* TODO: Maybe we could explicitly delete the vec. now? */
+}
+
+static GTY (()) VEC (prot_list_entry, gc) * protlist;
+
+/* Add the local protocol meta-data declaration to the list which later on ends up
+ in the __protocol_list section. */
+
+static void
+objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
+{
+ prot_list_entry e;
+ if (!protlist)
+ /* Arbitrary init count. */
+ protlist = VEC_alloc (prot_list_entry, gc, 32);
+ e.id = protocol_interface_decl;
+ e.refdecl = protocol_decl;
+ VEC_safe_push (prot_list_entry, gc, protlist, &e);
+}
+
+/* Build the __protocol_list section table containing address of all generate protocol_t
+ meta-data. */
+
+static void
+build_v2_protocol_list_address_table (void)
+{
+ int count;
+ prot_list_entry *ref;
+ if (!protlist || !VEC_length (prot_list_entry, protlist))
+ return;
+
+ FOR_EACH_VEC_ELT (prot_list_entry, protlist, count, ref)
+ {
+ tree decl, expr;
+ char buf[BUFSIZE];
+ 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);
+ expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
+ OBJCMETA (decl, objc_meta, meta_label_protocollist);
+ finish_var_decl (decl, expr);
+ }
+
+ /* TODO: delete the vec. */
+ /* TODO: upgrade to the the clang/llvm hidden version. */
+}
+
+/* This routine declares a variable to hold meta data for
+ 'struct protocol_list_t'. */
+
+static tree
+generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
+{
+ tree refs_decl, lproto, e, plist, ptempl_p_t;
+ int size = 0;
+ VEC(constructor_elt,gc) *initlist = NULL;
+ char buf[BUFSIZE];
+
+ if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
+ || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
+ plist = CLASS_PROTOCOL_LIST (i_or_p);
+ else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
+ plist = PROTOCOL_LIST (i_or_p);
+ else
+ gcc_unreachable ();
+
+ /* Compute size. */
+ for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
+ if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
+ && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
+ size++;
+
+ /* Build initializer. */
+
+ ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
+ e = build_int_cst (ptempl_p_t, size);
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
+
+ for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
+ {
+ tree pval = TREE_VALUE (lproto);
+
+ if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
+ && PROTOCOL_FORWARD_DECL (pval))
+ {
+ tree fwref = PROTOCOL_FORWARD_DECL (pval);
+ location_t loc = DECL_SOURCE_LOCATION (fwref) ;
+ e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
+ }
+ }
+
+ /* static struct protocol_list_t *list[size]; */
+
+ switch (TREE_CODE (i_or_p))
+ {
+ case PROTOCOL_INTERFACE_TYPE:
+ snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
+ break;
+ case CLASS_INTERFACE_TYPE:
+ snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
+ break;
+ case CATEGORY_INTERFACE_TYPE:
+ snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
+ buf);
+ /* ObjC2 puts all these in the base section. */
+ OBJCMETA (refs_decl, objc_meta, meta_base);
+ DECL_PRESERVE_P (refs_decl) = 1;
+ finish_var_decl (refs_decl,
+ objc_build_constructor (TREE_TYPE (refs_decl),initlist));
+ return refs_decl;
+}
+
+/* This routine builds one 'struct method_t' initializer list. Note that the
+ old ABI is supposed to build 'struct objc_method' which has 3 fields, but
+ it does not build the initialization expression for 'method_imp' which for
+ protocols is NULL any way. To be consistant with declaration of
+ 'struct method_t', in the new ABI we set the method_t.imp to NULL.
+*/
+
+static tree
+build_v2_descriptor_table_initializer (tree type, tree entries)
+{
+ VEC(constructor_elt,gc) *initlist = NULL;
+ do
+ {
+ VEC(constructor_elt,gc) *eltlist = NULL;
+ CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
+ build_selector (METHOD_SEL_NAME (entries)));
+ CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
+ add_objc_string (METHOD_ENCODING (entries),
+ meth_var_types));
+ CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
+
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
+ objc_build_constructor (type, eltlist));
+ entries = TREE_CHAIN (entries);
+ }
+ while (entries);
+
+ return objc_build_constructor (build_array_type (type, 0), initlist);
+}
+
+/* struct method_list_t {
+ uint32_t entsize;
+ uint32_t method_count;
+ struct objc_method method_list[method_count];
+ }; */
+
+static tree
+build_v2_method_list_template (tree list_type, int size)
+{
+ tree method_list_t_record;
+ tree array_type, decls, *chain = NULL;
+
+ method_list_t_record = objc_start_struct (NULL_TREE);
+
+ /* uint32_t const entsize */
+ decls = add_field_decl (integer_type_node, "entsize", &chain);
+
+ /* int method_count; */
+ add_field_decl (integer_type_node, "method_count", &chain);
+
+ /* struct objc_method method_list[]; */
+ array_type = build_sized_array_type (list_type, size);
+ add_field_decl (array_type, "method_list", &chain);
+
+ objc_finish_struct (method_list_t_record, decls);
+ return method_list_t_record;
+}
+
+/* Note, as above that we are building to the objc_method_template
+ which has the *imp field. ABI0/1 build with 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)
+{
+ tree method_list_template, initlist, decl, methods;
+ int size, entsize;
+ VEC(constructor_elt,gc) *v = NULL;
+ char buf[BUFSIZE];
+
+ if (!chain || !prefix)
+ return NULL_TREE;
+
+ methods = chain;
+ size = 0;
+ while (methods)
+ {
+ if (! METHOD_ENCODING (methods))
+ METHOD_ENCODING (methods) = encode_method_prototype (methods);
+ methods = TREE_CHAIN (methods);
+ size++;
+ }
+
+ gcc_assert (size);
+ method_list_template = build_v2_method_list_template (objc_method_template,
+ size);
+ snprintf (buf, BUFSIZE, "%s_%s", prefix,
+ IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
+
+ decl = start_var_decl (method_list_template, buf);
+
+ entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
+ initlist =
+ build_v2_descriptor_table_initializer (objc_method_template,
+ chain);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
+ /* Get into the right section. */
+ OBJCMETA (decl, objc_meta, attr);
+ finish_var_decl (decl, objc_build_constructor (method_list_template, 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. */
+
+static tree
+build_v2_property_table_initializer (tree type, tree context)
+{
+ tree x;
+ VEC(constructor_elt,gc) *inits = NULL;
+ if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
+ x = CLASS_PROPERTY_DECL (context);
+ else
+ x = IMPL_PROPERTY_DECL (context);
+
+ for (; x; x = TREE_CHAIN (x))
+ {
+ VEC(constructor_elt,gc) *elemlist = NULL;
+ /* NOTE! sections where property name/attribute go MUST change later. */
+ tree attribute, name_ident = PROPERTY_NAME (x);
+
+ CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
+ add_objc_string (name_ident, prop_names_attr));
+
+ attribute = objc_v2_encode_prop_attr (x);
+ CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
+ add_objc_string (attribute, prop_names_attr));
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ objc_build_constructor (type, elemlist));
+ }
+
+ return objc_build_constructor (build_array_type (type, 0),inits);
+}
+
+/* This routine builds the following type:
+ struct _prop_list_t {
+ uint32_t entsize; // sizeof (struct _prop_t)
+ uint32_t prop_count;
+ struct _prop_t prop_list [prop_count];
+ }
+*/
+
+static tree
+build_v2_property_list_template (tree list_type, int size)
+{
+ tree property_list_t_record;
+ tree array_type, decls, *chain = NULL;
+
+ /* anonymous. */
+ property_list_t_record = objc_start_struct (NULL_TREE);
+
+ /* uint32_t const entsize */
+ decls = add_field_decl (integer_type_node, "entsize", &chain);
+
+ /* int prop_count */
+ add_field_decl (integer_type_node, "prop_count", &chain);
+
+ /* struct _prop_t prop_list[]; */
+ array_type = build_sized_array_type (list_type, size);
+ add_field_decl (array_type, "prop_list", &chain);
+
+ objc_finish_struct (property_list_t_record, decls);
+ return property_list_t_record;
+}
+
+/*
+ Top-level routine to generate property tables for each implementation.
+*/
+
+static tree
+generate_v2_property_table (tree context, tree klass_ctxt)
+{
+ tree x, decl, initlist, property_list_template;
+ bool is_proto = false;
+ VEC(constructor_elt,gc) *inits = NULL;
+ int init_val, size = 0;
+ char buf[BUFSIZE];
+
+ if (context)
+ {
+ gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
+ x = CLASS_PROPERTY_DECL (context);
+ is_proto = true;
+ }
+ else
+ x = IMPL_PROPERTY_DECL (klass_ctxt);
+
+ for (; x; x = TREE_CHAIN (x))
+ size++;
+
+ if (size == 0)
+ return NULL_TREE;
+
+ property_list_template =
+ build_v2_property_list_template (objc_v2_property_template,
+ size);
+
+ initlist = build_v2_property_table_initializer (objc_v2_property_template,
+ is_proto ? context
+ : klass_ctxt);
+
+ init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
+ if (is_proto)
+ snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
+ IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
+ else
+ snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
+
+ decl = start_var_decl (property_list_template, buf);
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ build_int_cst (NULL_TREE, init_val));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ build_int_cst (NULL_TREE, size));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
+
+ OBJCMETA (decl, objc_meta, meta_base);
+ finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
+ return decl;
+}
+
+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 expr, ttyp;
+ location_t loc;
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ /* TODO: find a better representation of location from the inputs. */
+ loc = UNKNOWN_LOCATION;
+
+ /* This is NULL for the new ABI. */
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ convert (objc_object_type, null_pointer_node));
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
+
+ ttyp = objc_method_proto_list_ptr;
+ if (inst_methods)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ if (class_methods)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ if (opt_ins_meth)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ if (opt_cls_meth)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ ttyp = objc_prop_list_ptr;
+ if (property_list)
+ expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
+ else
+ expr = convert (ttyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+
+ /* const uint32_t size; = sizeof(struct protocol_t) */
+ expr = build_int_cst (integer_type_node,
+ TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
+ /* const uint32_t flags; = 0 */
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
+
+ return objc_build_constructor (type, inits);
+}
+
+/*
+ Main routine to build all meta data for all protocols used in a translation unit.
+*/
+
+static void
+generate_v2_protocols (void)
+{
+ tree p ;
+ bool some = false;
+
+ if (!protocol_chain)
+ return ;
+
+ /* If a protocol was directly referenced, pull in indirect references. */
+ for (p = protocol_chain; p; p = TREE_CHAIN (p))
+ if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
+ generate_protocol_references (PROTOCOL_LIST (p));
+
+ for (p = protocol_chain; p; p = TREE_CHAIN (p))
+ {
+ location_t loc;
+ tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
+ tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
+
+ /* If protocol wasn't referenced, don't generate any code. */
+ decl = PROTOCOL_FORWARD_DECL (p);
+
+ if (!decl)
+ continue;
+
+ loc = DECL_SOURCE_LOCATION (decl);
+ some = true;
+
+ inst_meth =
+ generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
+ "_OBJC_ProtocolInstanceMethods",
+ meta_proto_nst_meth);
+
+ class_meth =
+ generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
+ "_OBJC_ProtocolClassMethods",
+ meta_proto_cls_meth);
+
+ opt_inst_meth =
+ generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
+ "_OBJC_OptProtocolInstMethods",
+ meta_proto_nst_meth);
+
+ opt_class_meth =
+ generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
+ "_OBJC_OptProtocolClassMethods",
+ meta_proto_cls_meth);
+
+ if (PROTOCOL_LIST (p))
+ refs_decl = generate_v2_protocol_list (p, NULL_TREE);
+ else
+ refs_decl = 0;
+
+ /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
+ protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
+
+ if (refs_decl)
+ refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
+ build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
+ else
+ refs_expr = build_int_cst (NULL_TREE, 0);
+
+ props = generate_v2_property_table (p, 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);
+ finish_var_decl (decl, initlist);
+ objc_add_to_protocol_list (p, decl);
+ }
+
+ if (some)
+ {
+ /* Make sure we get the Protocol class linked in - reference it... */
+ p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
+ /* .. but since we don't specifically use the ref..
+ we need to force it. */
+ DECL_PRESERVE_P (p) = 1;
+ }
+}
+
+static tree
+generate_v2_dispatch_table (tree chain, const char *name, tree attr)
+{
+ tree decl, method_list_template, initlist;
+ VEC(constructor_elt,gc) *v = NULL;
+ int size, init_val;
+
+ if (!chain || !name || !(size = list_length (chain)))
+ return NULL_TREE;
+
+ method_list_template
+ = build_v2_method_list_template (objc_method_template, size);
+ initlist
+ = build_dispatch_table_initializer (objc_method_template, chain);
+
+ decl = start_var_decl (method_list_template, name);
+
+ init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (integer_type_node, init_val));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_int_cst (integer_type_node, size));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
+
+ OBJCMETA (decl, objc_meta, attr);
+ finish_var_decl (decl,
+ objc_build_constructor (TREE_TYPE (decl), v));
+ return decl;
+}
+
+/* Init a category. */
+static tree
+build_v2_category_initializer (tree type, tree cat_name, tree class_name,
+ tree inst_methods, tree class_methods,
+ tree protocol_list, tree property_list,
+ location_t loc)
+{
+ tree expr, ltyp;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
+
+ ltyp = objc_method_list_ptr;
+ if (inst_methods)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ if (class_methods)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* protocol_list = */
+ ltyp = build_pointer_type (objc_v2_protocol_template);
+ if (protocol_list)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ ltyp = objc_prop_list_ptr;
+ if (property_list)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ return objc_build_constructor (type, v);
+}
+
+/* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
+
+static void
+generate_v2_category (struct imp_entry *impent)
+{
+ tree initlist, cat_name_expr, class_name_expr;
+ tree protocol_decl, category, props, t;
+ tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
+ tree cat = impent->imp_context;
+ tree cat_decl = impent->class_decl;
+ location_t loc;
+ char buf[BUFSIZE];
+
+ loc = DECL_SOURCE_LOCATION (cat_decl);
+
+ /* ??? not sure this is really necessary, the following references should
+ force appropriate linkage linkage...
+ -- but ... ensure a reference to the class... */
+ t = objc_v2_get_class_reference (CLASS_NAME (cat));
+ /* ... which we ignore so force it out.. */
+ DECL_PRESERVE_P (t) = 1;
+
+ snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
+ class_name_expr = create_extern_decl (objc_v2_class_template, buf);
+ class_name_expr = build_fold_addr_expr (class_name_expr);
+
+ cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
+ category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
+
+ if (category && CLASS_PROTOCOL_LIST (category))
+ {
+ generate_protocol_references (CLASS_PROTOCOL_LIST (category));
+ protocol_decl = generate_v2_protocol_list (category, cat);
+ }
+ else
+ protocol_decl = NULL_TREE;
+
+/* decl = update_var_decl(impent->class_decl);*/
+
+ props = generate_v2_property_table (NULL_TREE, cat);
+
+ if (CLASS_NST_METHODS (cat))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (cat)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
+ inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
+ meta_cati_meth);
+ }
+
+ if (CLASS_CLS_METHODS (cat))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (cat)),
+ IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
+ class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
+ meta_catc_meth);
+ }
+
+ initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
+ cat_name_expr, class_name_expr,
+ inst_methods, class_methods,
+ protocol_decl, props, loc);
+
+ finish_var_decl (cat_decl, initlist);
+ impent->class_decl = cat_decl;
+
+ /* Add to list of pointers in __category_list section */
+ objc_v2_add_to_category_list (cat_decl);
+ if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
+ objc_v2_add_to_nonlazy_category_list (cat_decl);
+}
+
+/* This routine declares a variable to hold the offset for ivar FIELD_DECL.
+ Variable name is .objc_ivar.ClassName.IvarName. */
+
+typedef struct GTY(()) ivarref_entry {
+ tree decl;
+ tree offset;
+} ivarref_entry;
+DEF_VEC_O(ivarref_entry);
+DEF_VEC_ALLOC_O(ivarref_entry, gc);
+
+static GTY (()) VEC (ivarref_entry, gc) * ivar_offset_refs;
+
+static tree
+ivar_offset_ref (tree class_name, tree field_decl)
+{
+ tree decl, field_decl_id;
+ ivarref_entry e;
+ bool global_var;
+ char buf[512];
+
+ create_ivar_offset_name (buf, class_name, field_decl);
+ field_decl_id = get_identifier (buf);
+
+ if (ivar_offset_refs)
+ {
+ int count;
+ ivarref_entry *ref;
+ FOR_EACH_VEC_ELT (ivarref_entry, ivar_offset_refs, count, ref)
+ if (DECL_NAME (ref->decl) == field_decl_id)
+ return ref->decl;
+ }
+ else
+ /* Somewhat arbitrary initial provision. */
+ ivar_offset_refs = VEC_alloc (ivarref_entry, gc, 32);
+
+ /* We come here if we don't find a match or at the start. */
+ global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
+ if (global_var)
+ decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
+ else
+ decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
+
+ /* Make sure it ends up in an ObjC section. */
+ OBJCMETA (decl, objc_meta, meta_base);
+
+ e.decl = decl;
+ e.offset = byte_position (field_decl);
+ VEC_safe_push (ivarref_entry, gc, ivar_offset_refs, &e);
+ return decl;
+}
+
+/* This routine builds initializer-list needed to initialize
+ 'struct ivar_t list[count]
+ of 'struct ivar_list_t' meta data. TYPE is 'struct ivar_t' and
+ FIELD_DECL is list of ivars for the target class.
+*/
+
+static tree
+build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
+{
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ do
+ {
+ VEC(constructor_elt,gc) *ivar = NULL;
+ int val;
+ tree id;
+
+ /* Unnamed bitfields are ignored. */
+ if (!DECL_NAME (field_decl))
+ {
+ field_decl = DECL_CHAIN (field_decl);
+ continue;
+ }
+
+ /* Set offset */
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
+ build_unary_op (input_location,
+ ADDR_EXPR,
+ ivar_offset_ref (class_name,
+ field_decl), 0));
+
+ /* Set name */
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
+ add_objc_string (DECL_NAME (field_decl),
+ meth_var_names));
+
+ /* Set type */
+ encode_field_decl (field_decl,
+ obstack_object_size (&util_obstack),
+ OBJC_ENCODE_DONT_INLINE_DEFS);
+ /* Null terminate string. */
+ obstack_1grow (&util_obstack, 0);
+ id = add_objc_string (get_identifier (XOBFINISH (&util_obstack, char *)),
+ meth_var_types);
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
+ obstack_free (&util_obstack, util_firstobj);
+
+ /* Set alignment */
+ val = DECL_ALIGN_UNIT (field_decl);
+ val = exact_log2 (val);
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
+ build_int_cst (integer_type_node, val));
+
+ /* Set size */
+ val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
+ build_int_cst (integer_type_node, val));
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ objc_build_constructor (type, ivar));
+
+ do
+ field_decl = DECL_CHAIN (field_decl);
+ while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
+ }
+ while (field_decl);
+
+ return objc_build_constructor (build_array_type (type, 0), inits);
+}
+
+/*
+ struct ivar_list_t {
+ uint32 entsize;
+ uint32 count;
+ struct iver_t list[count];
+ };
+*/
+
+static tree
+build_v2_ivar_list_t_template (tree list_type, int size)
+{
+ tree objc_ivar_list_record;
+ tree decls, *chain = NULL;
+
+ /* Anonymous. */
+ objc_ivar_list_record = objc_start_struct (NULL_TREE);
+
+ /* uint32 entsize; */
+ decls = add_field_decl (integer_type_node, "entsize", &chain);
+
+ /* uint32 count; */
+ add_field_decl (integer_type_node, "count", &chain);
+
+ /* struct objc_ivar ivar_list[]; */
+ add_field_decl (build_sized_array_type (list_type, size),
+ "list", &chain);
+
+ objc_finish_struct (objc_ivar_list_record, decls);
+ return objc_ivar_list_record;
+}
+
+/* This routine declares a static variable of type 'struct ivar_list_t' and
+ initializes it.
+ chain is the source of the data, name is the name for the var.
+ attr is the meta-data section tag attribute
+ templ is the implementation template for the class. */
+
+static tree
+generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
+{
+ tree decl, initlist, ivar_list_template;
+ VEC(constructor_elt,gc) *inits = NULL;
+ int size, ivar_t_size;
+
+ if (!chain || !name || !(size = ivar_list_length (chain)))
+ return NULL_TREE;
+
+ generating_instance_variables = 1;
+ ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
+ size);
+
+ initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
+ objc_v2_ivar_template, chain);
+ ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
+
+ decl = start_var_decl (ivar_list_template, name);
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ build_int_cst (integer_type_node, ivar_t_size));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ build_int_cst (integer_type_node, size));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
+ OBJCMETA (decl, objc_meta, attr);
+ finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
+ generating_instance_variables = 0;
+ return decl;
+}
+
+/* Routine to build initializer list to initialize objects of type struct class_t; */
+
+static tree
+build_v2_class_t_initializer (tree type, tree isa, tree superclass,
+ tree ro, tree cache, tree vtable)
+{
+ VEC(constructor_elt,gc) *initlist = NULL;
+
+ /* isa */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
+
+ /* superclass */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
+
+ /* cache */
+ if (cache)
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
+ else
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
+
+ /* vtable */
+ if (vtable)
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
+ else
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
+
+ /* ro */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
+
+ return objc_build_constructor (type, initlist);
+}
+
+/* Routine to build object of struct class_ro_t { ... }; */
+
+static tree
+build_v2_class_ro_t_initializer (tree type, tree name,
+ unsigned int flags, unsigned int instanceStart,
+ unsigned int instanceSize,
+ tree ivarLayout,
+ tree baseMethods, tree baseProtocols,
+ tree ivars, tree property_list)
+{
+ tree expr, unsigned_char_star, ltyp;
+ location_t loc;
+ VEC(constructor_elt,gc) *initlist = NULL;
+
+ /* TODO: fish out the real location from somewhere. */
+ loc = UNKNOWN_LOCATION;
+
+ /* flags */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
+ build_int_cst (integer_type_node, flags));
+
+ /* instanceStart */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
+ build_int_cst (integer_type_node, instanceStart));
+
+ /* instanceSize */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
+ build_int_cst (integer_type_node, instanceSize));
+
+ /* This ABI is currently only used on m64 NeXT, we choose to
+ make the alignment padding explicit. */
+ /* reserved, pads alignment. */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
+ build_int_cst (integer_type_node, 0));
+
+ /* ivarLayout */
+ unsigned_char_star = build_pointer_type (unsigned_char_type_node);
+ if (ivarLayout)
+ expr = ivarLayout;
+ else
+ expr = convert (unsigned_char_star, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
+
+ /* name */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
+
+ /* baseMethods */
+ ltyp = objc_method_list_ptr;
+ if (baseMethods)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
+
+ /* baseProtocols */
+ ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_V2_PROTOCOL_LIST)));
+ if (baseProtocols)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
+
+ /* ivars */
+ ltyp = objc_v2_ivar_list_ptr;
+ if (ivars)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
+
+ /* TODO: We don't yet have the weak/strong stuff... */
+ /* weakIvarLayout */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
+ convert (unsigned_char_star, null_pointer_node));
+
+ /* property list */
+ ltyp = objc_prop_list_ptr;
+ if (property_list)
+ expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
+ return objc_build_constructor (type, initlist);
+}
+
+static GTY (()) VEC (ident_data_tuple, gc) * ehtype_list;
+
+/* Record a name as needing a catcher. */
+static void
+objc_v2_add_to_ehtype_list (tree name)
+{
+ ident_data_tuple e;
+ if (ehtype_list)
+ {
+ int count = 0;
+ ident_data_tuple *ref;
+
+ FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
+ if (ref->ident == name)
+ return; /* Already entered. */
+ }
+ else
+ /* Arbitrary initial count. */
+ ehtype_list = VEC_alloc (ident_data_tuple, gc, 8);
+ /* Not found, or new list. */
+ e.ident = name;
+ e.data = NULL_TREE;
+ VEC_safe_push (ident_data_tuple, gc, ehtype_list, &e);
+}
+
+static void
+generate_v2_class_structs (struct imp_entry *impent)
+{
+ tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
+ tree field, firstIvar, chain;
+ tree class_superclass_expr, metaclass_superclass_expr, props;
+ /* TODO: figure out how to compute this. */
+ tree ivarLayout = NULL_TREE;
+ tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
+ tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
+ tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
+ location_t loc;
+ char buf[BUFSIZE];
+ unsigned int instanceStart, instanceSize;
+ unsigned int flags = 0x01; /* RO_META */
+ int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
+ : 0 ;
+
+ class_decl = impent->class_decl;
+ metaclass_decl = impent->meta_decl;
+ loc = DECL_SOURCE_LOCATION (class_decl);
+
+ DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
+ TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
+#ifdef OBJCPLUS
+ gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
+ gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
+#endif
+
+ /* Generation of data for meta class */
+ my_super_id = CLASS_SUPER_NAME (impent->imp_template);
+ if (my_super_id)
+ {
+ /* compute reference to root's name. For meta class, "isa" is reference
+ to root class name. */
+ tree my_root_id = my_super_id;
+ tree my_root_int, interface;
+ do
+ {
+ my_root_int = lookup_interface (my_root_id);
+
+ if (my_root_int && CLASS_SUPER_NAME (my_root_int))
+ my_root_id = CLASS_SUPER_NAME (my_root_int);
+ else
+ break;
+ }
+ while (1);
+
+ /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
+ create extern if not already declared. */
+ snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
+ root_expr = create_extern_decl (objc_v2_class_template, buf);
+ root_expr = build_fold_addr_expr (root_expr);
+
+ /* Install class `isa' and `super' pointers at runtime. */
+ interface = lookup_interface (my_super_id);
+ gcc_assert (interface);
+ /* Similarly, for OBJC_CLASS_$_<interface>... */
+ snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (interface)));
+ class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
+ class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
+ /* ... and for OBJC_METACLASS_$_<interface>. */
+ snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (interface)));
+ metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
+ metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
+ }
+ else
+ {
+ /* root class. */
+ root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
+ metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
+ class_superclass_expr = build_int_cst (NULL_TREE, 0);
+ flags |= 0x02; /* RO_ROOT: it is also a root meta class */
+ }
+
+ if (CLASS_PROTOCOL_LIST (impent->imp_template))
+ {
+ generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
+ protocol_decl = generate_v2_protocol_list (impent->imp_template,
+ impent->imp_context);
+ }
+ else
+ protocol_decl = 0;
+
+ name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
+ class_names);
+
+ if (CLASS_CLS_METHODS (impent->imp_context))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ class_methods =
+ generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
+ buf, meta_clac_meth);
+ }
+
+ instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
+
+ /* Currently there are no class ivars and generation of class variables for
+ the root of the inheritance has been removed. It causes multiple defines
+ if there are two root classes in the link, because each will define its
+ own identically-named offset variable. */
+
+ class_ivars = NULL_TREE;
+ /* TODO: Add total size of class variables when implemented. */
+ instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
+
+ /* So now build the META CLASS structs. */
+ /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
+
+ decl = start_var_decl (objc_v2_class_ro_template,
+ newabi_append_ro (IDENTIFIER_POINTER
+ (DECL_NAME (metaclass_decl))));
+
+ /* TODO: ivarLayout needs t be built. */
+ initlist =
+ build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
+ (flags | cls_flags), instanceStart,
+ instanceSize, ivarLayout,
+ class_methods, protocol_decl,
+ class_ivars, NULL_TREE);
+ /* The ROs sit in the default const section. */
+ OBJCMETA (decl, objc_meta, meta_base);
+ finish_var_decl (decl, initlist);
+
+ /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
+ initlist =
+ build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
+ root_expr,
+ metaclass_superclass_expr,
+ build_fold_addr_expr (decl),
+ build_fold_addr_expr (UOBJC_V2_CACHE_decl),
+ build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
+ /* The class section attributes are set when they are created. */
+ finish_var_decl (metaclass_decl, initlist);
+ impent->meta_decl = metaclass_decl;
+
+ /* So now build the CLASS structs. */
+
+ flags = 0x0; /* ... */
+ if (!my_super_id)
+ flags |= 0x02; /* RO_ROOT: this is a root class */
+
+ if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
+ flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
+
+ if (objc2_objc_exception_attr (impent->imp_template))
+ flags |= 0x20; /* RO_EXCEPTION */
+
+ if (CLASS_NST_METHODS (impent->imp_context))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ inst_methods =
+ generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
+ buf, meta_clai_meth);
+ }
+
+ /* Sort out the ivars before we try to compute the class sizes. */
+ if ((chain = CLASS_IVARS (impent->imp_template)))
+ {
+ snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
+ IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
+ inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
+ impent->imp_template);
+ }
+
+ /* Compute instanceStart */
+ gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
+ field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
+ if (my_super_id && field && TREE_CHAIN (field))
+ field = TREE_CHAIN (field);
+
+ firstIvar = field;
+
+ while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
+ firstIvar = TREE_CHAIN (firstIvar);
+
+ gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
+
+ /* Compute instanceSize */
+ while (field && TREE_CHAIN (field)
+ && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
+ field = TREE_CHAIN (field);
+
+ if (field && TREE_CODE (field) == FIELD_DECL)
+ instanceSize = int_byte_position (field) * BITS_PER_UNIT
+ + tree_low_cst (DECL_SIZE (field), 0);
+ else
+ instanceSize = 0;
+ instanceSize /= BITS_PER_UNIT;
+
+ props = generate_v2_property_table (NULL_TREE, impent->imp_context);
+
+ /* If the class has no ivars, instanceStart should be set to the superclass's
+ instanceSize */
+ instanceStart =
+ (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
+ : instanceSize;
+
+ /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
+ decl = start_var_decl (objc_v2_class_ro_template,
+ newabi_append_ro (IDENTIFIER_POINTER
+ (DECL_NAME (class_decl))));
+
+ initlist =
+ build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
+ (flags | cls_flags), instanceStart,
+ instanceSize, ivarLayout,
+ inst_methods, protocol_decl,
+ inst_ivars, props);
+ /* The ROs sit in the default const section. */
+ OBJCMETA (decl, objc_meta, meta_base);
+ finish_var_decl (decl, initlist);
+
+ /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
+ initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
+ build_fold_addr_expr (metaclass_decl),
+ class_superclass_expr,
+ build_fold_addr_expr (decl),
+ build_fold_addr_expr (UOBJC_V2_CACHE_decl),
+ build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
+
+ /* The class section attributes are set when they are created. */
+ finish_var_decl (class_decl, initlist);
+ impent->class_decl = class_decl;
+
+ objc_v2_add_to_class_list (class_decl);
+ if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
+ objc_v2_add_to_nonlazy_class_list (class_decl);
+
+ if (flags & 0x20) /* RO_EXCEPTION */
+ objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
+}
+
+/* This routine outputs the (ivar_reference_offset, offset) tuples. */
+
+static void
+build_v2_ivar_offset_ref_table (void)
+{
+ int count;
+ ivarref_entry *ref;
+
+ if (!ivar_offset_refs || !VEC_length (ivarref_entry, ivar_offset_refs))
+ return;
+
+ FOR_EACH_VEC_ELT (ivarref_entry, ivar_offset_refs, count, ref)
+ finish_var_decl (ref->decl, ref->offset);
+}
+
+/* static int _OBJC_IMAGE_INFO[2] = { 0, 16 | flags }; */
+
+static void
+generate_v2_objc_image_info (void)
+{
+ tree decl, array_type;
+ VEC(constructor_elt,gc) *v = NULL;
+ int flags =
+ ((flag_replace_objc_classes && imp_count ? 1 : 0)
+ | (flag_objc_gc ? 2 : 0));
+
+ flags |= 16;
+
+ array_type = build_sized_array_type (integer_type_node, 2);
+
+ decl = start_var_decl (array_type, "_OBJC_ImageInfo");
+
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags));
+ /* The Runtime wants this. */
+ DECL_PRESERVE_P (decl) = 1;
+ OBJCMETA (decl, objc_meta, meta_info);
+ finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v));
+}
+
+static void
+objc_generate_v2_next_metadata (void)
+{
+ struct imp_entry *impent;
+
+ gcc_assert (!objc_static_instances); /* Not for NeXT */
+
+ build_metadata_templates ();
+
+ for (impent = imp_list; impent; impent = impent->next)
+ {
+ /* If -gen-decls is present, Dump the @interface of each class.
+ TODO: Dump the classes in the order they were found, rather than in
+ reverse order as we are doing now. */
+ if (flag_gen_declaration)
+ dump_interface (gen_declaration_file, impent->imp_context);
+
+ /* all of the following reference the string pool... */
+ if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
+ generate_v2_class_structs (impent);
+ else
+ generate_v2_category (impent);
+ }
+
+ build_next_selector_translation_table ();
+ build_v2_message_ref_translation_table ();
+
+ /* This will add "Protocol" to the class refs. */
+ generate_v2_protocols ();
+
+ build_v2_classrefs_table ();
+ build_v2_super_classrefs_table (/*metaclass= */false);
+ build_v2_super_classrefs_table (/*metaclass= */true);
+
+ build_v2_ivar_offset_ref_table ();
+
+ build_v2_protocol_list_translation_table ();
+ build_v2_protocol_list_address_table ();
+
+ build_v2_address_table (class_list, "_OBJC_ClassList$",
+ meta_label_classlist);
+ build_v2_address_table (category_list, "_OBJC_CategoryList$",
+ meta_label_categorylist);
+ build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
+ meta_label_nonlazy_classlist);
+ build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
+ meta_label_nonlazy_categorylist);
+
+ /* This conveys information on GC usage and zero-link. */
+ generate_v2_objc_image_info ();
+
+ /* Generate catch objects for eh, if any are needed. */
+ build_v2_eh_catch_objects ();
+
+ /* Emit the string table last. */
+ generate_strings ();
+}
+
+/* NOTE --- Output NeXT V2 Exceptions --- */
+
+static GTY(()) tree objc_v2_ehtype_template;
+static GTY(()) tree next_v2_ehvtable_decl;
+static GTY(()) tree next_v2_EHTYPE_id_decl;
+
+static void
+build_v2_ehtype_template (void)
+{
+ tree decls, *chain = NULL;
+ objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
+
+ /* void *_objc_ehtype_vtable; */
+ decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
+
+ /* const char *className; */
+ add_field_decl (string_type_node, "className", &chain);
+
+ /* struct class_t *const cls; */
+ add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
+
+ objc_finish_struct (objc_v2_ehtype_template, decls);
+}
+
+/* Template for the Objective-C family typeinfo type for ABI=2.
+ This starts off the same as the gxx/cxx eh typeinfo.
+
+ struct _objc_ehtype_t {
+ void *_objc_ehtype_vtable_ptr; - as per c++
+ const char *className; - as per c++
+ struct class_t *const cls;
+ }
+*/
+
+/* This routine builds initializer list for object of type struct _objc_ehtype_t.
+*/
+
+static tree
+objc2_build_ehtype_initializer (tree name, tree cls)
+{
+ VEC(constructor_elt,gc) *initlist = NULL;
+ tree addr, offs;
+
+ /* This is done the same way as c++, missing the two first entries in the
+ parent vtable. NOTE: there is a fix-me in the Apple/NeXT runtime source
+ about this so, perhaps, this will change at some point. */
+ /* _objc_ehtype_vtable + 2*sizeof(void*) */
+ if (!next_v2_ehvtable_decl)
+ {
+ next_v2_ehvtable_decl =
+ start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
+ TREE_STATIC (next_v2_ehvtable_decl) = 0;
+ DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
+ TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
+ }
+ addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
+ offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
+ addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, offs);
+
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
+
+ /* className */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
+
+ /* cls */
+ CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
+
+ return objc_build_constructor (objc_v2_ehtype_template, initlist);
+}
+
+static tree
+build_ehtype (tree name, const char *eh_name, bool weak)
+{
+ tree name_expr, class_name_expr, ehtype_decl, inits;
+
+ name_expr = add_objc_string (name, class_names);
+ /* Extern ref. for the class. ??? maybe we can look this up somewhere. */
+ class_name_expr =
+ create_extern_decl (objc_v2_class_template,
+ objc_build_internal_classname (name, false));
+ class_name_expr = build_fold_addr_expr (class_name_expr);
+ ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
+ if (weak)
+ DECL_WEAK (ehtype_decl) = 1;
+ inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
+ OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
+ finish_var_decl (ehtype_decl, inits);
+ return ehtype_decl;
+}
+
+/* This routine returns TRUE if CLS or any of its super classes has
+ __attribute__ ((objc_exception)).
+*/
+
+static bool
+objc2_objc_exception_attr (tree cls)
+{
+ while (cls)
+ {
+ if (CLASS_HAS_EXCEPTION_ATTR (cls))
+ return true;
+ cls = lookup_interface (CLASS_SUPER_NAME (cls));
+ }
+
+ return false;
+}
+
+static bool
+is_implemented (tree name)
+{
+ struct imp_entry *t;
+ for (t = imp_list; t; t = t->next)
+ if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
+ && CLASS_NAME (t->imp_template) == name)
+ return true;
+
+ return false;
+}
+
+/* We will build catch objects:
+ for any type implemented here.
+ for any type used in a catch that has no exception attribute. */
+static void build_v2_eh_catch_objects (void)
+{
+ int count=0;
+ ident_data_tuple *ref;
+
+ if (!ehtype_list || !VEC_length (ident_data_tuple, ehtype_list))
+ return;
+
+ FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
+ {
+ char buf[BUFSIZE];
+ bool impl = is_implemented (ref->ident);
+ bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
+ snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
+ if (!impl && excpt)
+ /* The User says this class has a catcher already. */
+ ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
+ else
+ /* Create a catcher, weak if it wasn't marked. */
+ ref->data = build_ehtype (ref->ident, buf, !excpt);
+ }
+}
+
+static tree
+lookup_ehtype_ref (tree id)
+{
+ int count=0;
+ ident_data_tuple *ref;
+
+ if (!ehtype_list || !VEC_length (ident_data_tuple, ehtype_list))
+ return NULL_TREE;
+
+ FOR_EACH_VEC_ELT (ident_data_tuple, ehtype_list, count, ref)
+ if (ref->ident == id)
+ return ref->data;
+ return NULL_TREE;
+}
+
+/* This hook, called via lang_eh_runtime_type, generates a runtime object
+ which is either the address of the 'OBJC_EHTYPE_$_class' object or
+ address of external OBJC_EHTYPE_id object.
+*/
+static tree
+next_runtime_02_eh_type (tree type)
+{
+ tree t;
+
+ if (type == error_mark_node
+ /*|| errorcount || sorrycount*/)
+ goto err_mark_in;
+
+ if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
+ {
+ if (!next_v2_EHTYPE_id_decl)
+ {
+ /* This is provided by the Apple/NeXT libobjc.dylib so we need
+ only to reference it. */
+ next_v2_EHTYPE_id_decl =
+ start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
+ DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
+ TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
+ TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
+ }
+ return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
+ }
+
+ if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
+ {
+#ifdef OBJCPLUS
+ /* This routine is also called for c++'s catch clause; in which case,
+ we use c++'s typeinfo decl. */
+ return build_eh_type_type (type);
+#else
+ error ("non-objective-c type '%T' cannot be caught", type);
+ goto err_mark_in;
+#endif
+ }
+ else
+ t = OBJC_TYPE_NAME (TREE_TYPE (type));
+
+ /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
+ t = lookup_ehtype_ref (t);
+ if (!t)
+ goto err_mark_in;
+
+ return build_fold_addr_expr (t);
+
+err_mark_in:
+ return error_mark_node;
+}
+
+static GTY(()) tree objc_eh_personality_decl;
+
+static tree
+objc_eh_personality (void)
+{
+ if (!objc_eh_personality_decl)
+ objc_eh_personality_decl = build_personality_function ("objc");
+ return objc_eh_personality_decl;
+}
+
+/* NOTE --- interfaces --- */
+
+static tree
+build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
+{
+ tree t;
+ if (rethrown)
+ /* We have a separate re-throw entry. */
+ t = build_function_call_vec (loc, objc_rethrow_exception_decl, NULL, NULL);
+ else
+ {
+ /* Throw like the others .. */
+ VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
+ VEC_quick_push (tree, parms, throw_expr);
+ t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
+ VEC_free (tree, gc, parms);
+ }
+ return add_stmt (t);
+}
+
+/* Build __builtin_eh_pointer. */
+
+static tree
+objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
+{
+ tree t;
+ t = built_in_decls[BUILT_IN_EH_POINTER];
+ t = build_call_expr (t, 1, integer_zero_node);
+ return fold_convert (objc_object_type, t);
+}
+
+static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
+ tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
+{
+ tree t;
+
+ /* Record the data for the catch in the try context so that we can
+ finalize it later. Ellipsis is signalled by a NULL entry. */
+ if (ellipsis)
+ t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
+ else
+ t = build_stmt (input_location, CATCH_EXPR, type, compound);
+ (*cur_try_context)->current_catch = t;
+
+ /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
+ t = objc_build_exc_ptr (cur_try_context);
+ t = convert (TREE_TYPE (decl), t);
+ /* TODO location stuff. */
+ if (type && type != error_mark_node)
+ {
+ t = build1(NOP_EXPR, ptr_type_node, t);
+ t = build_function_call (input_location, objc2_begin_catch_decl,
+ tree_cons (NULL_TREE, t, NULL_TREE));
+
+ /* We might want to build a catch object for this (if it's not id). */
+ if (POINTER_TYPE_P (type)
+ && !objc_is_object_id (TREE_TYPE (type))
+ && TYPED_OBJECT (TREE_TYPE (type)))
+ objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
+ }
+ return build2 (MODIFY_EXPR, void_type_node, decl, t);
+}
+
+/* try { catch-body } finally { objc_end_catch (); } */
+static void
+finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
+{
+ struct objc_try_context *ct;
+ tree try_exp, func, *l, t ;
+ location_t loc = (*cur_try_context)->try_locus;
+
+ if (!curr_catch || curr_catch == error_mark_node)
+ return;
+
+ t = CATCH_BODY (curr_catch);
+ if (TREE_CODE (t) == BIND_EXPR)
+ {
+ /* usual case of @catch (objc-expr). */
+ objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
+ BIND_EXPR_BODY (t) = NULL_TREE;
+ l = &BIND_EXPR_BODY (t);
+ }
+ else
+ {
+ /* NULL entry, @catch (...) */
+ objc_begin_try_stmt (loc, t);
+ CATCH_BODY (curr_catch) = NULL_TREE;
+ l = &CATCH_BODY (curr_catch);
+ }
+
+ /* Pick up the new context we made in begin_try above.. */
+ ct = *cur_try_context;
+ func = build_function_call_vec (loc, objc2_end_catch_decl, NULL, NULL);
+ append_to_statement_list (func, &ct->finally_body);
+ try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
+ *cur_try_context = ct->outer;
+ free (ct);
+ append_to_statement_list (try_exp, l);
+ append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
+}
+
+static tree
+finish_try_stmt (struct objc_try_context **cur_try_context)
+{
+ struct objc_try_context *c = *cur_try_context;
+ tree stmt = c->try_body;
+ if (c->catch_list)
+ stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
+ if (c->finally_body)
+ stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
+ return stmt;
+}
+
+#include "gt-objc-objc-next-runtime-abi-02.h"
diff --git a/gcc/objc/objc-runtime-hooks.h b/gcc/objc/objc-runtime-hooks.h
new file mode 100644
index 0000000..d071c8b
--- /dev/null
+++ b/gcc/objc/objc-runtime-hooks.h
@@ -0,0 +1,108 @@
+/* Hooks to abstract the runtime meta-data generation for Objective C.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Iain Sandoe
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _OBJC_RUNTIME_HOOKS_H_
+#define _OBJC_RUNTIME_HOOKS_H_
+
+/* A set of hooks for the front end to obtain runtime-specific actions. */
+
+/* Objective-C supports several runtime library variants:
+
+ "GNU" runtime selected by -fgnu-runtime (currently at API version 1).
+ "NeXT" runtime (selected by -fnext-runtime) and installed on OSX/Darwin
+ systems at API version 1 (for m32 code) and version 2 (for m64 code).
+
+ The runtimes require different data types/layouts, method call mechanisms
+ and so on, and the purpose of this interface is to abstract such
+ differences from the parser's perspective. */
+
+typedef struct _objc_runtime_hooks_r
+{
+ /* Initialize for this runtime. */
+ void (*initialize) (void);
+ const char *default_constant_string_class_name;
+
+ /* FIXME: Having to check this name should not be necessary. */
+ const char *tag_getclass;
+ /* id for superclass class field - named differently in the existing
+ runtimes. */
+ tree (*super_superclassfield_ident) (void);
+
+ /* Obtain a class decl for the identifier. */
+ tree (*class_decl) (tree);
+ /* Obtain a metaclass decl for the identifier. */
+ tree (*metaclass_decl) (tree);
+ /* Obtain a category decl for the identifier. */
+ tree (*category_decl) (tree);
+ /* Obtain a protocol decl for the identifier. */
+ tree (*protocol_decl) (tree);
+ /* Obtain a string decl, to be placed in the nominated string-section. */
+ tree (*string_decl) (tree, const char *, string_section);
+
+ /* Obtain a class reference, generating the fwd def. if necessary. */
+ tree (*get_class_reference) (tree);
+ /* build/get selector reference. */
+ tree (*build_selector_reference) (location_t, tree, tree);
+ /* Get a protocol reference, generating the forward def. if necessary. */
+ tree (*get_protocol_reference) (location_t, tree);
+ /* Get an ivar ref. re the base. */
+ tree (*build_ivar_reference) (location_t, tree, tree);
+ /* Get a reference to {meta}class' super. */
+ tree (*get_class_super_ref) (location_t, struct imp_entry *, bool);
+ /* Get a reference to Category {meta}class' super. */
+ tree (*get_category_super_ref) (location_t, struct imp_entry *, bool);
+
+ /* Receiver is class Object, check runtime-specific. */
+ tree (*receiver_is_class_object) (tree);
+ /* Get the start of a method argument type list (receiver, _cmd). */
+ tree (*get_arg_type_list_base) (tree, int, int);
+ /* Build method call. */
+ tree (*build_objc_method_call) (location_t, tree, tree, tree, tree, tree, int);
+
+ /* Check for or otherwise handle a request to check that the constant
+ string class reference is set-up & OK. */
+ bool (*setup_const_string_class_decl) (void);
+ /* Return the tree reprenting a const string constructor for the arg.
+ Most of the data are in global trees. */
+ tree (*build_const_string_constructor) (location_t, tree, int);
+
+ /* Exceptions. */
+ tree (*build_throw_stmt) (location_t, tree, bool);
+ tree (*build_exc_ptr) (struct objc_try_context **);
+ tree (*begin_catch) (struct objc_try_context **, tree, tree, tree, bool);
+ void (*finish_catch) (struct objc_try_context **, tree);
+ tree (*finish_try_stmt) (struct objc_try_context **);
+
+ /* Emit all the metadata required by the runtime - based on the tables built
+ during parsing. */
+ void (*generate_metadata) (void);
+
+} objc_runtime_hooks;
+
+/* For shared support that needs to access these. */
+extern objc_runtime_hooks runtime;
+
+/* One per runtime at present.
+ TODO: Make into some kind of configury-generated table. */
+extern bool objc_gnu_runtime_abi_01_init (objc_runtime_hooks *);
+extern bool objc_next_runtime_abi_01_init (objc_runtime_hooks *);
+extern bool objc_next_runtime_abi_02_init (objc_runtime_hooks *);
+
+#endif /* _OBJC_RUNTIME_HOOKS_H_ */
diff --git a/gcc/objc/objc-runtime-shared-support.c b/gcc/objc/objc-runtime-shared-support.c
new file mode 100644
index 0000000..dff1d46
--- /dev/null
+++ b/gcc/objc/objc-runtime-shared-support.c
@@ -0,0 +1,733 @@
+/* Support routines shared by all runtimes.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Iain Sandoe (partially split from objc-act.c)
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+
+#ifdef OBJCPLUS
+#include "cp-tree.h"
+#else
+#include "c-tree.h"
+#include "c-lang.h"
+#endif
+#include "langhooks.h"
+#include "c-family/c-objc.h"
+#include "objc-act.h"
+
+/* When building Objective-C++, we are not linking against the C front-end
+ and so need to replicate the C tree-construction functions in some way. */
+#ifdef OBJCPLUS
+#define OBJCP_REMAP_FUNCTIONS
+#include "objcp-decl.h"
+#endif /* OBJCPLUS */
+
+#include "obstack.h"
+
+/* These are only used for encoding ivars. */
+extern struct obstack util_obstack;
+extern char *util_firstobj;
+
+/* Hooks for string decls etc. */
+#include "objc-runtime-hooks.h"
+
+#include "objc-runtime-shared-support.h"
+
+/* rt_trees identifiers - shared between NeXT implementations. These allow
+ the FE to tag meta-data in a manner that survives LTO and can be used when
+ the runtime requires that certain meta-data items appear in particular
+ named sections. */
+#include "objc-next-metadata-tags.h"
+extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
+
+/* Rather than repeatedly looking up the identifiers, we save them here. */
+tree objc_rt_trees[OCTI_RT_META_MAX];
+
+/* For building an objc struct. These might not be used when this file
+ is compiled as part of obj-c++. */
+
+static bool objc_building_struct;
+static struct c_struct_parse_info *objc_struct_info ATTRIBUTE_UNUSED;
+
+/* Start building a struct for objc. */
+
+tree
+objc_start_struct (tree name)
+{
+ gcc_assert (!objc_building_struct);
+ objc_building_struct = true;
+ return start_struct (input_location, RECORD_TYPE, name, &objc_struct_info);
+}
+
+/* Finish building a struct for objc. */
+
+tree
+objc_finish_struct (tree type, tree fieldlist)
+{
+ gcc_assert (objc_building_struct);
+ objc_building_struct = false;
+ return finish_struct (input_location, type, fieldlist, NULL_TREE,
+ objc_struct_info);
+}
+
+tree
+build_sized_array_type (tree base_type, int size)
+{
+ tree index_type = build_index_type (build_int_cst (NULL_TREE, size - 1));
+ return build_array_type (base_type, index_type);
+}
+
+/* Create a declaration for field NAME of a given TYPE. */
+
+static tree
+create_field_decl (tree type, const char *name)
+{
+ return build_decl (input_location,
+ FIELD_DECL, get_identifier (name), type);
+}
+
+tree
+add_field_decl (tree type, const char *name, tree **chain)
+{
+ tree field = create_field_decl (type, name);
+
+ if (*chain != NULL)
+ **chain = field;
+ *chain = &DECL_CHAIN (field);
+
+ return field;
+}
+
+/* Create a global, static declaration for variable NAME of a given TYPE. The
+ finish_var_decl() routine will need to be called on it afterwards. */
+
+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;
+ DECL_INITIAL (var) = error_mark_node; /* A real initializer is coming... */
+ DECL_IGNORED_P (var) = 1;
+ DECL_ARTIFICIAL (var) = 1;
+ DECL_CONTEXT (var) = NULL_TREE;
+#ifdef OBJCPLUS
+ DECL_THIS_STATIC (var) = 1; /* squash redeclaration errors */
+#endif
+ return var;
+}
+
+/* Finish off the variable declaration created by start_var_decl(). */
+
+void
+finish_var_decl (tree var, tree initializer)
+{
+ finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE);
+}
+
+/* Just a handy wrapper for add_objc_string. */
+
+tree
+build_selector (tree ident)
+{
+ return convert (objc_selector_type, add_objc_string (ident, meth_var_names));
+}
+
+/* --- templates --- */
+
+/* Set 'objc_super_template' to the data type node for 'struct _objc_super'.
+ This needs to be done just once per compilation. */
+
+/* struct _objc_super {
+ struct _objc_object *self;
+ struct _objc_class *super_class;
+ [or Class cls; for the abi v2]
+ }; */
+
+void
+build_super_template (void)
+{
+ tree decls, *chain = NULL;
+
+ objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
+
+ /* struct _objc_object *self; */
+ decls = add_field_decl (objc_object_type, "self", &chain);
+
+ /* struct _objc_class *super_class; */
+ add_field_decl (build_pointer_type (objc_class_template),
+ "super_class", &chain);
+
+ objc_finish_struct (objc_super_template, decls);
+}
+
+/* To accomplish method prototyping without generating all kinds of
+ inane warnings, the definition of the dispatch table entries were
+ changed from:
+
+ struct objc_method { SEL _cmd; ...; id (*_imp)(); };
+ to:
+ struct objc_method { SEL _cmd; ...; void *_imp; }; */
+
+tree
+build_method_template (void)
+{
+ tree _SLT_record;
+ tree decls, *chain = NULL;
+
+ _SLT_record = objc_start_struct (get_identifier (UTAG_METHOD));
+
+ /* SEL _cmd; */
+ decls = add_field_decl (objc_selector_type, "_cmd", &chain);
+
+ /* char *method_types; */
+ add_field_decl (string_type_node, "method_types", &chain);
+
+ /* void *_imp; */
+ add_field_decl (build_pointer_type (void_type_node), "_imp", &chain);
+
+ objc_finish_struct (_SLT_record, decls);
+
+ return _SLT_record;
+}
+
+tree
+build_method_prototype_template (void)
+{
+ tree proto_record;
+ tree decls, *chain = NULL;
+
+ proto_record = objc_start_struct (get_identifier (UTAG_METHOD_PROTOTYPE));
+
+ /* SEL _cmd; */
+ decls = add_field_decl (objc_selector_type, "_cmd", &chain);
+
+ /* char *method_types; */
+ add_field_decl (string_type_node, "method_types", &chain);
+
+ objc_finish_struct (proto_record, decls);
+
+ return proto_record;
+}
+
+/* struct {
+ struct _objc__method_prototype_list *method_next;
+ int method_count;
+ struct objc_method method_list[method_count];
+ }; */
+
+tree
+build_method_list_template (tree list_type, int size)
+{
+ tree objc_ivar_list_record;
+ tree array_type, decls, *chain = NULL;
+
+ objc_ivar_list_record = objc_start_struct (NULL_TREE);
+
+ /* struct _objc__method_prototype_list *method_next; */
+ decls = add_field_decl (objc_method_proto_list_ptr, "method_next", &chain);
+
+ /* int method_count; */
+ add_field_decl (integer_type_node, "method_count", &chain);
+
+ /* struct objc_method method_list[]; */
+ array_type = build_sized_array_type (list_type, size);
+ add_field_decl (array_type, "method_list", &chain);
+
+ objc_finish_struct (objc_ivar_list_record, decls);
+
+ return objc_ivar_list_record;
+}
+
+/* struct objc_method_prototype_list {
+ int count;
+ struct objc_method_prototype {
+ SEL name;
+ char *types;
+ } list[1];
+ }; */
+
+tree
+build_method_prototype_list_template (tree list_type, int size)
+{
+ tree objc_ivar_list_record;
+ tree array_type, decls, *chain = NULL;
+
+ /* Generate an unnamed struct definition. */
+
+ objc_ivar_list_record = objc_start_struct (NULL_TREE);
+
+ /* int method_count; */
+ decls = add_field_decl (integer_type_node, "method_count", &chain);
+
+ /* struct objc_method method_list[]; */
+ array_type = build_sized_array_type (list_type, size);
+ add_field_decl (array_type, "method_list", &chain);
+
+ objc_finish_struct (objc_ivar_list_record, decls);
+
+ return objc_ivar_list_record;
+}
+
+/* --- names, decls entry --- */
+
+/* For each string section we have a chain which maps identifier nodes
+ to decls for the strings. */
+
+static GTY(()) int meth_var_names_idx;
+static GTY(()) int meth_var_types_idx;
+static GTY(()) int property_name_attr_idx;
+
+tree
+add_objc_string (tree ident, string_section section)
+{
+ tree *chain, decl, type;
+ char buf[BUFSIZE];
+
+ switch (section)
+ {
+ case class_names:
+ chain = &class_names_chain;
+ snprintf (buf, BUFSIZE, "_OBJC_ClassName_%s", IDENTIFIER_POINTER (ident));
+ break;
+ case meth_var_names:
+ chain = &meth_var_names_chain;
+ snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
+ break;
+ case meth_var_types:
+ chain = &meth_var_types_chain;
+ snprintf (buf, BUFSIZE, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
+ break;
+ case prop_names_attr:
+ chain = &prop_names_attr_chain;
+ snprintf (buf, BUFSIZE, "_OBJC_PropertyAttributeOrName_%d", property_name_attr_idx++);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ while (*chain)
+ {
+ if (TREE_VALUE (*chain) == ident)
+ return convert (string_type_node,
+ build_unary_op (input_location,
+ ADDR_EXPR, TREE_PURPOSE (*chain), 1));
+
+ chain = &TREE_CHAIN (*chain);
+ }
+
+ type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1);
+ /* Get a runtime-specific string decl which will be finish_var()'ed in
+ generate_strings (). */
+ decl = (*runtime.string_decl) (type, buf, section);
+ TREE_CONSTANT (decl) = 1;
+ *chain = tree_cons (decl, ident, NULL_TREE);
+
+ return convert (string_type_node,
+ build_unary_op (input_location, ADDR_EXPR, decl, 1));
+}
+
+/* --- shared metadata routines --- */
+
+tree
+build_descriptor_table_initializer (tree type, tree entries)
+{
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ do
+ {
+ VEC(constructor_elt,gc) *elts = NULL;
+
+ CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
+ build_selector (METHOD_SEL_NAME (entries)));
+ CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,
+ add_objc_string (METHOD_ENCODING (entries),
+ meth_var_types));
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ objc_build_constructor (type, elts));
+
+ entries = DECL_CHAIN (entries);
+ }
+ while (entries);
+
+ return objc_build_constructor (build_array_type (type, 0), inits);
+}
+
+tree
+build_dispatch_table_initializer (tree type, tree entries)
+{
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ do
+ {
+ VEC(constructor_elt,gc) *elems = NULL;
+ tree expr;
+
+ CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
+ build_selector (METHOD_SEL_NAME (entries)));
+
+ /* Generate the method encoding if we don't have one already. */
+ if (! METHOD_ENCODING (entries))
+ METHOD_ENCODING (entries) =
+ encode_method_prototype (entries);
+
+ CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE,
+ add_objc_string (METHOD_ENCODING (entries),
+ meth_var_types));
+
+ expr = convert (ptr_type_node,
+ build_unary_op (input_location, ADDR_EXPR,
+ METHOD_DEFINITION (entries), 1));
+ CONSTRUCTOR_APPEND_ELT (elems, NULL_TREE, expr);
+
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ objc_build_constructor (type, elems));
+
+ entries = DECL_CHAIN (entries);
+ }
+ while (entries);
+
+ return objc_build_constructor (build_array_type (type, 0), inits);
+}
+
+/* Used only by build_*_selector_translation_table (). */
+void
+diagnose_missing_method (tree meth, location_t here)
+{
+ tree method_chain;
+ bool found = false;
+ for (method_chain = meth_var_names_chain;
+ method_chain;
+ method_chain = TREE_CHAIN (method_chain))
+ {
+ if (TREE_VALUE (method_chain) == meth)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ warning_at (here, 0, "creating selector for nonexistent method %qE",
+ meth);
+}
+
+
+static tree
+init_module_descriptor (tree type, long vers)
+{
+ tree expr, ltyp;
+ location_t loc;
+ VEC(constructor_elt,gc) *v = NULL;
+
+ /* No really useful place to point to. */
+ loc = UNKNOWN_LOCATION;
+
+ /* version = { 1, ... } */
+
+ expr = build_int_cst (long_integer_type_node, vers);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* size = { ..., sizeof (struct _objc_module), ... } */
+
+ expr = convert (long_integer_type_node,
+ size_in_bytes (objc_module_template));
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* Don't provide any file name for security reasons. */
+ /* name = { ..., "", ... } */
+
+ expr = add_objc_string (get_identifier (""), class_names);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ /* symtab = { ..., _OBJC_SYMBOLS, ... } */
+
+ ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_SYMTAB)));
+ if (UOBJC_SYMBOLS_decl)
+ expr = convert (ltyp, build_unary_op (loc,
+ ADDR_EXPR, UOBJC_SYMBOLS_decl, 0));
+ else
+ expr = convert (ltyp, null_pointer_node);
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
+
+ return objc_build_constructor (type, v);
+}
+
+/* Write out the data structures to describe Objective C classes defined.
+
+ struct _objc_module { ... } _OBJC_MODULE = { ... }; */
+
+void
+build_module_descriptor (long vers, tree attr)
+{
+ tree decls, *chain = NULL;
+
+#ifdef OBJCPLUS
+ push_lang_context (lang_name_c); /* extern "C" */
+#endif
+
+ objc_module_template = objc_start_struct (get_identifier (UTAG_MODULE));
+
+ /* long version; */
+ decls = add_field_decl (long_integer_type_node, "version", &chain);
+
+ /* long size; */
+ add_field_decl (long_integer_type_node, "size", &chain);
+
+ /* char *name; */
+ add_field_decl (string_type_node, "name", &chain);
+
+ /* struct _objc_symtab *symtab; */
+ add_field_decl (build_pointer_type (xref_tag (RECORD_TYPE,
+ get_identifier (UTAG_SYMTAB))),
+ "symtab", &chain);
+
+ objc_finish_struct (objc_module_template, decls);
+
+ /* Create an instance of "_objc_module". */
+ UOBJC_MODULES_decl = start_var_decl (objc_module_template,
+ flag_next_runtime ? "_OBJC_Module" : "_OBJC_Module");
+
+ /* This is the root of the metadata for defined classes and categories, it
+ is referenced by the runtime and, therefore, needed. */
+ DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1;
+
+ /* Allow the runtime to mark meta-data such that it can be assigned to target
+ specific sections by the back-end. */
+ if (attr)
+ DECL_ATTRIBUTES (UOBJC_MODULES_decl) = attr;
+
+ finish_var_decl (UOBJC_MODULES_decl,
+ init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl),
+ vers));
+
+#ifdef OBJCPLUS
+ pop_lang_context ();
+#endif
+}
+
+tree
+build_ivar_list_initializer (tree type, tree field_decl)
+{
+ VEC(constructor_elt,gc) *inits = NULL;
+
+ do
+ {
+ VEC(constructor_elt,gc) *ivar = NULL;
+ tree id;
+
+ /* Set name. */
+ if (DECL_NAME (field_decl))
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
+ add_objc_string (DECL_NAME (field_decl),
+ meth_var_names));
+ else
+ /* Unnamed bit-field ivar (yuck). */
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, build_int_cst (NULL_TREE, 0));
+
+ /* Set type. */
+ encode_field_decl (field_decl,
+ obstack_object_size (&util_obstack),
+ OBJC_ENCODE_DONT_INLINE_DEFS);
+
+ /* Null terminate string. */
+ obstack_1grow (&util_obstack, 0);
+ id = add_objc_string (get_identifier (XOBFINISH (&util_obstack, char *)),
+ meth_var_types);
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
+ obstack_free (&util_obstack, util_firstobj);
+
+ /* Set offset. */
+ CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, byte_position (field_decl));
+ CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
+ objc_build_constructor (type, ivar));
+ do
+ field_decl = DECL_CHAIN (field_decl);
+ while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
+ }
+ while (field_decl);
+
+ return objc_build_constructor (build_array_type (type, 0), inits);
+}
+
+/* struct {
+ int ivar_count;
+ struct objc_ivar ivar_list[ivar_count];
+ }; */
+
+tree
+build_ivar_list_template (tree list_type, int size)
+{
+ tree objc_ivar_list_record;
+ tree array_type, decls, *chain = NULL;
+
+ objc_ivar_list_record = objc_start_struct (NULL_TREE);
+
+ /* int ivar_count; */
+ decls = add_field_decl (integer_type_node, "ivar_count", &chain);
+
+ /* struct objc_ivar ivar_list[]; */
+ array_type = build_sized_array_type (list_type, size);
+ add_field_decl (array_type, "ivar_list", &chain);
+
+ objc_finish_struct (objc_ivar_list_record, decls);
+
+ return objc_ivar_list_record;
+}
+
+/* struct _objc_ivar {
+ char *ivar_name;
+ char *ivar_type;
+ int ivar_offset;
+ }; */
+
+tree
+build_ivar_template (void)
+{
+ tree objc_ivar_id, objc_ivar_record;
+ tree decls, *chain = NULL;
+
+ objc_ivar_id = get_identifier (UTAG_IVAR);
+ objc_ivar_record = objc_start_struct (objc_ivar_id);
+
+ /* char *ivar_name; */
+ decls = add_field_decl (string_type_node, "ivar_name", &chain);
+
+ /* char *ivar_type; */
+ add_field_decl (string_type_node, "ivar_type", &chain);
+
+ /* int ivar_offset; */
+ add_field_decl (integer_type_node, "ivar_offset", &chain);
+
+ objc_finish_struct (objc_ivar_record, decls);
+
+ return objc_ivar_record;
+}
+
+/* Used by NeXT ABI=0..2 */
+void
+build_next_selector_translation_table (void)
+{
+ tree chain;
+ for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
+ {
+ tree expr;
+ tree decl = TREE_PURPOSE (chain);
+ if (warn_selector)
+ {
+ location_t loc;
+ if (decl)
+ loc = DECL_SOURCE_LOCATION (decl);
+ else
+ loc = UNKNOWN_LOCATION;
+ diagnose_missing_method (TREE_VALUE (chain), loc);
+ }
+
+ expr = build_selector (TREE_VALUE (chain));
+
+ if (decl)
+ {
+ /* Entries of this form are used for references to methods.
+ The runtime re-writes these on start-up, but the compiler can't see
+ that and optimizes it away unless we force it. */
+ DECL_PRESERVE_P (decl) = 1;
+ finish_var_decl (decl, expr);
+ }
+ }
+}
+
+void
+generate_protocol_references (tree plist)
+{
+ tree lproto;
+
+ /* Forward declare protocols referenced. */
+ for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
+ {
+ tree proto = TREE_VALUE (lproto);
+
+ if (TREE_CODE (proto) == PROTOCOL_INTERFACE_TYPE
+ && PROTOCOL_NAME (proto))
+ {
+ if (! PROTOCOL_FORWARD_DECL (proto))
+ PROTOCOL_FORWARD_DECL (proto) = (*runtime.protocol_decl) (proto);
+
+ if (PROTOCOL_LIST (proto))
+ generate_protocol_references (PROTOCOL_LIST (proto));
+ }
+ }
+}
+
+/* --- new routines --- */
+
+/* Output all strings. */
+
+/* FIXME: don't use global vars for all this... */
+
+/* This emits all the meta-data string tables (and finalizes each var
+ as it goes). */
+void
+generate_strings (void)
+{
+ tree chain, string_expr;
+ tree string, decl; /* , type;*/
+
+ for (chain = class_names_chain; chain; chain = TREE_CHAIN (chain))
+ {
+ string = TREE_VALUE (chain);
+ decl = TREE_PURPOSE (chain);
+ string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
+ IDENTIFIER_POINTER (string));
+ finish_var_decl (decl, string_expr);
+ }
+
+ for (chain = meth_var_names_chain; chain; chain = TREE_CHAIN (chain))
+ {
+ string = TREE_VALUE (chain);
+ decl = TREE_PURPOSE (chain);
+ string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
+ IDENTIFIER_POINTER (string));
+ finish_var_decl (decl, string_expr);
+ }
+
+ for (chain = meth_var_types_chain; chain; chain = TREE_CHAIN (chain))
+ {
+ string = TREE_VALUE (chain);
+ decl = TREE_PURPOSE (chain);
+ string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
+ IDENTIFIER_POINTER (string));
+ finish_var_decl (decl, string_expr);
+ }
+
+ for (chain = prop_names_attr_chain; chain; chain = TREE_CHAIN (chain))
+ {
+ string = TREE_VALUE (chain);
+ decl = TREE_PURPOSE (chain);
+ string_expr = my_build_string (IDENTIFIER_LENGTH (string) + 1,
+ IDENTIFIER_POINTER (string));
+ finish_var_decl (decl, string_expr);
+ }
+}
+
+#include "gt-objc-objc-runtime-shared-support.h"
diff --git a/gcc/objc/objc-runtime-shared-support.h b/gcc/objc/objc-runtime-shared-support.h
new file mode 100644
index 0000000..8e4693d
--- /dev/null
+++ b/gcc/objc/objc-runtime-shared-support.h
@@ -0,0 +1,90 @@
+/* Support routines shared by all runtimes.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Iain Sandoe
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _OBJC_RUNTIME_SHARED_SUPPORT_H_
+#define _OBJC_RUNTIME_SHARED_SUPPORT_H_
+
+/* Left in obj-act.c for now... */
+
+extern tree objc_start_struct (tree);
+extern tree objc_finish_struct (tree, tree);
+extern tree add_field_decl (tree, const char *, tree **);
+extern tree build_sized_array_type (tree, int);
+
+extern tree lookup_interface (tree);
+extern tree objc_build_constructor (tree, VEC(constructor_elt,gc) *);
+
+extern tree start_var_decl (tree, const char *);
+extern void finish_var_decl (tree, tree);
+
+extern tree my_build_string (int, const char *);
+extern tree my_build_string_pointer (int, const char *);
+extern tree add_objc_string (tree ident, string_section);
+extern tree get_objc_string_decl (tree, string_section);
+
+extern void add_class_reference (tree);
+
+#ifdef OBJCPLUS
+extern void objc_start_function (tree, tree, tree, tree);
+extern tree objc_get_parm_info (int);
+#else
+extern void objc_start_function (tree, tree, tree, struct c_arg_info *);
+extern struct c_arg_info *objc_get_parm_info (int);
+#endif
+extern void objc_push_parm (tree);
+extern tree get_arg_type_list (tree, int, int);
+
+/* Stuff that should be migrated to shared support (or some v1-only file). */
+extern void build_super_template (void);
+
+extern tree objc_build_component_ref (tree, tree);
+
+extern tree objc_v2_encode_prop_attr (tree);
+extern tree build_descriptor_table_initializer (tree, tree);
+extern tree build_method_prototype_list_template (tree, int);
+extern tree build_protocol_initializer (tree, tree, tree, tree, tree);
+
+/* Stuff that should be migrated to shared encode. */
+extern tree encode_method_prototype (tree);
+extern void encode_field_decl (tree, int, int);
+
+/* Moved or new routines in objc-runtime-shared-support.c */
+
+extern tree build_selector (tree);
+extern tree build_method_template (void);
+extern tree build_method_prototype_template (void);
+extern tree build_method_list_template (tree, int);
+
+extern tree build_dispatch_table_initializer (tree, tree);
+extern void diagnose_missing_method (tree, location_t);
+extern void build_next_selector_translation_table (void);
+extern void generate_protocol_references (tree);
+extern void build_module_descriptor (long, tree);
+extern tree build_ivar_list_initializer (tree, tree);
+extern tree build_ivar_list_template (tree, int);
+extern tree build_ivar_template (void);
+
+extern void generate_strings (void);
+
+extern void dump_interface (FILE *, tree);
+extern int generating_instance_variables;
+extern FILE *gen_declaration_file;
+
+#endif /* _OBJC_RUNTIME_SHARED_SUPPORT_H_ */
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 83999f7..a327707 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,19 @@
+2011-02-17 Iain Sandoe <iains@gcc.gnu.org>
+
+ * Make-lang.in (START_HDRS): New.
+ (OBJCXX_OBJS): Added new object files from objc/.
+ (objcp/objcp-act.o): Updated prerequisites.
+ (objcp/objcp-lang.o): Updated prerequisites.
+ (objcp/objc-runtime-shared-support.o): New.
+ (objcp/objc-gnu-runtime-abi-01.o): New.
+ (objcp/objc-next-runtime-abi-01.o): New.
+ (objcp/objc-next-runtime-abi-02.o): New.
+ * config-lang.in (gtfiles): Updated.
+ * objcp-lang.c (objcxx_eh_personality): Removed.
+ (LANG_HOOKS_EH_PERSONALITY): Removed.
+ (LANG_HOOKS_EH_RUNTIME_TYPE): Removed.
+ (objcp_eh_personality_decl): Removed.
+
2011-02-07 Mike Stump <mikestump@comcast.net>
* Make-lang.in (obj-c++.tags): Don't include *.y.
diff --git a/gcc/objcp/Make-lang.in b/gcc/objcp/Make-lang.in
index 2122d2d..5bbd27e 100644
--- a/gcc/objcp/Make-lang.in
+++ b/gcc/objcp/Make-lang.in
@@ -1,5 +1,5 @@
# Top level -*- makefile -*- fragment for GNU Objective-C++
-# Copyright (C) 2005, 2007, 2008, 2009, 2010
+# Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
# Free Software Foundation, Inc.
# Contributed by Ziemowit Laski <zlaski@apple.com>
@@ -44,12 +44,19 @@ obj-c++: cc1objplus$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: obj-c++
+START_HDRS = $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) \
+ langhooks.h c-family/c-objc.h objc/objc-act.h
+
# Use maximal warnings for this front end. Also, make ObjC and C++
# headers accessible.
objcp-warn = $(STRICT_WARN) -DOBJCPLUS -I$(srcdir)/objc -I$(srcdir)/cp
# Language-specific object files for Objective C++.
OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.o objcp/objcp-decl.o \
+ objcp/objc-runtime-shared-support.o \
+ objcp/objc-gnu-runtime-abi-01.o \
+ objcp/objc-next-runtime-abi-01.o \
+ objcp/objc-next-runtime-abi-02.o \
$(CXX_AND_OBJCXX_OBJS)
obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o
@@ -69,23 +76,48 @@ cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBDEPS)
# Objective C++ language specific files.
-objcp/objcp-lang.o : objcp/objcp-lang.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) \
- $(C_COMMON_H) $(LANGHOOKS_DEF_H) objc/objc-act.h cp/cp-objcp-common.h \
- $(TARGET_H) gtype-objcp.h c-family/c-objc.h
+objcp/objcp-lang.o : objcp/objcp-lang.c $(START_HDRS) \
+ $(C_COMMON_H) $(LANGHOOKS_DEF_H) cp/cp-objcp-common.h \
+ $(TARGET_H) gtype-objcp.h
objcp/objcp-decl.o : objcp/objcp-decl.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) \
objc/objc-act.h objcp/objcp-decl.h c-family/c-objc.h
+objcp/objc-runtime-shared-support.o : objc/objc-runtime-shared-support.c \
+ $(START_HDRS) objc/objc-runtime-shared-support.h $(OBSTACK_H) \
+ objc/objc-next-metadata-tags.h gt-objc-objc-runtime-shared-support.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
+ $(OUTPUT_OPTION)
+
+objcp/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c $(START_HDRS) \
+ objc/objc-runtime-hooks.h $(GGC_H) \
+ gt-objc-objc-gnu-runtime-abi-01.h toplev.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
+ $(OUTPUT_OPTION)
+
+objcp/objc-next-runtime-abi-01.o: objc/objc-next-runtime-abi-01.c $(START_HDRS) \
+ $(GGC_H) objc/objc-runtime-hooks.h \
+ objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-01.h output.h \
+ objc/objc-runtime-shared-support.h $(TARGET_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
+ $(OUTPUT_OPTION)
+
+objcp/objc-next-runtime-abi-02.o: objc/objc-next-runtime-abi-02.c $(START_HDRS) \
+ $(GGC_H) objc/objc-runtime-hooks.h \
+ objc/objc-next-metadata-tags.h gt-objc-objc-next-runtime-abi-02.h $(TARGET_H) \
+ objc/objc-runtime-shared-support.h $(OBSTACK_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
+ $(OUTPUT_OPTION)
+
+
# The following must be an explicit rule; please keep in sync with the implicit
# one in Makefile.in.
-objcp/objcp-act.o : objc/objc-act.c \
- $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) $(TM_P_H) \
- $(EXPR_H) $(TARGET_H) $(CXX_TREE_H) $(DIAGNOSTIC_H) toplev.h $(FLAGS_H) \
- objc/objc-act.h input.h $(FUNCTION_H) output.h debug.h langhooks.h \
+objcp/objcp-act.o : objc/objc-act.c $(START_HDRS) $(GGC_H) \
+ $(RTL_H) $(EXPR_H) $(TARGET_H) $(DIAGNOSTIC_H) toplev.h $(FLAGS_H) \
+ input.h $(FUNCTION_H) output.h debug.h $(OBSTACK_H) \
objcp/objcp-decl.h $(LANGHOOKS_DEF_H) $(HASHTAB_H) gt-objc-objc-act.h \
- $(GIMPLE_H) c-family/c-objc.h
+ $(GIMPLE_H) objc/objc-runtime-hooks.h objc/objc-runtime-shared-support.h
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
$(OUTPUT_OPTION)
diff --git a/gcc/objcp/config-lang.in b/gcc/objcp/config-lang.in
index 962b9a8..b8565d8 100644
--- a/gcc/objcp/config-lang.in
+++ b/gcc/objcp/config-lang.in
@@ -1,5 +1,5 @@
# Top level configure fragment for GNU Objective-C++.
-# Copyright (C) 2005, 2007, 2010 Free Software Foundation, Inc.
+# Copyright (C) 2005, 2007, 2010, 2011 Free Software Foundation, Inc.
# Contributed by Ziemowit Laski <zlaski@apple.com>
#This file is part of GCC.
@@ -37,4 +37,4 @@ build_by_default="no"
lang_requires="objc c++"
subdir_requires="objc cp"
-gtfiles="\$(srcdir)/objcp/objcp-decl.c \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-act.h \$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/cp-objcp-common.c"
+gtfiles="\$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/cp/call.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/method.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-objcp-common.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/rtti.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c "
diff --git a/gcc/objcp/objcp-lang.c b/gcc/objcp/objcp-lang.c
index fa674aa..fe2be66 100644
--- a/gcc/objcp/objcp-lang.c
+++ b/gcc/objcp/objcp-lang.c
@@ -1,5 +1,5 @@
/* Language-dependent hooks for Objective-C++.
- Copyright 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
+ Copyright 2005, 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
Contributed by Ziemowit Laski <zlaski@apple.com>
This file is part of GCC.
@@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -35,7 +34,6 @@ along with GCC; see the file COPYING3. If not see
enum c_language_kind c_language = clk_objcxx;
static void objcxx_init_ts (void);
-static tree objcxx_eh_personality (void);
/* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h;
consequently, there should be very few hooks below. */
@@ -48,10 +46,6 @@ static tree objcxx_eh_personality (void);
#define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
#undef LANG_HOOKS_INIT_TS
#define LANG_HOOKS_INIT_TS objcxx_init_ts
-#undef LANG_HOOKS_EH_PERSONALITY
-#define LANG_HOOKS_EH_PERSONALITY objcxx_eh_personality
-#undef LANG_HOOKS_EH_RUNTIME_TYPE
-#define LANG_HOOKS_EH_RUNTIME_TYPE build_eh_type_type
/* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
@@ -145,14 +139,4 @@ objcxx_init_ts (void)
init_shadowed_var_for_decl ();
}
-static GTY(()) tree objcp_eh_personality_decl;
-
-static tree
-objcxx_eh_personality (void)
-{
- if (!objcp_eh_personality_decl)
- objcp_eh_personality_decl = build_personality_function ("gxx");
- return objcp_eh_personality_decl;
-}
-
#include "gtype-objcp.h"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4d6fae0..274da7e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,55 @@
+2011-02-17 Iain Sandoe <iains@gcc.gnu.org>
+
+ * objc.dg/special/unclaimed-category-1.h: Updated for
+ new ABI support.
+ * objc.dg/special/unclaimed-category-1.m: Same.
+ * objc.dg/zero-link-1.m: Same.
+ * objc.dg/lookup-1.m: Same.
+ * objc.dg/torture/strings/const-str-9.m
+ * objc.dg/torture/strings/const-str-10.m: Same.
+ * objc.dg/torture/strings/const-str-11.m: Same.
+ * objc.dg/torture/forward-1.m: Same.
+ * objc.dg/zero-link-2.m: Same.
+ * objc.dg/encode-7-next-64bit.m: Same.
+ * objc.dg/method-4.m: Same.
+ * objc.dg/next-runtime-1.m: Same.
+ * objc.dg/image-info.m: Same.
+ * objc.dg/pr23214.m: Same.
+ * objc.dg/symtab-1.m: Same.
+ * obj-c++.dg/basic.m: Same.m
+ * obj-c++.dg/proto-lossage-3.m: Same.m
+ * obj-c++.dg/torture/strings/const-str-10.m: Same.m
+ * obj-c++.dg/torture/strings/const-str-11.m: Same.m
+ * obj-c++.dg/torture/strings/const-str-9.m: Same.m
+ * obj-c++.dg/method-11.m: Same.m
+ * objc/execute/enumeration-1.m: Same.
+ * objc/execute/object_is_class.m: Same.
+ * objc/execute/formal_protocol-2.m: Same.
+ * objc/execute/formal_protocol-4.m: Same.
+ * objc/execute/formal_protocol-6.m: Same.
+ * objc/execute/bycopy-3.m: Same.
+ * objc/execute/exceptions/catchall-1.m: Same.
+ * objc/execute/exceptions/finally-1.m: Same.
+ * objc/execute/exceptions/local-variables-1.m: Same.
+ * objc/execute/exceptions/foward-1.m: Same.
+ * objc/execute/bf-common.h
+ * objc/execute/enumeration-2.m: Same.
+ * objc/execute/formal_protocol-1.m: Same.
+ * objc/execute/formal_protocol-3.m: Same.
+ * objc/execute/formal_protocol-5.m: Same.
+ * objc/execute/accessing_ivars.m: Same.
+ * objc/execute/bycopy-2.m: Same.
+ * objc/execute/formal_protocol-7.m: Same.
+ * objc/execute/compatibility_alias.m: Same.
+ * objc/execute/no_clash.m: Same.
+ * objc/execute/object_is_meta_class.m: Same.
+ * objc/execute/exceptions/exceptions.exp: Load target-supports.exp
+ * objc/execute/class-tests-1.h: Include stdio.h.
+ * objc/execute/class-tests-2.h: Same.
+ * obj-c++.dg/try-catch-9.mm: xfail-run the test with both
+ runtimes.
+ * obj-c++.dg/try-catch-2.mm: Same.
+
2011-02-17 Jakub Jelinek <jakub@redhat.com>
PR c++/47783
diff --git a/gcc/testsuite/obj-c++.dg/basic.mm b/gcc/testsuite/obj-c++.dg/basic.mm
index 8fb0204..bd593c1 100644
--- a/gcc/testsuite/obj-c++.dg/basic.mm
+++ b/gcc/testsuite/obj-c++.dg/basic.mm
@@ -1,22 +1,41 @@
// A basic sanity check for Objective-C++.
// { dg-do run }
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
-#include "../objc-obj-c++-shared/Object1.h"
+
+//#include "../objc-obj-c++-shared/Object1.h"
#include <iostream>
+#include <objc/Object.h>
+
+#ifdef __OBJC2__
+@interface Object (ADDITIONS)
++ initialize;
+- init;
++ alloc;
++ new;
+@end
+@implementation Object (ADDITIONS)
++ initialize { return self; }
+- init { return self; }
++ alloc { return class_createInstance (self, 0); }
++ new { return [[self alloc] init]; }
+@end
+#endif
+
@interface Greeter : Object
- (void) greet: (const char *)msg;
@end
@implementation Greeter
-- (void) greet: (const char *)msg { std::cout << msg; }
+- (void) greet: (const char *)msg
+{ std::cout << msg << __VERSION__ << std::endl;}
@end
int
main ()
{
- std::cout << "Hello from C++\n";
+ std::cout << "Hello from C++" << __VERSION__ << std::endl;
Greeter *obj = [Greeter new];
- [obj greet: "Hello from Objective-C\n"];
+ [obj greet: "Hello from Objective-C++"];
}
-#include "../objc-obj-c++-shared/Object1-implementation.h"
+//#include "../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/obj-c++.dg/method-11.mm b/gcc/testsuite/obj-c++.dg/method-11.mm
index 6c6b1a0..74192e8 100644
--- a/gcc/testsuite/obj-c++.dg/method-11.mm
+++ b/gcc/testsuite/obj-c++.dg/method-11.mm
@@ -22,5 +22,8 @@ void foo(void) {
obj = [ObjectAlias2 new];
}
-/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */
-/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_1" } } */
+/* { dg-final { scan-assembler "_OBJC_ClassRefs_0" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler "_OBJC_ClassRef_Object" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler-not "_OBJC_ClassRefs_1" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler-not "_OBJC_ClassRef_ObjectTypedef" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler-not "_OBJC_ClassRef_ObjectAlias" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/obj-c++.dg/proto-lossage-3.mm b/gcc/testsuite/obj-c++.dg/proto-lossage-3.mm
index 8a6623e..ac66ace 100644
--- a/gcc/testsuite/obj-c++.dg/proto-lossage-3.mm
+++ b/gcc/testsuite/obj-c++.dg/proto-lossage-3.mm
@@ -19,9 +19,16 @@
int
main()
{
+#ifdef __OBJC2__
+protocol_getMethodDescription(@protocol(NoInstanceMethods), @selector(name), NO, YES);
+protocol_getMethodDescription(@protocol(NoInstanceMethods), @selector(name), NO, NO);
+protocol_getMethodDescription(@protocol(NoClassMethods), @selector(name), NO, YES);
+protocol_getMethodDescription(@protocol(NoClassMethods), @selector(name), NO, NO);
+#else
[@protocol(NoInstanceMethods) descriptionForInstanceMethod: @selector(name)];
[@protocol(NoInstanceMethods) descriptionForClassMethod: @selector(name)];
[@protocol(NoClassMethods) descriptionForInstanceMethod: @selector(name)];
[@protocol(NoClassMethods) descriptionForClassMethod: @selector(name)];
+#endif
return 0;
}
diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm
index f61a474..3cb3acf 100644
--- a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm
+++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm
@@ -29,6 +29,7 @@ extern struct objc_class _NSConstantStringClassReference;
const NSConstantString *appKey = @"MyApp";
-/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" } } */
+/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */
/* { dg-final { scan-assembler ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler ".quad\t__NSConstantStringClassReference\n\t.quad\t.*\n\t.long\t5\n\t.space 4\n\t.data" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._NSConstantString\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm
index 4abab36..8674646 100644
--- a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm
+++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm
@@ -29,6 +29,7 @@ extern struct objc_class _XStrClassReference;
const XStr *appKey = @"MyApp";
-/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" } } */
-/* { dg-final { scan-assembler ".long\t__XStrClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler ".quad\t__XStrClassReference\n\t.quad\t.*\n\t.long\t5\n\t.space 4\n\t.data" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler ".long\t__XStrClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._XStr\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm
index 7c99f6b..e05c62b 100644
--- a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm
+++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm
@@ -21,6 +21,7 @@ extern struct objc_class _NSConstantStringClassReference;
const NSConstantString *appKey = @"MyApp";
-/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" } } */
-/* { dg-final { scan-assembler ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } }} } */
-/* { dg-final { scan-assembler ".quad\t__NSConstantStringClassReference\n\t.quad\t.*\n\t.long\t5\n\t.space 4\n\t.data" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._NSConstantString\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/obj-c++.dg/try-catch-2.mm b/gcc/testsuite/obj-c++.dg/try-catch-2.mm
index cf5189a..05aba36 100644
--- a/gcc/testsuite/obj-c++.dg/try-catch-2.mm
+++ b/gcc/testsuite/obj-c++.dg/try-catch-2.mm
@@ -3,7 +3,7 @@
/* Developed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
-/* { dg-xfail-if "PR23616" { *-*-* } { "-fgnu-runtime" } { "-fnext-runtime" } } */
+/* { dg-xfail-run-if "PR23616" { *-*-* } { "-fgnu-runtime" } { "-fnext-runtime" } } */
/* { dg-xfail-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" "-fgnu-runtime" } { "" } }
/* { dg-options "-fobjc-exceptions" } */
diff --git a/gcc/testsuite/obj-c++.dg/try-catch-9.mm b/gcc/testsuite/obj-c++.dg/try-catch-9.mm
index c4033c7..a4331fc 100644
--- a/gcc/testsuite/obj-c++.dg/try-catch-9.mm
+++ b/gcc/testsuite/obj-c++.dg/try-catch-9.mm
@@ -3,7 +3,7 @@
/* Developed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */
-/* { dg-xfail-if "PR23616" { *-*-* } { "-fgnu-runtime" } { "-fnext-runtime" } } */
+/* { dg-xfail-run-if "PR23616" { *-*-* } { "-fgnu-runtime" } { "-fnext-runtime" } } */
/* { dg-xfail-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" "-fgnu-runtime" } { "" } }
/* { dg-prune-output ".*internal compiler error.*" } */
/* { dg-options "-fobjc-exceptions -O2" } */
diff --git a/gcc/testsuite/objc.dg/encode-7-next-64bit.m b/gcc/testsuite/objc.dg/encode-7-next-64bit.m
index 3a5e61d..60129f9 100644
--- a/gcc/testsuite/objc.dg/encode-7-next-64bit.m
+++ b/gcc/testsuite/objc.dg/encode-7-next-64bit.m
@@ -2,16 +2,15 @@
/* { dg-do run { target *-*-darwin* } } */
/* { dg-require-effective-target lp64 } */
-/* { dg-options "-Wno-deprecated-declarations" } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
-/* { dg-additional-sources "../objc-obj-c++-shared/Object1.m" } */
-#include "../objc-obj-c++-shared/Object1.h"
-#include "../objc-obj-c++-shared/next-mapping.h"
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
+#include <objc/Object.h>
+#include "../objc-obj-c++-shared/next-mapping.h"
+
#define CHECK_IF(E) if (!(E)) abort ()
@class NSDictionary, NSFont, NSError, _NSATSTypesetterGuts, NSString, NSMenu, NSArray;
@@ -195,69 +194,70 @@ NSRange globalRange;
int main(void) {
Class fooClass = objc_getClass ("Foo");
Method meth;
- struct objc_ivar_list *ivars;
- struct objc_ivar *ivar;
+ Ivar *ivars;
+ unsigned int ivar_count;
+ Ivar ivar;
meth = class_getInstanceMethod (fooClass, @selector(_errorWithOSStatus:ref1:ref2:reading:));
- CHECK_IF (!strcmp (meth->method_types, "@44@0:8q16r^{FSRef=[80C]}24r^{FSRef=[80C]}32c40"));
+ CHECK_IF (!strcmp (method_getTypeEncoding(meth), "@44@0:8q16r^{FSRef=[80C]}24r^{FSRef=[80C]}32c40"));
meth = class_getInstanceMethod (fooClass, @selector(_attributeRunForCharacterAtIndex:));
- CHECK_IF (!strcmp (meth->method_types, "r^{?=@@QQ^Qffff{_NSRect={_NSPoint=ff}{_NSSize=ff}}q^qQ^Q@@@:::****{?=b1b1b1b1b1b27}}24@0:8Q16"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "r^{?=@@QQ^Qffff{_NSRect={_NSPoint=ff}{_NSSize=ff}}q^qQ^Q@@@:::****{?=b1b1b1b1b1b27}}24@0:8Q16"));
meth = class_getInstanceMethod (fooClass, @selector(_getATSTypesetterGuts:));
- CHECK_IF (!strcmp (meth->method_types, "r@24@0:8r:16"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "r@24@0:8r:16"));
meth = class_getInstanceMethod (fooClass, @selector(resumeWithSuspensionID:and:));
- CHECK_IF (!strcmp (meth->method_types, "v32@0:8^{__NSAppleEventManagerSuspension=}16r^Q24"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "v32@0:8^{__NSAppleEventManagerSuspension=}16r^Q24"));
meth = class_getInstanceMethod (fooClass, @selector(anotherMeth:and:and:));
- CHECK_IF (!strcmp (meth->method_types, "r@40@0:8r:16r@24r@32"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "r@40@0:8r:16r@24r@32"));
meth = class_getInstanceMethod (fooClass, @selector(str1:str2:str3:str4:));
- CHECK_IF (!strcmp (meth->method_types, "@48@0:8r*16*24*32r*40"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "@48@0:8r*16*24*32r*40"));
meth = class_getInstanceMethod (fooClass, @selector(foo1:foo2:foo3:foo4:));
- CHECK_IF (!strcmp (meth->method_types, "Vv48@0:8@16r@24@32r@40"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "Vv48@0:8@16r@24@32r@40"));
meth = class_getInstanceMethod (fooClass, @selector(sel1:id1:));
- CHECK_IF (!strcmp (meth->method_types, "rn*32@0:8r:16r@24"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "rn*32@0:8r:16r@24"));
meth = class_getInstanceMethod (fooClass, @selector(obj1:obj2:obj3:));
- CHECK_IF (!strcmp (meth->method_types, "N@40@0:8r@16@24^{Object=#}32"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "N@40@0:8r@16@24^{Object=#}32"));
meth = class_getClassMethod (fooClass, @selector(_defaultScriptingComponent));
- CHECK_IF (!strcmp (meth->method_types, "^{ComponentInstanceRecord=[1q]}16@0:8"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "^{ComponentInstanceRecord=[1q]}16@0:8"));
meth = class_getInstanceMethod (fooClass, @selector(_formatCocoaErrorString:parameters:applicableFormatters:count:));
- CHECK_IF (!strcmp (meth->method_types, "@44@0:8@16r*24^^{?}32i40"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "@44@0:8@16r*24^^{?}32i40"));
meth = class_getInstanceMethod (fooClass, @selector(formatter_func:run:));
- CHECK_IF (!strcmp (meth->method_types, "^{?=^?@I}32@0:8@16r^^{?}24"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "^{?=^?@I}32@0:8@16r^^{?}24"));
meth = class_getInstanceMethod (fooClass, @selector(_forgetWord:inDictionary:));
- CHECK_IF (!strcmp (meth->method_types, "c32@0:8nO@16nO@24"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "c32@0:8nO@16nO@24"));
meth = class_getInstanceMethod (fooClass, @selector(_registerServicesMenu:withSendTypes:andReturnTypes:addToList:));
- CHECK_IF (!strcmp (meth->method_types, "v44@0:8@16r^*24r^*32c40"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "v44@0:8@16r^*24r^*32c40"));
meth = class_getClassMethod (fooClass, @selector(_proxySharePointer));
- CHECK_IF (!strcmp (meth->method_types, "^^{__CFSet}16@0:8"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "^^{__CFSet}16@0:8"));
meth = class_getInstanceMethod (fooClass, @selector(_checkGrammarInString:language:details:));
- CHECK_IF (!strcmp (meth->method_types, "{_NSRange=II}40@0:8n@16nO@24oO^@32"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "{_NSRange=II}40@0:8n@16nO@24oO^@32"));
meth = class_getInstanceMethod (fooClass, @selector(_resolvePositionalStakeGlyphsForLineFragment:lineFragmentRect:minPosition:maxPosition:maxLineFragmentWidth:breakHint:));
- CHECK_IF (!strcmp (meth->method_types, "B60@0:8^{__CTLine=}16{_NSRect={_NSPoint=ff}{_NSSize=ff}}24f40f44f48^Q52"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "B60@0:8^{__CTLine=}16{_NSRect={_NSPoint=ff}{_NSSize=ff}}24f40f44f48^Q52"));
meth = class_getClassMethod (fooClass, @selector(findVoiceByIdentifier:returningCreator:returningID:));
- CHECK_IF (!strcmp (meth->method_types, "c40@0:8@16^I24^I32"));
+ CHECK_IF (!strcmp (method_getTypeEncoding (meth), "c40@0:8@16^I24^I32"));
- ivars = fooClass->ivars;
- CHECK_IF (ivars->ivar_count == 1);
+ ivars = class_copyIvarList (fooClass, &ivar_count);
+ CHECK_IF (ivar_count == 1);
- ivar = ivars->ivar_list;
- CHECK_IF (!strcmp (ivar->ivar_name, "r"));
- CHECK_IF (!strcmp (ivar->ivar_type,
+ ivar = ivars[0];
+ CHECK_IF (!strcmp (ivar_getName(ivar), "r"));
+ CHECK_IF (!strcmp (ivar_getTypeEncoding(ivar),
"{?=\"_attributes\"@\"NSDictionary\"\"_font\"@\"NSFont\"\"_characterLength\""
"Q\"_nominalGlyphLocation\"Q\"p\"^Q\"_defaultLineHeight\"f\"_defaultBaselineOffset\""
"f\"_horizExpansion\"f\"_baselineDelta\"f\"_attachmentBBox\"{_NSRect=\"origin\""
diff --git a/gcc/testsuite/objc.dg/image-info.m b/gcc/testsuite/objc.dg/image-info.m
index e9e9de6..194d366 100644
--- a/gcc/testsuite/objc.dg/image-info.m
+++ b/gcc/testsuite/objc.dg/image-info.m
@@ -7,13 +7,19 @@
/* { dg-skip-if "NeXT-only" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-freplace-objc-classes" } */
-#include "../objc-obj-c++-shared/Object1.h"
#include <objc/objc.h>
+#include <objc/Object.h>
extern void abort(void);
-
#define CHECK_IF(expr) if(!(expr)) abort();
+@interface Object (TEST_SUITE_C1)
+- init;
+@end
+@implementation Object (TEST_SUITE_C1)
+- init {return self;}
+@end
+
@interface Base: Object {
@public
int a;
@@ -33,4 +39,5 @@ extern void abort(void);
}
@end
-/* { dg-final { scan-assembler "\t.section __OBJC, __image_info.*\n\t.align.*\nL_OBJC_IMAGE_INFO.*:\n\t.long\t0\n\t.long\t1" } } */
+/* { dg-final { scan-assembler "\t.section __OBJC, __image_info.*\n\t.align.*\nL_OBJC_ImageInfo.*:\n\t.long\t0\n\t.long\t1" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler "\t.section __DATA, __objc_imageinfo.*\n\t.align.*\nL_OBJC_ImageInfo.*:\n\t.long\t0\n\t.long\t17" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/objc.dg/lookup-1.m b/gcc/testsuite/objc.dg/lookup-1.m
index ff59b7e..737d58a 100644
--- a/gcc/testsuite/objc.dg/lookup-1.m
+++ b/gcc/testsuite/objc.dg/lookup-1.m
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-additional-sources "../objc-obj-c++-shared/Object1.m" } */
#include <stdlib.h>
#include "../objc-obj-c++-shared/Object1.h"
@@ -53,5 +54,3 @@ int main(void) {
return 0;
}
-
-#include "../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc.dg/method-4.m b/gcc/testsuite/objc.dg/method-4.m
index c5fa1a0..df25bba 100644
--- a/gcc/testsuite/objc.dg/method-4.m
+++ b/gcc/testsuite/objc.dg/method-4.m
@@ -22,5 +22,5 @@ void foo(void) {
obj = [ObjectAlias2 new];
}
-/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */
-/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_1" } } */
+/* { dg-final { scan-assembler "_OBJC_ClassRefs_0" } } */
+/* { dg-final { scan-assembler-not "_OBJC_ClassRefs_1" } } */
diff --git a/gcc/testsuite/objc.dg/next-runtime-1.m b/gcc/testsuite/objc.dg/next-runtime-1.m
index 9a0951c..c76b616 100644
--- a/gcc/testsuite/objc.dg/next-runtime-1.m
+++ b/gcc/testsuite/objc.dg/next-runtime-1.m
@@ -1,13 +1,14 @@
/* Test that the correct version number (6) is set in the module descriptor
- when compiling for the NeXT runtime. */
-/* Author: Ziemowit Laski <zlaski@apple.com> */
+ when compiling for the NeXT runtime ABI=0 - and that the MODULE descriptor
+ is not emitted at all for ABI 2. */
+/* modified from a testcase added by: Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile { target *-*-darwin* } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
+/* { dg-skip-if "" { *-*-* } { "-fobjc-abi-version=1" } { "" } } */
+/* { dg-options "-fobjc-abi-version=0" { target { *-*-darwin* && { ! lp64 } } } } */
-#include "../objc-obj-c++-shared/Object1.h"
-
-@interface FooBar: Object
+@interface FooBar
- (void)boo;
@end
@@ -15,5 +16,5 @@
- (void)boo { }
@end
-/* { dg-final { scan-assembler "L_OBJC_MODULES:\n\[ \t\]*\.long\t6\n" { target { *-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler "L_OBJC_MODULES:\n\[ \t\]*\.quad\t6\n" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler "L_OBJC_Module:\n\[ \t\]*\.long\t6\n" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler-not "L_OBJC_Module" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/objc.dg/pr23214.m b/gcc/testsuite/objc.dg/pr23214.m
index 8443c94..d8092a8 100644
--- a/gcc/testsuite/objc.dg/pr23214.m
+++ b/gcc/testsuite/objc.dg/pr23214.m
@@ -3,10 +3,19 @@
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
-/* { dg-additional-sources "../objc-obj-c++-shared/Object1.m" } */
-#import "../objc-obj-c++-shared/Object1.h"
-#import "../objc-obj-c++-shared/Protocol1.h"
+#include <objc/Protocol.h>
+
+#ifdef __OBJC2__
+/* The ObjC V2 "Object" does not provide -class. */
+@interface Object (TS_CAT)
+- class;
+@end
+
+@implementation Object (TS_CAT)
+- class { return isa; }
+@end
+#endif
@protocol A
@end
diff --git a/gcc/testsuite/objc.dg/special/unclaimed-category-1.h b/gcc/testsuite/objc.dg/special/unclaimed-category-1.h
index 0453033..bf507a7 100644
--- a/gcc/testsuite/objc.dg/special/unclaimed-category-1.h
+++ b/gcc/testsuite/objc.dg/special/unclaimed-category-1.h
@@ -5,7 +5,11 @@
@interface TestClass
{
+#ifdef __OBJC2__
+ Class isa;
+#else
id isa;
+#endif
}
- (int)D;
@end
diff --git a/gcc/testsuite/objc.dg/special/unclaimed-category-1.m b/gcc/testsuite/objc.dg/special/unclaimed-category-1.m
index 472ad8b..88e3d8e 100644
--- a/gcc/testsuite/objc.dg/special/unclaimed-category-1.m
+++ b/gcc/testsuite/objc.dg/special/unclaimed-category-1.m
@@ -2,11 +2,11 @@
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
-#import "../../objc-obj-c++-shared/next-mapping.h"
#include <objc/objc.h>
#ifndef __NEXT_RUNTIME__
#include <objc/objc-api.h>
#endif
+#include "../../objc-obj-c++-shared/next-mapping.h"
extern void abort (void);
@@ -73,5 +73,3 @@ int main (void)
return 0;
}
-
-#import "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc.dg/symtab-1.m b/gcc/testsuite/objc.dg/symtab-1.m
index 100b245..936f8d4 100644
--- a/gcc/testsuite/objc.dg/symtab-1.m
+++ b/gcc/testsuite/objc.dg/symtab-1.m
@@ -4,7 +4,7 @@
/* { dg-do compile { target { *-*-darwin* } } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
-#include "../objc-obj-c++-shared/Object1.h"
+#include <objc/Object.h>
@interface Base: Object
- (void)setValues;
@@ -22,7 +22,6 @@
-(void)checkValues { }
@end
-/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.long\t0\n\t.long\t0\n\t.word\t2\n\t.word\t0\n\t.long\tL_OBJC_CLASS_Derived.*\n\t.long\tL_OBJC_CLASS_Base.*\n" { target { *86*-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.long\t0\n\t.long\t0\n\t.short\t2\n\t.short\t0\n\t.long\tL_OBJC_CLASS_Derived.*\n\t.long\tL_OBJC_CLASS_Base.*\n" { target { powerpc*-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.quad\t0\n\t.quad\t0\n\t.word\t2\n\t.word\t0\n\t.space 4\n\t.quad\tL_OBJC_CLASS_Derived.*\n\t.quad\tL_OBJC_CLASS_Base.*\n" { target { *86*-*-darwin* && { lp64 } } } } } */
-/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.quad\t0\n\t.quad\t0\n\t.short\t2\n\t.short\t0\n\t.space 4\n\t.quad\tL_OBJC_CLASS_Derived.*\n\t.quad\tL_OBJC_CLASS_Base.*\n" { target { powerpc*-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler "L_OBJC_Symbols.*:\n\t.long\t0\n\t.long\t0\n\t.word\t2\n\t.word\t0\n\t.long\tL_OBJC_Class_Derived.*\n\t.long\tL_OBJC_Class_Base.*\n" { target { *86*-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler "L_OBJC_Symbols.*:\n\t.long\t0\n\t.long\t0\n\t.short\t2\n\t.short\t0\n\t.long\tL_OBJC_Class_Derived.*\n\t.long\tL_OBJC_Class_Base.*\n" { target { powerpc*-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler-not "L_OBJC_Symbols" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/objc.dg/torture/forward-1.m b/gcc/testsuite/objc.dg/torture/forward-1.m
index 518bf27..bccf4a1 100644
--- a/gcc/testsuite/objc.dg/torture/forward-1.m
+++ b/gcc/testsuite/objc.dg/torture/forward-1.m
@@ -1,14 +1,18 @@
/* { dg-do run } */
/* See if -forward::/-performv:: is able to work. */
/* { dg-xfail-run-if "PR36610" { ! { { i?86-*-* x86_64-*-* } && ilp32 } } { "-fgnu-runtime" } { "" } } */
-/* { dg-skip-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-skip-if "Needs OBJC2 Implementation" { *-*-darwin* && { lp64 } } { "-fnext-runtime" } { "" } } */
+/* There is no implementation of forward: in the NeXT m64 libobjc/Object
+ neither have we implemented this in our extensions - so we have to skip it
+ for now. */
#include <stdio.h>
#include <stdlib.h>
-#import "../../objc-obj-c++-shared/Object1.h"
-#import "../../objc-obj-c++-shared/next-mapping.h"
-#include <objc/objc-api.h>
+#ifndef __NEXT_RUNTIME__
+# include <objc/objc-api.h>
+#endif
+#include <objc/Object.h>
#define VALUETOUSE 1234567890
diff --git a/gcc/testsuite/objc.dg/torture/strings/const-str-10.m b/gcc/testsuite/objc.dg/torture/strings/const-str-10.m
index c170f38..f0f2823 100644
--- a/gcc/testsuite/objc.dg/torture/strings/const-str-10.m
+++ b/gcc/testsuite/objc.dg/torture/strings/const-str-10.m
@@ -29,6 +29,7 @@ extern Class _NSConstantStringClassReference;
const NSConstantString *appKey = @"MyApp";
-/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" } } */
+/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */
/* { dg-final { scan-assembler ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler ".quad\t__NSConstantStringClassReference\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._NSConstantString\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/objc.dg/torture/strings/const-str-11.m b/gcc/testsuite/objc.dg/torture/strings/const-str-11.m
index 9f3705e..fa9dbd9 100644
--- a/gcc/testsuite/objc.dg/torture/strings/const-str-11.m
+++ b/gcc/testsuite/objc.dg/torture/strings/const-str-11.m
@@ -29,6 +29,7 @@ extern Class _XStrClassReference;
const XStr *appKey = @"MyApp";
-/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" } } */
+/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */
/* { dg-final { scan-assembler ".long\t__XStrClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler ".quad\t__XStrClassReference\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._XStr\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/objc.dg/torture/strings/const-str-9.m b/gcc/testsuite/objc.dg/torture/strings/const-str-9.m
index ddbe93d..39bd102 100644
--- a/gcc/testsuite/objc.dg/torture/strings/const-str-9.m
+++ b/gcc/testsuite/objc.dg/torture/strings/const-str-9.m
@@ -21,6 +21,7 @@ Class _NSConstantStringClassReference;
const NSConstantString *appKey = @"MyApp";
-/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" } } */
+/* { dg-final { scan-assembler ".section __OBJC, __cstring_object" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { target { *-*-darwin* && { lp64 } } } } } */
/* { dg-final { scan-assembler ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } } } } */
-/* { dg-final { scan-assembler ".quad\t__NSConstantStringClassReference\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
+/* { dg-final { scan-assembler ".quad\t_OBJC_CLASS_._NSConstantString\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
diff --git a/gcc/testsuite/objc.dg/zero-link-1.m b/gcc/testsuite/objc.dg/zero-link-1.m
index 35cabfa..c040031 100644
--- a/gcc/testsuite/objc.dg/zero-link-1.m
+++ b/gcc/testsuite/objc.dg/zero-link-1.m
@@ -25,6 +25,7 @@ int main(void) {
return 0;
}
-/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_0" } } */
+/* { dg-final { scan-assembler-not "_OBJC_ClassRefs_0" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler-not "_OBJC_ClassRef_Base" { target { *-*-darwin* && { lp64 } } } } } */
/* { dg-final { scan-assembler "objc_getClass" } } */
diff --git a/gcc/testsuite/objc.dg/zero-link-2.m b/gcc/testsuite/objc.dg/zero-link-2.m
index 443090a..ff82e5e 100644
--- a/gcc/testsuite/objc.dg/zero-link-2.m
+++ b/gcc/testsuite/objc.dg/zero-link-2.m
@@ -5,8 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-fno-zero-link" } */
-#include "../objc-obj-c++-shared/Object1.h"
-#include <objc/objc.h>
+#include <objc/Object.h>
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort();
@@ -25,5 +24,6 @@ int main(void) {
return 0;
}
-/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */
+/* { dg-final { scan-assembler "_OBJC_ClassRefs_0" { target { *-*-darwin* && { ! lp64 } } } } } */
+/* { dg-final { scan-assembler "_OBJC_ClassRef_Base" { target { *-*-darwin* && { lp64 } } } } } */
/* { dg-final { scan-assembler-not "objc_getClass" } } */
diff --git a/gcc/testsuite/objc/execute/accessing_ivars.m b/gcc/testsuite/objc/execute/accessing_ivars.m
index dbde8cd..e4c9cf4 100644
--- a/gcc/testsuite/objc/execute/accessing_ivars.m
+++ b/gcc/testsuite/objc/execute/accessing_ivars.m
@@ -1,7 +1,9 @@
/* Contributed by Nicola Pero - Thu Mar 8 16:27:46 CET 2001 */
#include <stdlib.h>
-#import "../../objc-obj-c++-shared/Object1.h"
+#ifndef __NEXT_RUNTIME__
#include <objc/objc-api.h>
+#endif
+#include "../../objc-obj-c++-shared/Object1.h"
/* Test that by using -> we can access ivars of other objects of the same
class */
@@ -53,3 +55,4 @@ int main (void)
return 0;
}
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/bf-common.h b/gcc/testsuite/objc/execute/bf-common.h
index c79c3ef..ca70c21 100644
--- a/gcc/testsuite/objc/execute/bf-common.h
+++ b/gcc/testsuite/objc/execute/bf-common.h
@@ -11,6 +11,7 @@
#define objc_get_class(C) objc_getClass(C)
#endif
+#ifndef __OBJC2__
void print_ivars (Class class)
{
struct objc_ivar_list* ivars = class->ivars;
@@ -61,9 +62,11 @@ void compare_structures (Class class, const char* type)
printf ("%d ivars checked\n", i);
}
+#endif
int main ()
{
+#ifndef __OBJC2__
struct class_vars
{
@defs (MyObject);
@@ -80,8 +83,10 @@ int main ()
printf ("sizes don't match (computed %d, exact %d)\n", size1, size2);
abort ();
}
+#endif
exit (0);
}
-
+#ifndef __OBJC2__
#include "../../objc-obj-c++-shared/objc-test-suite-next-encode-assist-impl.h"
+#endif
diff --git a/gcc/testsuite/objc/execute/bycopy-2.m b/gcc/testsuite/objc/execute/bycopy-2.m
index 8e7f169..840881f 100644
--- a/gcc/testsuite/objc/execute/bycopy-2.m
+++ b/gcc/testsuite/objc/execute/bycopy-2.m
@@ -27,5 +27,4 @@ int main (void)
exit (0);
}
-
-
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/bycopy-3.m b/gcc/testsuite/objc/execute/bycopy-3.m
index 4c2bd27..15c49a5 100644
--- a/gcc/testsuite/objc/execute/bycopy-3.m
+++ b/gcc/testsuite/objc/execute/bycopy-3.m
@@ -24,6 +24,12 @@ extern int printf (const char *, ...);
/* This no-op class to keep it compile under broken gcc 3.x */
@interface MyObject : Object <MyProtocol>
+#ifdef __OBJC2__
++ (id) initialize;
++ (id) alloc;
++ new;
+- init;
+#endif
@end
@implementation MyObject
@@ -31,6 +37,12 @@ extern int printf (const char *, ...);
{
return [MyObject alloc];
}
+#ifdef __OBJC2__
++ initialize {return self;}
++ alloc { return class_createInstance (self, 0);}
++ new { return [[self alloc] init]; }
+- init {return self;}
+#endif
@end
/* The following header, together with the implementation included below,
diff --git a/gcc/testsuite/objc/execute/class-tests-1.h b/gcc/testsuite/objc/execute/class-tests-1.h
index ebc49b6..54a77d2 100644
--- a/gcc/testsuite/objc/execute/class-tests-1.h
+++ b/gcc/testsuite/objc/execute/class-tests-1.h
@@ -1,5 +1,6 @@
/* Contributed by Nicola Pero on Tue Mar 6 23:05:53 CET 2001 */
+#include <stdio.h>
#include <stdlib.h>
#include "../../objc-obj-c++-shared/Object1.h"
#include <objc/objc.h>
diff --git a/gcc/testsuite/objc/execute/class-tests-2.h b/gcc/testsuite/objc/execute/class-tests-2.h
index cc14abb..1aa7394 100644
--- a/gcc/testsuite/objc/execute/class-tests-2.h
+++ b/gcc/testsuite/objc/execute/class-tests-2.h
@@ -1,6 +1,7 @@
/* Contributed by Nicola Pero on Tue Mar 6 23:05:53 CET 2001 */
#include <objc/objc.h>
#include <objc/objc-api.h>
+#include <stdio.h>
#include <stdlib.h>
/*
diff --git a/gcc/testsuite/objc/execute/compatibility_alias.m b/gcc/testsuite/objc/execute/compatibility_alias.m
index b134f0c..61d7625 100644
--- a/gcc/testsuite/objc/execute/compatibility_alias.m
+++ b/gcc/testsuite/objc/execute/compatibility_alias.m
@@ -10,3 +10,4 @@ int main (void)
return 0;
}
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/enumeration-1.m b/gcc/testsuite/objc/execute/enumeration-1.m
index 1adcfd0..57d1a4b 100644
--- a/gcc/testsuite/objc/execute/enumeration-1.m
+++ b/gcc/testsuite/objc/execute/enumeration-1.m
@@ -48,3 +48,4 @@ int main (void)
return 0;
}
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/enumeration-2.m b/gcc/testsuite/objc/execute/enumeration-2.m
index c47bb8a..3094963 100644
--- a/gcc/testsuite/objc/execute/enumeration-2.m
+++ b/gcc/testsuite/objc/execute/enumeration-2.m
@@ -50,3 +50,4 @@ int main (void)
return 0;
}
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/exceptions/catchall-1.m b/gcc/testsuite/objc/execute/exceptions/catchall-1.m
index 01eff92..2db40a8 100644
--- a/gcc/testsuite/objc/execute/exceptions/catchall-1.m
+++ b/gcc/testsuite/objc/execute/exceptions/catchall-1.m
@@ -74,3 +74,4 @@ int main (void) {
test((Object *)-1);
return 0;
}
+#import "../../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/exceptions/exceptions.exp b/gcc/testsuite/objc/execute/exceptions/exceptions.exp
index 173f656..0443ca1 100644
--- a/gcc/testsuite/objc/execute/exceptions/exceptions.exp
+++ b/gcc/testsuite/objc/execute/exceptions/exceptions.exp
@@ -28,6 +28,7 @@ lappend additional_flags "-fobjc-exceptions"
# load support procs
load_lib objc-torture.exp
load_lib torture-options.exp
+load_lib target-supports.exp
torture-init
objc-set-runtime-options "execute" "additional_flags=-fobjc-exceptions"
diff --git a/gcc/testsuite/objc/execute/exceptions/finally-1.m b/gcc/testsuite/objc/execute/exceptions/finally-1.m
index 5206c77..370b19b 100644
--- a/gcc/testsuite/objc/execute/exceptions/finally-1.m
+++ b/gcc/testsuite/objc/execute/exceptions/finally-1.m
@@ -1,6 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
+//#import "../../../objc-obj-c++-shared/Object1.h"
+#ifdef __OBJC2__
+#include <objc/runtime.h>
+@interface Object
++ initialize;
++ new;
+- free;
+@end
+@implementation Object
++ initialize { return self; }
++ new { return class_createInstance (self, 0); }
+- free { return object_dispose(self);}
+@end
+
+#else
#import "../../../objc-obj-c++-shared/Object1.h"
+#endif
static int made_try = 0;
@@ -57,3 +73,4 @@ main(int ac, char *av[])
abort ();
return 0;
}
+//#import "../../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/exceptions/foward-1.m b/gcc/testsuite/objc/execute/exceptions/foward-1.m
index ae5d927..6b31d7c 100644
--- a/gcc/testsuite/objc/execute/exceptions/foward-1.m
+++ b/gcc/testsuite/objc/execute/exceptions/foward-1.m
@@ -2,12 +2,33 @@
/* Developed by Marcin Koziej <creep@desk.pl>. */
#include <stdlib.h>
-#import "../../../objc-obj-c++-shared/Object1.h"
+#include <objc/Object.h>
+#ifndef __NEXT_RUNTIME__
#import <objc/objc-api.h>
+#endif
+
+#ifdef __OBJC2__
+@interface Object (TEST_SUITE_ADDITIONS)
++ initialize;
++ alloc;
++ new;
+- init;
+- free;
+@end
+
+@implementation Object (TEST_SUITE_ADDITIONS)
++ initialize { return self; }
++ alloc { return class_createInstance (self, 0); }
++ new { return [[self alloc] init]; }
+- init { return self; }
+- free { return object_dispose(self); }
+@end
+#endif
static int i;
-@interface Thrower : Object
+__attribute__((objc_exception))
+@interface Thrower : Object
- forward: (SEL) s : (void*) a;
@end
@@ -16,8 +37,10 @@ static int i;
{
i++;
@throw [Object new];
+ return nil;
}
@end
+
int
main()
{
diff --git a/gcc/testsuite/objc/execute/exceptions/local-variables-1.m b/gcc/testsuite/objc/execute/exceptions/local-variables-1.m
index fa419f9..0488d79 100644
--- a/gcc/testsuite/objc/execute/exceptions/local-variables-1.m
+++ b/gcc/testsuite/objc/execute/exceptions/local-variables-1.m
@@ -60,3 +60,4 @@ int main(void) {
foo(15, &gf1);
return 0;
}
+#import "../../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/formal_protocol-1.m b/gcc/testsuite/objc/execute/formal_protocol-1.m
index a62def3..6514449 100644
--- a/gcc/testsuite/objc/execute/formal_protocol-1.m
+++ b/gcc/testsuite/objc/execute/formal_protocol-1.m
@@ -42,4 +42,4 @@ int main (void)
return 0;
}
-
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/formal_protocol-2.m b/gcc/testsuite/objc/execute/formal_protocol-2.m
index a0f7eec..b830cd9 100644
--- a/gcc/testsuite/objc/execute/formal_protocol-2.m
+++ b/gcc/testsuite/objc/execute/formal_protocol-2.m
@@ -43,4 +43,4 @@ int main (void)
return 0;
}
-
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/formal_protocol-3.m b/gcc/testsuite/objc/execute/formal_protocol-3.m
index c55773a..f28c95f 100644
--- a/gcc/testsuite/objc/execute/formal_protocol-3.m
+++ b/gcc/testsuite/objc/execute/formal_protocol-3.m
@@ -56,4 +56,4 @@ int main (void)
return 0;
}
-
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/formal_protocol-4.m b/gcc/testsuite/objc/execute/formal_protocol-4.m
index 92f0521..10aba89 100644
--- a/gcc/testsuite/objc/execute/formal_protocol-4.m
+++ b/gcc/testsuite/objc/execute/formal_protocol-4.m
@@ -38,4 +38,4 @@ int main (void)
return 0;
}
-
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/formal_protocol-5.m b/gcc/testsuite/objc/execute/formal_protocol-5.m
index 8bb63ec..c3bd53d 100644
--- a/gcc/testsuite/objc/execute/formal_protocol-5.m
+++ b/gcc/testsuite/objc/execute/formal_protocol-5.m
@@ -1,7 +1,8 @@
/* Contributed by Nicola Pero - Fri Mar 9 21:35:47 CET 2001 */
#include <stdlib.h>
-#include "../../objc-obj-c++-shared/Protocol1.h"
+#include <objc/Protocol.h>
+#include "../../objc-obj-c++-shared/next-mapping.h"
/* Test defining a protocol, and accessing it using @protocol */
@@ -35,4 +36,3 @@ int main (void)
return 0;
}
-
diff --git a/gcc/testsuite/objc/execute/formal_protocol-6.m b/gcc/testsuite/objc/execute/formal_protocol-6.m
index dd42b37..b02fc1e 100644
--- a/gcc/testsuite/objc/execute/formal_protocol-6.m
+++ b/gcc/testsuite/objc/execute/formal_protocol-6.m
@@ -1,7 +1,8 @@
/* Contributed by Nicola Pero - Fri Mar 9 21:35:47 CET 2001 */
#include <stdlib.h>
-#include "../../objc-obj-c++-shared/Protocol1.h"
+#include <objc/Protocol.h>
+#include "../../objc-obj-c++-shared/next-mapping.h"
/* Test defining a protocol, and accessing it using @protocol */
diff --git a/gcc/testsuite/objc/execute/formal_protocol-7.m b/gcc/testsuite/objc/execute/formal_protocol-7.m
index c4e1850..d15013a 100644
--- a/gcc/testsuite/objc/execute/formal_protocol-7.m
+++ b/gcc/testsuite/objc/execute/formal_protocol-7.m
@@ -41,4 +41,4 @@ int main (void)
return 0;
}
-
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/no_clash.m b/gcc/testsuite/objc/execute/no_clash.m
index 9cb004d..d4ab4cb 100644
--- a/gcc/testsuite/objc/execute/no_clash.m
+++ b/gcc/testsuite/objc/execute/no_clash.m
@@ -39,3 +39,4 @@ int main (void)
return 0;
}
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/object_is_class.m b/gcc/testsuite/objc/execute/object_is_class.m
index 199517e..14a7f52 100644
--- a/gcc/testsuite/objc/execute/object_is_class.m
+++ b/gcc/testsuite/objc/execute/object_is_class.m
@@ -1,8 +1,10 @@
/* Contributed by Nicola Pero - Tue Jul 3 10:55:21 BST 2001 */
-#import "../../objc-obj-c++-shared/next-mapping.h"
-#import "../../objc-obj-c++-shared/Object1.h"
-#include <objc/objc.h>
-#include <objc/objc-api.h>
+#ifdef __NEXT_RUNTIME__
+# include "../../objc-obj-c++-shared/next-mapping.h"
+#else
+# include <objc/objc-api.h>
+#endif
+#include "../../objc-obj-c++-shared/Object1.h"
/* This test demonstrate a failure in object_is_class which was fixed */
@@ -41,3 +43,4 @@ int main (void)
return 0;
}
+#include "../../objc-obj-c++-shared/Object1-implementation.h"
diff --git a/gcc/testsuite/objc/execute/object_is_meta_class.m b/gcc/testsuite/objc/execute/object_is_meta_class.m
index d5aedca..91a628e 100644
--- a/gcc/testsuite/objc/execute/object_is_meta_class.m
+++ b/gcc/testsuite/objc/execute/object_is_meta_class.m
@@ -1,7 +1,10 @@
/* Contributed by Nicola Pero - Tue Jul 3 10:55:21 BST 2001 */
-#import "../../objc-obj-c++-shared/Object1.h"
-#import "../../objc-obj-c++-shared/next-mapping.h"
-#include <objc/objc-api.h>
+#ifdef __NEXT_RUNTIME__
+# include "../../objc-obj-c++-shared/next-mapping.h"
+#else
+# include <objc/objc-api.h>
+#endif
+#include "../../objc-obj-c++-shared/Object1.h"
/* This test demonstrate a failure in object_is_meta_class which was fixed */
@@ -38,4 +41,4 @@ int main (void)
return 0;
}
-
+#include "../../objc-obj-c++-shared/Object1-implementation.h"