Commit d764a8e6 by Iain Sandoe Committed by Nicola Pero

Added support for the 64-bit Apple Objective-C runtime

From-SVN: r170260
parent 0a8134ca
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> 2011-02-17 Joseph Myers <joseph@codesourcery.com>
* common.opt (optimize_fast): New Variable. * common.opt (optimize_fast): New Variable.
......
...@@ -629,6 +629,9 @@ darwin_cpp_builtins (cpp_reader *pfile) ...@@ -629,6 +629,9 @@ darwin_cpp_builtins (cpp_reader *pfile)
builtin_define ("__strong="); builtin_define ("__strong=");
builtin_define ("__weak="); builtin_define ("__weak=");
} }
if (flag_objc_abi == 2)
builtin_define ("__OBJC2__");
} }
/* Handle C family front-end options. */ /* Handle C family front-end options. */
......
...@@ -94,7 +94,7 @@ DEF_SECTION (mod_term_section, 0, ".mod_term_func", 0) ...@@ -94,7 +94,7 @@ DEF_SECTION (mod_term_section, 0, ".mod_term_func", 0)
DEF_SECTION (constructor_section, 0, ".constructor", 0) DEF_SECTION (constructor_section, 0, ".constructor", 0)
DEF_SECTION (destructor_section, 0, ".destructor", 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_class_section, 0, ".objc_class", 1)
DEF_SECTION (objc_meta_class_section, 0, ".objc_meta_class", 1) DEF_SECTION (objc_meta_class_section, 0, ".objc_meta_class", 1)
DEF_SECTION (objc_category_section, 0, ".objc_category", 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) ...@@ -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_protocol_section, 0, ".objc_protocol", 1)
DEF_SECTION (objc_string_object_section, 0, ".objc_string_object", 1) DEF_SECTION (objc_string_object_section, 0, ".objc_string_object", 1)
DEF_SECTION (objc_constant_string_object_section, 0, 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. */ /* Fix-and-Continue image marker. */
DEF_SECTION (objc_image_info_section, 0, DEF_SECTION (objc_image_info_section, 0,
...@@ -156,3 +156,40 @@ DEF_SECTION (darwin_exception_section, SECTION_NO_ANCHOR, ...@@ -156,3 +156,40 @@ DEF_SECTION (darwin_exception_section, SECTION_NO_ANCHOR,
DEF_SECTION (darwin_eh_frame_section, SECTION_NO_ANCHOR, DEF_SECTION (darwin_eh_frame_section, SECTION_NO_ANCHOR,
".section " EH_FRAME_SECTION_NAME ",__eh_frame" ".section " EH_FRAME_SECTION_NAME ",__eh_frame"
EH_FRAME_SECTION_ATTR, 0) 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)
...@@ -148,13 +148,48 @@ output_objc_section_asm_op (const void *directive) ...@@ -148,13 +148,48 @@ output_objc_section_asm_op (const void *directive)
objc_class_vars_section, objc_class_vars_section,
objc_instance_vars_section, objc_instance_vars_section,
objc_module_info_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; size_t i;
been_here = true; been_here = true;
if (flag_objc_abi < 2)
{
for (i = 0; i < ARRAY_SIZE (tomark); i++) for (i = 0; i < ARRAY_SIZE (tomark); i++)
switch_to_section (darwin_sections[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); switch_to_section (saved_in_section);
} }
output_section_asm_op (directive); output_section_asm_op (directive);
...@@ -277,7 +312,6 @@ indirect_data (rtx sym_ref) ...@@ -277,7 +312,6 @@ indirect_data (rtx sym_ref)
return ! lprefix; return ! lprefix;
} }
static int static int
machopic_data_defined_p (rtx sym_ref) machopic_data_defined_p (rtx sym_ref)
{ {
...@@ -1233,6 +1267,177 @@ machopic_reloc_rw_mask (void) ...@@ -1233,6 +1267,177 @@ machopic_reloc_rw_mask (void)
return MACHOPIC_INDIRECT ? 3 : 0; 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 * section *
machopic_select_section (tree decl, machopic_select_section (tree decl,
int reloc, int reloc,
...@@ -1331,7 +1536,25 @@ machopic_select_section (tree decl, ...@@ -1331,7 +1536,25 @@ machopic_select_section (tree decl,
gcc_unreachable (); 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 if (TREE_CODE (decl) == CONSTRUCTOR
&& TREE_TYPE (decl) && TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
...@@ -1341,10 +1564,17 @@ machopic_select_section (tree decl, ...@@ -1341,10 +1564,17 @@ machopic_select_section (tree decl,
if (TREE_CODE (name) == TYPE_DECL) if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name); 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 (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString"))
{ {
if (flag_next_runtime) 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]; return darwin_sections[objc_constant_string_object_section];
}
else else
return darwin_sections[objc_string_object_section]; return darwin_sections[objc_string_object_section];
} }
...@@ -1353,17 +1583,34 @@ machopic_select_section (tree decl, ...@@ -1353,17 +1583,34 @@ machopic_select_section (tree decl,
else else
return base_section; return base_section;
} }
/* c) legacy meta-data selection. */
else if (TREE_CODE (decl) == VAR_DECL else if (TREE_CODE (decl) == VAR_DECL
&& DECL_NAME (decl) && DECL_NAME (decl)
&& TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
&& IDENTIFIER_POINTER (DECL_NAME (decl)) && IDENTIFIER_POINTER (DECL_NAME (decl))
&& flag_next_runtime
&& !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "_OBJC_", 6)) && !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "_OBJC_", 6))
{ {
const char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); 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 /* We shall assert that zero-sized objects are an error in ObjC
meta-data. */ meta-data. */
gcc_assert (tree_low_cst (DECL_SIZE_UNIT (decl), 1) != 0); 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)) if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
return darwin_sections[objc_cls_meth_section]; return darwin_sections[objc_cls_meth_section];
else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23)) else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
...@@ -1911,6 +2158,30 @@ darwin_emit_weak_or_comdat (FILE *fp, tree decl, const char *name, ...@@ -1911,6 +2158,30 @@ darwin_emit_weak_or_comdat (FILE *fp, tree decl, const char *name,
assemble_zeros (size); 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: /* This routine emits 'local' storage:
When Section Anchors are off this routine emits .zerofill commands in 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, ...@@ -2042,6 +2313,7 @@ darwin_output_aligned_bss (FILE *fp, tree decl, const char *name,
{ {
unsigned int l2align; unsigned int l2align;
bool one, pub, weak; bool one, pub, weak;
tree meta;
pub = TREE_PUBLIC (decl); pub = TREE_PUBLIC (decl);
one = DECL_ONE_ONLY (decl); one = DECL_ONE_ONLY (decl);
...@@ -2058,6 +2330,14 @@ fprintf (fp, "# albss: %s (%lld,%d) ro %d cst %d stat %d com %d" ...@@ -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)); pub, weak, one, (unsigned long)DECL_INITIAL (decl));
#endif #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. */ /* Check that any initializer is valid. */
gcc_assert ((DECL_INITIAL (decl) == NULL) gcc_assert ((DECL_INITIAL (decl) == NULL)
|| (DECL_INITIAL (decl) == error_mark_node) || (DECL_INITIAL (decl) == error_mark_node)
...@@ -2152,6 +2432,8 @@ darwin_asm_output_aligned_decl_common (FILE *fp, tree decl, const char *name, ...@@ -2152,6 +2432,8 @@ darwin_asm_output_aligned_decl_common (FILE *fp, tree decl, const char *name,
{ {
unsigned int l2align; unsigned int l2align;
bool one, weak; bool one, weak;
tree meta;
/* No corresponding var. */ /* No corresponding var. */
if (decl==NULL) if (decl==NULL)
{ {
...@@ -2176,6 +2458,14 @@ fprintf (fp, "# adcom: %s (%lld,%d) ro %d cst %d stat %d com %d pub %d" ...@@ -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)); TREE_PUBLIC (decl), weak, one, (unsigned long)DECL_INITIAL (decl));
#endif #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. */ /* We shouldn't be messing with this if the decl has a section name. */
gcc_assert (DECL_SECTION_NAME (decl) == NULL); gcc_assert (DECL_SECTION_NAME (decl) == NULL);
...@@ -2222,6 +2512,7 @@ darwin_asm_output_aligned_decl_local (FILE *fp, tree decl, const char *name, ...@@ -2222,6 +2512,7 @@ darwin_asm_output_aligned_decl_local (FILE *fp, tree decl, const char *name,
{ {
unsigned long l2align; unsigned long l2align;
bool one, weak; bool one, weak;
tree meta;
one = DECL_ONE_ONLY (decl); one = DECL_ONE_ONLY (decl);
weak = (DECL_P (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" ...@@ -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)); weak , (unsigned long)DECL_INITIAL (decl));
#endif #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. */ /* We shouldn't be messing with this if the decl has a section name. */
gcc_assert (DECL_SECTION_NAME (decl) == NULL); gcc_assert (DECL_SECTION_NAME (decl) == NULL);
......
...@@ -140,6 +140,16 @@ extern GTY(()) int darwin_ms_struct; ...@@ -140,6 +140,16 @@ extern GTY(()) int darwin_ms_struct;
} while (0) } while (0)
#define SUBTARGET_C_COMMON_OVERRIDE_OPTIONS do { \ #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 \ /* Sort out ObjC exceptions: If the runtime is NeXT we default to \
sjlj for m32 only. */ \ sjlj for m32 only. */ \
if (!global_options_set.x_flag_objc_sjlj_exceptions) \ if (!global_options_set.x_flag_objc_sjlj_exceptions) \
......
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> 2011-01-17 Nicola Pero <nicola.pero@meta-innovation.com>
PR objc/47314 PR objc/47314
......
# Top level -*- makefile -*- fragment for GNU Objective-C # Top level -*- makefile -*- fragment for GNU Objective-C
# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, # 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. #This file is part of GCC.
...@@ -43,11 +43,18 @@ objc: cc1obj$(exeext) ...@@ -43,11 +43,18 @@ objc: cc1obj$(exeext)
# Tell GNU make to ignore these if they exist. # Tell GNU make to ignore these if they exist.
.PHONY: objc .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. # Use maximal warnings for this front end.
objc-warn = $(STRICT_WARN) objc-warn = $(STRICT_WARN)
# Language-specific object files for Objective C. # 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 objc_OBJS = $(OBJC_OBJS) cc1obj-checksum.o
...@@ -66,17 +73,32 @@ cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $( ...@@ -66,17 +73,32 @@ cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $(
# Objective C language specific files. # Objective C language specific files.
objc/objc-lang.o : objc/objc-lang.c \ objc/objc-lang.o : objc/objc-lang.c $(START_HDRS) \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(C_TREE_H) \ $(GGC_H) $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \
$(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(C_COMMON_H) gtype-objc.h \ c-objc-common.h
c-objc-common.h c-family/c-objc.h objc/objc-act.h
objc/objc-runtime-shared-support.o : objc/objc-runtime-shared-support.c \
objc/objc-act.o : objc/objc-act.c \ $(START_HDRS) objc/objc-runtime-shared-support.h $(OBSTACK_H) \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ objc/objc-next-metadata-tags.h gt-objc-objc-runtime-shared-support.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 \ objc/objc-gnu-runtime-abi-01.o: objc/objc-gnu-runtime-abi-01.c $(START_HDRS) \
$(LANGHOOKS_DEF_H) $(HASHTAB_H) $(C_PRAGMA_H) gt-objc-objc-act.h \ objc/objc-runtime-hooks.h $(GGC_H) \
$(GIMPLE_H) c-lang.h c-family/c-objc.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: objc.srcextra:
......
# Top level configure fragment for GNU Objective-C # Top level configure fragment for GNU Objective-C
# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2010 # Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2010,
# Free Software Foundation, Inc. # 2011 Free Software Foundation, Inc.
#This file is part of GCC. #This file is part of GCC.
...@@ -33,4 +33,4 @@ target_libs=target-libobjc ...@@ -33,4 +33,4 @@ target_libs=target-libobjc
# Most of the object files for cc1obj actually come from C. # Most of the object files for cc1obj actually come from C.
lang_requires="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"
This source diff could not be displayed because it is too large. You can view the blob instead.
/* Declarations for objc-act.c. /* Declarations for objc-act.c.
Copyright (C) 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 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. This file is part of GCC.
...@@ -28,8 +28,6 @@ bool objc_init (void); ...@@ -28,8 +28,6 @@ bool objc_init (void);
const char *objc_printable_name (tree, int); const char *objc_printable_name (tree, int);
tree objc_fold_obj_type_ref (tree, tree); tree objc_fold_obj_type_ref (tree, tree);
int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *); 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 /* NB: The remaining public functions are prototyped in c-common.h, for the
benefit of stub-objc.c and objc-act.c. */ benefit of stub-objc.c and objc-act.c. */
...@@ -167,6 +165,8 @@ typedef enum objc_property_assign_semantics { ...@@ -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 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 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_NAME(CLASS) ((CLASS)->type.name)
#define PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0) #define PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0)
#define PROTOCOL_NST_METHODS(CLASS) ((CLASS)->type.minval) #define PROTOCOL_NST_METHODS(CLASS) ((CLASS)->type.minval)
...@@ -176,7 +176,6 @@ typedef enum objc_property_assign_semantics { ...@@ -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_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) #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 */ /* 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) #define CLASS_PROPERTY_DECL(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 6)
/* For CLASS_IMPLEMENTATION_TYPE or CATEGORY_IMPLEMENTATION_TYPE. */ /* For CLASS_IMPLEMENTATION_TYPE or CATEGORY_IMPLEMENTATION_TYPE. */
...@@ -215,6 +214,7 @@ typedef enum objc_property_assign_semantics { ...@@ -215,6 +214,7 @@ typedef enum objc_property_assign_semantics {
= make_tree_vec (OBJC_INFO_SLOT_ELTS); \ = make_tree_vec (OBJC_INFO_SLOT_ELTS); \
} \ } \
while (0) while (0)
#define DUP_TYPE_OBJC_INFO(DST, SRC) \ #define DUP_TYPE_OBJC_INFO(DST, SRC) \
do \ do \
{ \ { \
...@@ -244,20 +244,21 @@ struct GTY(()) hashed_attribute { ...@@ -244,20 +244,21 @@ struct GTY(()) hashed_attribute {
attr next; attr next;
tree value; tree value;
}; };
struct GTY(()) hashed_entry { struct GTY(()) hashed_entry {
attr list; attr list;
hash next; hash next;
tree key; tree key;
}; };
#define SIZEHASHTABLE 257
extern GTY ((length ("SIZEHASHTABLE"))) hash *nst_method_hash_list; extern GTY ((length ("SIZEHASHTABLE"))) hash *nst_method_hash_list;
extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_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 *cls_name_hash_list;
extern GTY ((length ("SIZEHASHTABLE"))) hash *als_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 /* An array of all the local variables in the current function that
need to be marked as volatile. */ need to be marked as volatile. */
extern GTY(()) VEC(tree,gc) *local_variables_to_volatilize; extern GTY(()) VEC(tree,gc) *local_variables_to_volatilize;
...@@ -268,8 +269,8 @@ struct GTY(()) imp_entry { ...@@ -268,8 +269,8 @@ struct GTY(()) imp_entry {
struct imp_entry *next; struct imp_entry *next;
tree imp_context; tree imp_context;
tree imp_template; tree imp_template;
tree class_decl; /* _OBJC_CLASS_<my_name>; */ tree class_decl; /* _OBJC[_v2]_CLASS/CATEGORY_<my_name>; */
tree meta_decl; /* _OBJC_METACLASS_<my_name>; */ tree meta_decl; /* _OBJC[_v2]_METACLASS_<my_name>; */
BOOL_BITFIELD has_cxx_cdtors : 1; BOOL_BITFIELD has_cxx_cdtors : 1;
}; };
...@@ -361,6 +362,7 @@ enum objc_tree_index ...@@ -361,6 +362,7 @@ enum objc_tree_index
OCTI_STRING_CLASS_DECL, OCTI_STRING_CLASS_DECL,
OCTI_INTERNAL_CNST_STR_TYPE, OCTI_INTERNAL_CNST_STR_TYPE,
OCTI_SUPER_DECL, OCTI_SUPER_DECL,
OCTI_SUPER_SUPERFIELD_ID,
OCTI_UMSG_NONNIL_DECL, OCTI_UMSG_NONNIL_DECL,
OCTI_UMSG_NONNIL_STRET_DECL, OCTI_UMSG_NONNIL_STRET_DECL,
OCTI_STORAGE_CLS, OCTI_STORAGE_CLS,
...@@ -394,6 +396,10 @@ enum objc_tree_index ...@@ -394,6 +396,10 @@ enum objc_tree_index
OCTI_GET_PROPERTY_STRUCT_DECL, OCTI_GET_PROPERTY_STRUCT_DECL,
OCTI_SET_PROPERTY_STRUCT_DECL, OCTI_SET_PROPERTY_STRUCT_DECL,
/* "V1" stuff. */
OCTI_V1_PROP_LIST_TEMPL,
OCTI_V1_PROP_NAME_ATTR_CHAIN,
OCTI_MAX OCTI_MAX
}; };
...@@ -433,14 +439,17 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; ...@@ -433,14 +439,17 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
(TREE_CODE (TYPE) == POINTER_TYPE \ (TREE_CODE (TYPE) == POINTER_TYPE \
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TYPE)) \ && (TYPE_MAIN_VARIANT (TREE_TYPE (TYPE)) \
== TREE_TYPE (objc_object_type))) == TREE_TYPE (objc_object_type)))
#define IS_CLASS(TYPE) \ #define IS_CLASS(TYPE) \
(TREE_CODE (TYPE) == POINTER_TYPE \ (TREE_CODE (TYPE) == POINTER_TYPE \
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TYPE)) \ && (TYPE_MAIN_VARIANT (TREE_TYPE (TYPE)) \
== TREE_TYPE (objc_class_type))) == TREE_TYPE (objc_class_type)))
#define IS_PROTOCOL_QUALIFIED_UNTYPED(TYPE) \ #define IS_PROTOCOL_QUALIFIED_UNTYPED(TYPE) \
((IS_ID (TYPE) || IS_CLASS (TYPE)) \ ((IS_ID (TYPE) || IS_CLASS (TYPE)) \
&& TYPE_HAS_OBJC_INFO (TREE_TYPE (TYPE)) \ && TYPE_HAS_OBJC_INFO (TREE_TYPE (TYPE)) \
&& TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (TYPE))) && TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (TYPE)))
#define IS_SUPER(TYPE) \ #define IS_SUPER(TYPE) \
(TREE_CODE (TYPE) == POINTER_TYPE \ (TREE_CODE (TYPE) == POINTER_TYPE \
&& TREE_TYPE (TYPE) == objc_super_template) && TREE_TYPE (TYPE) == objc_super_template)
...@@ -549,13 +558,19 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; ...@@ -549,13 +558,19 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define objc_class_id objc_global_trees[OCTI_CLS_ID] #define objc_class_id objc_global_trees[OCTI_CLS_ID]
#define objc_object_name objc_global_trees[OCTI_ID_NAME] #define objc_object_name objc_global_trees[OCTI_ID_NAME]
#define objc_class_name objc_global_trees[OCTI_CLASS_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_id objc_global_trees[OCTI_CNST_STR_ID]
#define constant_string_type objc_global_trees[OCTI_CNST_STR_TYPE] #define constant_string_type objc_global_trees[OCTI_CNST_STR_TYPE]
#define constant_string_global_id \ #define constant_string_global_id \
objc_global_trees[OCTI_CNST_STR_GLOB_ID] objc_global_trees[OCTI_CNST_STR_GLOB_ID]
#define string_class_decl objc_global_trees[OCTI_STRING_CLASS_DECL] #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 internal_const_str_type objc_global_trees[OCTI_INTERNAL_CNST_STR_TYPE]
#define UOBJC_SUPER_decl objc_global_trees[OCTI_SUPER_DECL] #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 \ #define objc_fast_enumeration_state_template \
objc_global_trees[OCTI_FAST_ENUM_STATE_TEMP] objc_global_trees[OCTI_FAST_ENUM_STATE_TEMP]
#define objc_enumeration_mutation_decl \ #define objc_enumeration_mutation_decl \
...@@ -566,8 +581,165 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX]; ...@@ -566,8 +581,165 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define objc_getProperty_decl objc_global_trees[OCTI_GET_PROPERTY_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_setProperty_decl objc_global_trees[OCTI_SET_PROPERTY_DECL]
#define objc_copyStruct_decl objc_global_trees[OCTI_COPY_STRUCT_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_getPropertyStruct_decl \
#define objc_setPropertyStruct_decl objc_global_trees[OCTI_SET_PROPERTY_STRUCT_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 */ #endif /* GCC_OBJC_ACT_H */
/* 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"
/* Language-dependent hooks for Objective-C. /* 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. Free Software Foundation, Inc.
Contributed by Ziemowit Laski <zlaski@apple.com> Contributed by Ziemowit Laski <zlaski@apple.com>
...@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h" #include "langhooks.h"
#include "langhooks-def.h" #include "langhooks-def.h"
#include "c-objc-common.h" #include "c-objc-common.h"
#include "c-lang.h"
enum c_language_kind c_language = clk_objc; enum c_language_kind c_language = clk_objc;
static void objc_init_ts (void); static void objc_init_ts (void);
...@@ -51,13 +52,6 @@ static void objc_init_ts (void); ...@@ -51,13 +52,6 @@ static void objc_init_ts (void);
#undef LANG_HOOKS_INIT_TS #undef LANG_HOOKS_INIT_TS
#define LANG_HOOKS_INIT_TS objc_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. */ /* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
......
/* 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));
/* 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"
This source diff could not be displayed because it is too large. You can view the blob instead.
/* 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_ */
/* 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"
/* 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_ */
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> 2011-02-07 Mike Stump <mikestump@comcast.net>
* Make-lang.in (obj-c++.tags): Don't include *.y. * Make-lang.in (obj-c++.tags): Don't include *.y.
......
# Top level -*- makefile -*- fragment for GNU Objective-C++ # 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. # Free Software Foundation, Inc.
# Contributed by Ziemowit Laski <zlaski@apple.com> # Contributed by Ziemowit Laski <zlaski@apple.com>
...@@ -44,12 +44,19 @@ obj-c++: cc1objplus$(exeext) ...@@ -44,12 +44,19 @@ obj-c++: cc1objplus$(exeext)
# Tell GNU make to ignore these if they exist. # Tell GNU make to ignore these if they exist.
.PHONY: obj-c++ .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++ # Use maximal warnings for this front end. Also, make ObjC and C++
# headers accessible. # headers accessible.
objcp-warn = $(STRICT_WARN) -DOBJCPLUS -I$(srcdir)/objc -I$(srcdir)/cp objcp-warn = $(STRICT_WARN) -DOBJCPLUS -I$(srcdir)/objc -I$(srcdir)/cp
# Language-specific object files for Objective C++. # Language-specific object files for Objective C++.
OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.o objcp/objcp-decl.o \ 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) $(CXX_AND_OBJCXX_OBJS)
obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o
...@@ -69,23 +76,48 @@ cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBDEPS) ...@@ -69,23 +76,48 @@ cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBDEPS)
# Objective C++ language specific files. # Objective C++ language specific files.
objcp/objcp-lang.o : objcp/objcp-lang.c \ objcp/objcp-lang.o : objcp/objcp-lang.c $(START_HDRS) \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) \ $(C_COMMON_H) $(LANGHOOKS_DEF_H) cp/cp-objcp-common.h \
$(C_COMMON_H) $(LANGHOOKS_DEF_H) objc/objc-act.h cp/cp-objcp-common.h \ $(TARGET_H) gtype-objcp.h
$(TARGET_H) gtype-objcp.h c-family/c-objc.h
objcp/objcp-decl.o : objcp/objcp-decl.c \ objcp/objcp-decl.o : objcp/objcp-decl.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) \ $(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 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 # The following must be an explicit rule; please keep in sync with the implicit
# one in Makefile.in. # one in Makefile.in.
objcp/objcp-act.o : objc/objc-act.c \ objcp/objcp-act.o : objc/objc-act.c $(START_HDRS) $(GGC_H) \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) $(TM_P_H) \ $(RTL_H) $(EXPR_H) $(TARGET_H) $(DIAGNOSTIC_H) toplev.h $(FLAGS_H) \
$(EXPR_H) $(TARGET_H) $(CXX_TREE_H) $(DIAGNOSTIC_H) toplev.h $(FLAGS_H) \ input.h $(FUNCTION_H) output.h debug.h $(OBSTACK_H) \
objc/objc-act.h input.h $(FUNCTION_H) output.h debug.h langhooks.h \
objcp/objcp-decl.h $(LANGHOOKS_DEF_H) $(HASHTAB_H) gt-objc-objc-act.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) $< \ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
$(OUTPUT_OPTION) $(OUTPUT_OPTION)
......
# Top level configure fragment for GNU Objective-C++. # 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> # Contributed by Ziemowit Laski <zlaski@apple.com>
#This file is part of GCC. #This file is part of GCC.
...@@ -37,4 +37,4 @@ build_by_default="no" ...@@ -37,4 +37,4 @@ build_by_default="no"
lang_requires="objc c++" lang_requires="objc c++"
subdir_requires="objc cp" 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 "
/* Language-dependent hooks for Objective-C++. /* 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> Contributed by Ziemowit Laski <zlaski@apple.com>
This file is part of GCC. This file is part of GCC.
...@@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License ...@@ -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 along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "coretypes.h" #include "coretypes.h"
...@@ -35,7 +34,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -35,7 +34,6 @@ along with GCC; see the file COPYING3. If not see
enum c_language_kind c_language = clk_objcxx; enum c_language_kind c_language = clk_objcxx;
static void objcxx_init_ts (void); 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; /* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h;
consequently, there should be very few hooks below. */ consequently, there should be very few hooks below. */
...@@ -48,10 +46,6 @@ static tree objcxx_eh_personality (void); ...@@ -48,10 +46,6 @@ static tree objcxx_eh_personality (void);
#define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
#undef LANG_HOOKS_INIT_TS #undef LANG_HOOKS_INIT_TS
#define LANG_HOOKS_INIT_TS objcxx_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. */ /* Each front end provides its own lang hook initializer. */
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
...@@ -145,14 +139,4 @@ objcxx_init_ts (void) ...@@ -145,14 +139,4 @@ objcxx_init_ts (void)
init_shadowed_var_for_decl (); 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" #include "gtype-objcp.h"
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> 2011-02-17 Jakub Jelinek <jakub@redhat.com>
PR c++/47783 PR c++/47783
......
// A basic sanity check for Objective-C++. // A basic sanity check for Objective-C++.
// { dg-do run } // { dg-do run }
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ /* { 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 <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 @interface Greeter : Object
- (void) greet: (const char *)msg; - (void) greet: (const char *)msg;
@end @end
@implementation Greeter @implementation Greeter
- (void) greet: (const char *)msg { std::cout << msg; } - (void) greet: (const char *)msg
{ std::cout << msg << __VERSION__ << std::endl;}
@end @end
int int
main () main ()
{ {
std::cout << "Hello from C++\n"; std::cout << "Hello from C++" << __VERSION__ << std::endl;
Greeter *obj = [Greeter new]; 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"
...@@ -22,5 +22,8 @@ void foo(void) { ...@@ -22,5 +22,8 @@ void foo(void) {
obj = [ObjectAlias2 new]; obj = [ObjectAlias2 new];
} }
/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */ /* { dg-final { scan-assembler "_OBJC_ClassRefs_0" { target { *-*-darwin* && { ! lp64 } } } } } */
/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_1" } } */ /* { 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 } } } } } */
...@@ -19,9 +19,16 @@ ...@@ -19,9 +19,16 @@
int int
main() 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) descriptionForInstanceMethod: @selector(name)];
[@protocol(NoInstanceMethods) descriptionForClassMethod: @selector(name)]; [@protocol(NoInstanceMethods) descriptionForClassMethod: @selector(name)];
[@protocol(NoClassMethods) descriptionForInstanceMethod: @selector(name)]; [@protocol(NoClassMethods) descriptionForInstanceMethod: @selector(name)];
[@protocol(NoClassMethods) descriptionForClassMethod: @selector(name)]; [@protocol(NoClassMethods) descriptionForClassMethod: @selector(name)];
#endif
return 0; return 0;
} }
...@@ -29,6 +29,7 @@ extern struct objc_class _NSConstantStringClassReference; ...@@ -29,6 +29,7 @@ extern struct objc_class _NSConstantStringClassReference;
const NSConstantString *appKey = @"MyApp"; 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 ".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 } } } } } */
...@@ -29,6 +29,7 @@ extern struct objc_class _XStrClassReference; ...@@ -29,6 +29,7 @@ extern struct objc_class _XStrClassReference;
const XStr *appKey = @"MyApp"; 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 ".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 ".quad\t_OBJC_CLASS_._XStr\n\t.quad\t.*\n\t.long\t5\n\t.space" { target { *-*-darwin* && { lp64 } } } } } */
...@@ -21,6 +21,7 @@ extern struct objc_class _NSConstantStringClassReference; ...@@ -21,6 +21,7 @@ extern struct objc_class _NSConstantStringClassReference;
const NSConstantString *appKey = @"MyApp"; 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 ".long\t__NSConstantStringClassReference\n\t.long\t.*\n\t.long\t5\n\t.data" { target { *-*-darwin* && { ! lp64 } } }} } */ /* { dg-final { scan-assembler ".section __DATA, __objc_stringobj" { 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 ".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 } } } } } */
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
/* Developed by Ziemowit Laski <zlaski@apple.com>. */ /* Developed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */ /* { 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-xfail-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" "-fgnu-runtime" } { "" } }
/* { dg-options "-fobjc-exceptions" } */ /* { dg-options "-fobjc-exceptions" } */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
/* Developed by Ziemowit Laski <zlaski@apple.com>. */ /* Developed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do run } */ /* { 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-xfail-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" "-fgnu-runtime" } { "" } }
/* { dg-prune-output ".*internal compiler error.*" } */ /* { dg-prune-output ".*internal compiler error.*" } */
/* { dg-options "-fobjc-exceptions -O2" } */ /* { dg-options "-fobjc-exceptions -O2" } */
......
...@@ -2,16 +2,15 @@ ...@@ -2,16 +2,15 @@
/* { dg-do run { target *-*-darwin* } } */ /* { dg-do run { target *-*-darwin* } } */
/* { dg-require-effective-target lp64 } */ /* { dg-require-effective-target lp64 } */
/* { dg-options "-Wno-deprecated-declarations" } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */ /* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-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 <stdbool.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <objc/Object.h>
#include "../objc-obj-c++-shared/next-mapping.h"
#define CHECK_IF(E) if (!(E)) abort () #define CHECK_IF(E) if (!(E)) abort ()
@class NSDictionary, NSFont, NSError, _NSATSTypesetterGuts, NSString, NSMenu, NSArray; @class NSDictionary, NSFont, NSError, _NSATSTypesetterGuts, NSString, NSMenu, NSArray;
...@@ -195,69 +194,70 @@ NSRange globalRange; ...@@ -195,69 +194,70 @@ NSRange globalRange;
int main(void) { int main(void) {
Class fooClass = objc_getClass ("Foo"); Class fooClass = objc_getClass ("Foo");
Method meth; Method meth;
struct objc_ivar_list *ivars; Ivar *ivars;
struct objc_ivar *ivar; unsigned int ivar_count;
Ivar ivar;
meth = class_getInstanceMethod (fooClass, @selector(_errorWithOSStatus:ref1:ref2:reading:)); 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:)); 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:)); 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:)); 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:)); 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:)); 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:)); 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:)); 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:)); 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)); 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:)); 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:)); 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:)); 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:)); 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)); 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:)); 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:)); 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:)); 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; ivars = class_copyIvarList (fooClass, &ivar_count);
CHECK_IF (ivars->ivar_count == 1); CHECK_IF (ivar_count == 1);
ivar = ivars->ivar_list; ivar = ivars[0];
CHECK_IF (!strcmp (ivar->ivar_name, "r")); CHECK_IF (!strcmp (ivar_getName(ivar), "r"));
CHECK_IF (!strcmp (ivar->ivar_type, CHECK_IF (!strcmp (ivar_getTypeEncoding(ivar),
"{?=\"_attributes\"@\"NSDictionary\"\"_font\"@\"NSFont\"\"_characterLength\"" "{?=\"_attributes\"@\"NSDictionary\"\"_font\"@\"NSFont\"\"_characterLength\""
"Q\"_nominalGlyphLocation\"Q\"p\"^Q\"_defaultLineHeight\"f\"_defaultBaselineOffset\"" "Q\"_nominalGlyphLocation\"Q\"p\"^Q\"_defaultLineHeight\"f\"_defaultBaselineOffset\""
"f\"_horizExpansion\"f\"_baselineDelta\"f\"_attachmentBBox\"{_NSRect=\"origin\"" "f\"_horizExpansion\"f\"_baselineDelta\"f\"_attachmentBBox\"{_NSRect=\"origin\""
......
...@@ -7,13 +7,19 @@ ...@@ -7,13 +7,19 @@
/* { dg-skip-if "NeXT-only" { *-*-* } { "-fgnu-runtime" } { "" } } */ /* { dg-skip-if "NeXT-only" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-freplace-objc-classes" } */ /* { dg-options "-freplace-objc-classes" } */
#include "../objc-obj-c++-shared/Object1.h"
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/Object.h>
extern void abort(void); extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort(); #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 { @interface Base: Object {
@public @public
int a; int a;
...@@ -33,4 +39,5 @@ extern void abort(void); ...@@ -33,4 +39,5 @@ extern void abort(void);
} }
@end @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 } } } } } */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ /* { 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 <stdlib.h>
#include "../objc-obj-c++-shared/Object1.h" #include "../objc-obj-c++-shared/Object1.h"
...@@ -53,5 +54,3 @@ int main(void) { ...@@ -53,5 +54,3 @@ int main(void) {
return 0; return 0;
} }
#include "../objc-obj-c++-shared/Object1-implementation.h"
...@@ -22,5 +22,5 @@ void foo(void) { ...@@ -22,5 +22,5 @@ void foo(void) {
obj = [ObjectAlias2 new]; obj = [ObjectAlias2 new];
} }
/* { dg-final { scan-assembler "_OBJC_CLASS_REFERENCES_0" } } */ /* { dg-final { scan-assembler "_OBJC_ClassRefs_0" } } */
/* { dg-final { scan-assembler-not "_OBJC_CLASS_REFERENCES_1" } } */ /* { dg-final { scan-assembler-not "_OBJC_ClassRefs_1" } } */
/* Test that the correct version number (6) is set in the module descriptor /* Test that the correct version number (6) is set in the module descriptor
when compiling for the NeXT runtime. */ when compiling for the NeXT runtime ABI=0 - and that the MODULE descriptor
/* Author: Ziemowit Laski <zlaski@apple.com> */ 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-do compile { target *-*-darwin* } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */ /* { 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
@interface FooBar: Object
- (void)boo; - (void)boo;
@end @end
...@@ -15,5 +16,5 @@ ...@@ -15,5 +16,5 @@
- (void)boo { } - (void)boo { }
@end @end
/* { dg-final { scan-assembler "L_OBJC_MODULES:\n\[ \t\]*\.long\t6\n" { target { *-*-darwin* && { ! lp64 } } } } } */ /* { dg-final { scan-assembler "L_OBJC_Module:\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-not "L_OBJC_Module" { target { *-*-darwin* && { lp64 } } } } } */
...@@ -3,10 +3,19 @@ ...@@ -3,10 +3,19 @@
/* { dg-do run } */ /* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ /* { 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" #include <objc/Protocol.h>
#import "../objc-obj-c++-shared/Protocol1.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 @protocol A
@end @end
......
...@@ -5,7 +5,11 @@ ...@@ -5,7 +5,11 @@
@interface TestClass @interface TestClass
{ {
#ifdef __OBJC2__
Class isa;
#else
id isa; id isa;
#endif
} }
- (int)D; - (int)D;
@end @end
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
/* { dg-do run } */ /* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
#import "../../objc-obj-c++-shared/next-mapping.h"
#include <objc/objc.h> #include <objc/objc.h>
#ifndef __NEXT_RUNTIME__ #ifndef __NEXT_RUNTIME__
#include <objc/objc-api.h> #include <objc/objc-api.h>
#endif #endif
#include "../../objc-obj-c++-shared/next-mapping.h"
extern void abort (void); extern void abort (void);
...@@ -73,5 +73,3 @@ int main (void) ...@@ -73,5 +73,3 @@ int main (void)
return 0; return 0;
} }
#import "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
/* { dg-do compile { target { *-*-darwin* } } } */ /* { dg-do compile { target { *-*-darwin* } } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */ /* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
#include "../objc-obj-c++-shared/Object1.h" #include <objc/Object.h>
@interface Base: Object @interface Base: Object
- (void)setValues; - (void)setValues;
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
-(void)checkValues { } -(void)checkValues { }
@end @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.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.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-not "L_OBJC_Symbols" { target { *-*-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-do run } */ /* { dg-do run } */
/* See if -forward::/-performv:: is able to work. */ /* See if -forward::/-performv:: is able to work. */
/* { dg-xfail-run-if "PR36610" { ! { { i?86-*-* x86_64-*-* } && ilp32 } } { "-fgnu-runtime" } { "" } } */ /* { 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 <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#import "../../objc-obj-c++-shared/Object1.h" #ifndef __NEXT_RUNTIME__
#import "../../objc-obj-c++-shared/next-mapping.h" # include <objc/objc-api.h>
#include <objc/objc-api.h> #endif
#include <objc/Object.h>
#define VALUETOUSE 1234567890 #define VALUETOUSE 1234567890
......
...@@ -29,6 +29,7 @@ extern Class _NSConstantStringClassReference; ...@@ -29,6 +29,7 @@ extern Class _NSConstantStringClassReference;
const NSConstantString *appKey = @"MyApp"; 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 ".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 } } } } } */
...@@ -29,6 +29,7 @@ extern Class _XStrClassReference; ...@@ -29,6 +29,7 @@ extern Class _XStrClassReference;
const XStr *appKey = @"MyApp"; 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 ".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 } } } } } */
...@@ -21,6 +21,7 @@ Class _NSConstantStringClassReference; ...@@ -21,6 +21,7 @@ Class _NSConstantStringClassReference;
const NSConstantString *appKey = @"MyApp"; 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 ".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 } } } } } */
...@@ -25,6 +25,7 @@ int main(void) { ...@@ -25,6 +25,7 @@ int main(void) {
return 0; 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" } } */ /* { dg-final { scan-assembler "objc_getClass" } } */
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */ /* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-fno-zero-link" } */ /* { dg-options "-fno-zero-link" } */
#include "../objc-obj-c++-shared/Object1.h" #include <objc/Object.h>
#include <objc/objc.h>
extern void abort(void); extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort(); #define CHECK_IF(expr) if(!(expr)) abort();
...@@ -25,5 +24,6 @@ int main(void) { ...@@ -25,5 +24,6 @@ int main(void) {
return 0; 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" } } */ /* { dg-final { scan-assembler-not "objc_getClass" } } */
/* Contributed by Nicola Pero - Thu Mar 8 16:27:46 CET 2001 */ /* Contributed by Nicola Pero - Thu Mar 8 16:27:46 CET 2001 */
#include <stdlib.h> #include <stdlib.h>
#import "../../objc-obj-c++-shared/Object1.h" #ifndef __NEXT_RUNTIME__
#include <objc/objc-api.h> #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 /* Test that by using -> we can access ivars of other objects of the same
class */ class */
...@@ -53,3 +55,4 @@ int main (void) ...@@ -53,3 +55,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define objc_get_class(C) objc_getClass(C) #define objc_get_class(C) objc_getClass(C)
#endif #endif
#ifndef __OBJC2__
void print_ivars (Class class) void print_ivars (Class class)
{ {
struct objc_ivar_list* ivars = class->ivars; struct objc_ivar_list* ivars = class->ivars;
...@@ -61,9 +62,11 @@ void compare_structures (Class class, const char* type) ...@@ -61,9 +62,11 @@ void compare_structures (Class class, const char* type)
printf ("%d ivars checked\n", i); printf ("%d ivars checked\n", i);
} }
#endif
int main () int main ()
{ {
#ifndef __OBJC2__
struct class_vars struct class_vars
{ {
@defs (MyObject); @defs (MyObject);
...@@ -80,8 +83,10 @@ int main () ...@@ -80,8 +83,10 @@ int main ()
printf ("sizes don't match (computed %d, exact %d)\n", size1, size2); printf ("sizes don't match (computed %d, exact %d)\n", size1, size2);
abort (); abort ();
} }
#endif
exit (0); exit (0);
} }
#ifndef __OBJC2__
#include "../../objc-obj-c++-shared/objc-test-suite-next-encode-assist-impl.h" #include "../../objc-obj-c++-shared/objc-test-suite-next-encode-assist-impl.h"
#endif
...@@ -27,5 +27,4 @@ int main (void) ...@@ -27,5 +27,4 @@ int main (void)
exit (0); exit (0);
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -24,6 +24,12 @@ extern int printf (const char *, ...); ...@@ -24,6 +24,12 @@ extern int printf (const char *, ...);
/* This no-op class to keep it compile under broken gcc 3.x */ /* This no-op class to keep it compile under broken gcc 3.x */
@interface MyObject : Object <MyProtocol> @interface MyObject : Object <MyProtocol>
#ifdef __OBJC2__
+ (id) initialize;
+ (id) alloc;
+ + new;
- - init;
#endif
@end @end
@implementation MyObject @implementation MyObject
...@@ -31,6 +37,12 @@ extern int printf (const char *, ...); ...@@ -31,6 +37,12 @@ extern int printf (const char *, ...);
{ {
return [MyObject alloc]; return [MyObject alloc];
} }
#ifdef __OBJC2__
+ initialize {return self;}
+ alloc { return class_createInstance (self, 0);}
+ new { return [[self alloc] init]; }
- init {return self;}
#endif
@end @end
/* The following header, together with the implementation included below, /* The following header, together with the implementation included below,
......
/* Contributed by Nicola Pero on Tue Mar 6 23:05:53 CET 2001 */ /* Contributed by Nicola Pero on Tue Mar 6 23:05:53 CET 2001 */
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "../../objc-obj-c++-shared/Object1.h" #include "../../objc-obj-c++-shared/Object1.h"
#include <objc/objc.h> #include <objc/objc.h>
......
/* Contributed by Nicola Pero on Tue Mar 6 23:05:53 CET 2001 */ /* Contributed by Nicola Pero on Tue Mar 6 23:05:53 CET 2001 */
#include <objc/objc.h> #include <objc/objc.h>
#include <objc/objc-api.h> #include <objc/objc-api.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/* /*
......
...@@ -10,3 +10,4 @@ int main (void) ...@@ -10,3 +10,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -48,3 +48,4 @@ int main (void) ...@@ -48,3 +48,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -50,3 +50,4 @@ int main (void) ...@@ -50,3 +50,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -74,3 +74,4 @@ int main (void) { ...@@ -74,3 +74,4 @@ int main (void) {
test((Object *)-1); test((Object *)-1);
return 0; return 0;
} }
#import "../../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -28,6 +28,7 @@ lappend additional_flags "-fobjc-exceptions" ...@@ -28,6 +28,7 @@ lappend additional_flags "-fobjc-exceptions"
# load support procs # load support procs
load_lib objc-torture.exp load_lib objc-torture.exp
load_lib torture-options.exp load_lib torture-options.exp
load_lib target-supports.exp
torture-init torture-init
objc-set-runtime-options "execute" "additional_flags=-fobjc-exceptions" objc-set-runtime-options "execute" "additional_flags=-fobjc-exceptions"
......
#include <stdio.h> #include <stdio.h>
#include <stdlib.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" #import "../../../objc-obj-c++-shared/Object1.h"
#endif
static int made_try = 0; static int made_try = 0;
...@@ -57,3 +73,4 @@ main(int ac, char *av[]) ...@@ -57,3 +73,4 @@ main(int ac, char *av[])
abort (); abort ();
return 0; return 0;
} }
//#import "../../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -2,11 +2,32 @@ ...@@ -2,11 +2,32 @@
/* Developed by Marcin Koziej <creep@desk.pl>. */ /* Developed by Marcin Koziej <creep@desk.pl>. */
#include <stdlib.h> #include <stdlib.h>
#import "../../../objc-obj-c++-shared/Object1.h" #include <objc/Object.h>
#ifndef __NEXT_RUNTIME__
#import <objc/objc-api.h> #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; static int i;
__attribute__((objc_exception))
@interface Thrower : Object @interface Thrower : Object
- - forward: (SEL) s : (void*) a; - - forward: (SEL) s : (void*) a;
@end @end
...@@ -16,8 +37,10 @@ static int i; ...@@ -16,8 +37,10 @@ static int i;
{ {
i++; i++;
@throw [Object new]; @throw [Object new];
return nil;
} }
@end @end
int int
main() main()
{ {
......
...@@ -60,3 +60,4 @@ int main(void) { ...@@ -60,3 +60,4 @@ int main(void) {
foo(15, &gf1); foo(15, &gf1);
return 0; return 0;
} }
#import "../../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -42,4 +42,4 @@ int main (void) ...@@ -42,4 +42,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -43,4 +43,4 @@ int main (void) ...@@ -43,4 +43,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -56,4 +56,4 @@ int main (void) ...@@ -56,4 +56,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -38,4 +38,4 @@ int main (void) ...@@ -38,4 +38,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
/* Contributed by Nicola Pero - Fri Mar 9 21:35:47 CET 2001 */ /* Contributed by Nicola Pero - Fri Mar 9 21:35:47 CET 2001 */
#include <stdlib.h> #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 */ /* Test defining a protocol, and accessing it using @protocol */
...@@ -35,4 +36,3 @@ int main (void) ...@@ -35,4 +36,3 @@ int main (void)
return 0; return 0;
} }
/* Contributed by Nicola Pero - Fri Mar 9 21:35:47 CET 2001 */ /* Contributed by Nicola Pero - Fri Mar 9 21:35:47 CET 2001 */
#include <stdlib.h> #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 */ /* Test defining a protocol, and accessing it using @protocol */
......
...@@ -41,4 +41,4 @@ int main (void) ...@@ -41,4 +41,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
...@@ -39,3 +39,4 @@ int main (void) ...@@ -39,3 +39,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
/* Contributed by Nicola Pero - Tue Jul 3 10:55:21 BST 2001 */ /* Contributed by Nicola Pero - Tue Jul 3 10:55:21 BST 2001 */
#import "../../objc-obj-c++-shared/next-mapping.h" #ifdef __NEXT_RUNTIME__
#import "../../objc-obj-c++-shared/Object1.h" # include "../../objc-obj-c++-shared/next-mapping.h"
#include <objc/objc.h> #else
#include <objc/objc-api.h> # 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 */ /* This test demonstrate a failure in object_is_class which was fixed */
...@@ -41,3 +43,4 @@ int main (void) ...@@ -41,3 +43,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
/* Contributed by Nicola Pero - Tue Jul 3 10:55:21 BST 2001 */ /* Contributed by Nicola Pero - Tue Jul 3 10:55:21 BST 2001 */
#import "../../objc-obj-c++-shared/Object1.h" #ifdef __NEXT_RUNTIME__
#import "../../objc-obj-c++-shared/next-mapping.h" # include "../../objc-obj-c++-shared/next-mapping.h"
#include <objc/objc-api.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 */ /* This test demonstrate a failure in object_is_meta_class which was fixed */
...@@ -38,4 +41,4 @@ int main (void) ...@@ -38,4 +41,4 @@ int main (void)
return 0; return 0;
} }
#include "../../objc-obj-c++-shared/Object1-implementation.h"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment