Commit 058bfe53 by Iain Sandoe

make ObjC do LTO.

gcc/
	PR objc/44140
	* config/darwin.c (output_objc_section_asm_op): Save and restore
	section when outputting ObjC section list.

testsuite/

	PR objc/44140
	* objc.dg/lto/trivial-1_0.m: New.
	* objc.dg/lto/lto.exp: New.
	* obj-c++.dg/lto/trivial-1_0.mm: New.
	* obj-c++.dg/lto/lto.exp: New.
	* objc.dg/symtab-1.m: Adjust sizes.
	* objc.dg/image-info.m: Do not run for gnu-runtime.

gcc/objc/

	PR objc/44140
	* objc-act.c: build_objc_string_decl() remove declaration.
	(finish_var_decl): Remove forcing of var output and marking
	as "Used". 
	(init_def_list): Use integer_zero_node. 
	(init_objc_symtab): Use integer_zero_node, make the short
	integer type specific on relevant nodes.
	(generate_objc_symtab_decl): Remove call to 
	forward_declare_categories().  Use null_pointer_node where
	appropriate.  
	(build_module_descriptor): Comment and mark this item as 
	DECL_PRESERVE_P. 
	(generate_static_references): Use gcc_unreachable instead of
	abort (). 
	(diagnose_missing_method): New.
	(build_next_selector_translation_table): New.
	(build_gnu_selector_translation_table): New.
	(add_objc_string): Merge code from build_objc_string_decl...
	... and delete build_objc_string_decl().
	(generate_dispatch_table): Make integer types explicit.
	(generate_category): Pass implent and arrange for the data
	to be extracted within the routine.  Do not start new vars, 
	but finish the ones collcted during parsing.
	(generate_shared_structures): Likewise.
	(finish_objc):  Reorder code so that we finish variables before
	referencing them.  Save the global data before calling meta-data
	creation routines, and pass the current reference to the two 
	main routines.  Only call generate_objc_image_info () for the 
	NeXT runtime.
	(generate_classref_translation_entry): Comment on and make this
	item DECL_PRESERVE_P.
	(handle_class_ref): Use varpool interfaces, comment on and make
	this item DECL_PRESERVE_P.
	(handle_impent): Likewise.
	(generate_objc_image_info): Only generate when the content is 
	non-zero.  Make integer types explict.

From-SVN: r162030
parent 0571e6db
2010-07-10 Iain Sandoe <iains@gcc.gnu.org>
PR objc/44140
* config/darwin.c (output_objc_section_asm_op): Save and restore
section when outputting ObjC section list.
2010-07-09 Jan Hubicka <jh@suse.cz> 2010-07-09 Jan Hubicka <jh@suse.cz>
* lto-streamer-out.c (produce_symtab): Do not write alias cgraph/varpool * lto-streamer-out.c (produce_symtab): Do not write alias cgraph/varpool
......
...@@ -99,6 +99,7 @@ output_objc_section_asm_op (const void *directive) ...@@ -99,6 +99,7 @@ output_objc_section_asm_op (const void *directive)
section is requested. */ section is requested. */
if (! been_here) if (! been_here)
{ {
section *saved_in_section = in_section;
static const enum darwin_section_enum tomark[] = static const enum darwin_section_enum tomark[] =
{ {
/* written, cold -> hot */ /* written, cold -> hot */
...@@ -129,6 +130,7 @@ output_objc_section_asm_op (const void *directive) ...@@ -129,6 +130,7 @@ output_objc_section_asm_op (const void *directive)
been_here = true; been_here = true;
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]]);
switch_to_section (saved_in_section);
} }
output_section_asm_op (directive); output_section_asm_op (directive);
} }
......
2010-07-10 Iain Sandoe <iains@gcc.gnu.org>
PR objc/44140
* objc-act.c: build_objc_string_decl() remove declaration.
(finish_var_decl): Remove forcing of var output and marking
as "Used".
(init_def_list): Use integer_zero_node.
(init_objc_symtab): Use integer_zero_node, make the short
integer type specific on relevant nodes.
(generate_objc_symtab_decl): Remove call to
forward_declare_categories(). Use null_pointer_node where
appropriate.
(build_module_descriptor): Comment and mark this item as
DECL_PRESERVE_P.
(generate_static_references): Use gcc_unreachable instead of
abort ().
(diagnose_missing_method): New.
(build_next_selector_translation_table): New.
(build_gnu_selector_translation_table): New.
(add_objc_string): Merge code from build_objc_string_decl...
... and delete build_objc_string_decl().
(generate_dispatch_table): Make integer types explicit.
(generate_category): Pass implent and arrange for the data
to be extracted within the routine. Do not start new vars,
but finish the ones collcted during parsing.
(generate_shared_structures): Likewise.
(finish_objc): Reorder code so that we finish variables before
referencing them. Save the global data before calling meta-data
creation routines, and pass the current reference to the two
main routines. Only call generate_objc_image_info () for the
NeXT runtime.
(generate_classref_translation_entry): Comment on and make this
item DECL_PRESERVE_P.
(handle_class_ref): Use varpool interfaces, comment on and make
this item DECL_PRESERVE_P.
(handle_impent): Likewise.
(generate_objc_image_info): Only generate when the content is
non-zero. Make integer types explict.
2010-07-03 Nathan Froyd <froydnj@codesourcery.com> 2010-07-03 Nathan Froyd <froydnj@codesourcery.com>
PR objc/24867 PR objc/24867
......
...@@ -214,7 +214,6 @@ enum string_section ...@@ -214,7 +214,6 @@ enum string_section
}; };
static tree add_objc_string (tree, enum string_section); static tree add_objc_string (tree, enum string_section);
static tree build_objc_string_decl (enum string_section);
static void build_selector_table_decl (void); static void build_selector_table_decl (void);
/* Protocol additions. */ /* Protocol additions. */
...@@ -1541,14 +1540,6 @@ static void ...@@ -1541,14 +1540,6 @@ static void
finish_var_decl (tree var, tree initializer) finish_var_decl (tree var, tree initializer)
{ {
finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE); finish_decl (var, input_location, initializer, NULL_TREE, NULL_TREE);
/* Ensure that the variable actually gets output. */
mark_decl_referenced (var);
/* Mark the decl to avoid "defined but not used" warning. */
TREE_USED (var) = 1;
DECL_READ_P (var) = 1;
/* We reserve the right for the runtime to use/modify these variables
in ways that are opaque to us. */
DECL_PRESERVE_P (var) = 1;
} }
/* Find the decl for the constant string class reference. This is only /* Find the decl for the constant string class reference. This is only
...@@ -2188,7 +2179,7 @@ init_def_list (tree type) ...@@ -2188,7 +2179,7 @@ init_def_list (tree type)
expr = build_unary_op (input_location, expr = build_unary_op (input_location,
ADDR_EXPR, static_instances_decl, 0); ADDR_EXPR, static_instances_decl, 0);
else else
expr = build_int_cst (NULL_TREE, 0); expr = integer_zero_node;
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
} }
...@@ -2211,7 +2202,9 @@ init_objc_symtab (tree type) ...@@ -2211,7 +2202,9 @@ init_objc_symtab (tree type)
/* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */ /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
if (flag_next_runtime || ! sel_ref_chain) if (flag_next_runtime || ! sel_ref_chain)
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (
build_pointer_type (objc_selector_type),
integer_zero_node));
else else
{ {
tree expr = build_unary_op (input_location, ADDR_EXPR, tree expr = build_unary_op (input_location, ADDR_EXPR,
...@@ -2224,11 +2217,13 @@ init_objc_symtab (tree type) ...@@ -2224,11 +2217,13 @@ init_objc_symtab (tree type)
/* cls_def_cnt = { ..., 5, ... } */ /* cls_def_cnt = { ..., 5, ... } */
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, imp_count)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
build_int_cst (short_integer_type_node, imp_count));
/* cat_def_cnt = { ..., 5, ... } */ /* cat_def_cnt = { ..., 5, ... } */
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, cat_count)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
build_int_cst (short_integer_type_node, cat_count));
/* cls_def = { ..., { &Foo, &Bar, ...}, ... } */ /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
...@@ -2289,10 +2284,7 @@ forward_declare_categories (void) ...@@ -2289,10 +2284,7 @@ forward_declare_categories (void)
static void static void
generate_objc_symtab_decl (void) generate_objc_symtab_decl (void)
{ {
/* forward declare categories */
if (cat_count)
forward_declare_categories ();
build_objc_symtab_template (); build_objc_symtab_template ();
UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS"); UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS");
finish_var_decl (UOBJC_SYMBOLS_decl, finish_var_decl (UOBJC_SYMBOLS_decl,
...@@ -2328,7 +2320,7 @@ init_module_descriptor (tree type) ...@@ -2328,7 +2320,7 @@ init_module_descriptor (tree type)
expr = build_unary_op (input_location, expr = build_unary_op (input_location,
ADDR_EXPR, UOBJC_SYMBOLS_decl, 0); ADDR_EXPR, UOBJC_SYMBOLS_decl, 0);
else else
expr = build_int_cst (NULL_TREE, 0); expr = null_pointer_node;
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
return objc_build_constructor (type, v); return objc_build_constructor (type, v);
...@@ -2367,6 +2359,9 @@ build_module_descriptor (void) ...@@ -2367,6 +2359,9 @@ build_module_descriptor (void)
/* Create an instance of "_objc_module". */ /* Create an instance of "_objc_module". */
UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES"); UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES");
/* This is the root of the metadata for defined classes and categories, it
is referenced by the runtime and, therefore, needed. */
DECL_PRESERVE_P (UOBJC_MODULES_decl) = 1;
finish_var_decl (UOBJC_MODULES_decl, finish_var_decl (UOBJC_MODULES_decl,
init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl))); init_module_descriptor (TREE_TYPE (UOBJC_MODULES_decl)));
...@@ -2490,7 +2485,7 @@ generate_static_references (void) ...@@ -2490,7 +2485,7 @@ generate_static_references (void)
VEC(constructor_elt,gc) *decls = NULL; VEC(constructor_elt,gc) *decls = NULL;
if (flag_next_runtime) if (flag_next_runtime)
abort (); gcc_unreachable ();
for (cl_chain = objc_static_instances, num_class = 0; for (cl_chain = objc_static_instances, num_class = 0;
cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++) cl_chain; cl_chain = TREE_CHAIN (cl_chain), num_class++)
...@@ -2574,54 +2569,78 @@ build_selector (tree ident) ...@@ -2574,54 +2569,78 @@ build_selector (tree ident)
add_objc_string (ident, meth_var_names)); add_objc_string (ident, meth_var_names));
} }
/* Used only by build_*_selector_translation_table (). */
static void static void
build_selector_translation_table (void) diagnose_missing_method (tree meth, location_t here)
{ {
tree chain; tree method_chain;
int offset = 0; bool found = false;
tree decl = NULL_TREE; for (method_chain = meth_var_names_chain;
VEC(constructor_elt,gc) *inits = NULL; method_chain;
method_chain = TREE_CHAIN (method_chain))
{
if (TREE_VALUE (method_chain) == meth)
{
found = true;
break;
}
}
if (!found)
warning_at (here, 0, "creating selector for nonexistent method %qE",
meth);
}
static void
build_next_selector_translation_table (void)
{
tree chain;
for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain)) for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
{ {
tree expr; tree expr;
tree decl = TREE_PURPOSE (chain);
if (warn_selector && objc_implementation_context) if (warn_selector && objc_implementation_context)
{ {
tree method_chain; location_t loc;
bool found = false; if (decl)
for (method_chain = meth_var_names_chain; loc = DECL_SOURCE_LOCATION (decl);
method_chain; else
method_chain = TREE_CHAIN (method_chain)) loc = input_location;
{ diagnose_missing_method (TREE_VALUE (chain), loc);
if (TREE_VALUE (method_chain) == TREE_VALUE (chain)) }
{
found = true;
break;
}
}
if (!found)
{
location_t loc;
if (flag_next_runtime && TREE_PURPOSE (chain))
loc = DECL_SOURCE_LOCATION (TREE_PURPOSE (chain));
else
loc = input_location;
warning_at (loc, 0, "creating selector for nonexistent method %qE",
TREE_VALUE (chain));
}
}
expr = build_selector (TREE_VALUE (chain)); expr = build_selector (TREE_VALUE (chain));
/* add one for the '\0' character */
offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
if (flag_next_runtime) if (decl)
{ {
decl = TREE_PURPOSE (chain); /* 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); finish_var_decl (decl, expr);
} }
else }
}
static void
build_gnu_selector_translation_table (void)
{
tree chain;
/* int offset = 0;
tree decl = NULL_TREE;*/
VEC(constructor_elt,gc) *inits = NULL;
for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
{
tree expr;
if (warn_selector && objc_implementation_context)
diagnose_missing_method (TREE_VALUE (chain), input_location);
expr = build_selector (TREE_VALUE (chain));
/* add one for the '\0' character
offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;*/
{ {
if (flag_typed_selectors) if (flag_typed_selectors)
{ {
...@@ -2634,9 +2653,8 @@ build_selector_translation_table (void) ...@@ -2634,9 +2653,8 @@ build_selector_translation_table (void)
CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
} }
} } /* each element in the chain */
if (! flag_next_runtime)
{ {
/* Cause the selector table (previously forward-declared) /* Cause the selector table (previously forward-declared)
to be actually output. */ to be actually output. */
...@@ -2645,12 +2663,12 @@ build_selector_translation_table (void) ...@@ -2645,12 +2663,12 @@ build_selector_translation_table (void)
if (flag_typed_selectors) if (flag_typed_selectors)
{ {
VEC(constructor_elt,gc) *v = NULL; VEC(constructor_elt,gc) *v = NULL;
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
expr = objc_build_constructor (objc_selector_template, v); expr = objc_build_constructor (objc_selector_template, v);
} }
else else
expr = build_int_cst (NULL_TREE, 0); expr = integer_zero_node;
CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl), expr = objc_build_constructor (TREE_TYPE (UOBJC_SELECTOR_TABLE_decl),
...@@ -2854,19 +2872,34 @@ objc_get_class_reference (tree ident) ...@@ -2854,19 +2872,34 @@ objc_get_class_reference (tree ident)
/* For each string section we have a chain which maps identifier nodes /* For each string section we have a chain which maps identifier nodes
to decls for the strings. */ to decls for the strings. */
static GTY(()) int class_names_idx;
static GTY(()) int meth_var_names_idx;
static GTY(()) int meth_var_types_idx;
static tree static tree
add_objc_string (tree ident, enum string_section section) add_objc_string (tree ident, enum string_section section)
{ {
tree *chain, decl, type, string_expr; tree *chain, decl, type, string_expr;
char buf[256];
buf[0] = 0;
if (section == class_names) if (section == class_names)
chain = &class_names_chain; {
chain = &class_names_chain;
sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
}
else if (section == meth_var_names) else if (section == meth_var_names)
chain = &meth_var_names_chain; {
chain = &meth_var_names_chain;
sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
}
else if (section == meth_var_types) else if (section == meth_var_types)
chain = &meth_var_types_chain; {
chain = &meth_var_types_chain;
sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
}
else else
abort (); gcc_unreachable ();
while (*chain) while (*chain)
{ {
...@@ -2878,12 +2911,11 @@ add_objc_string (tree ident, enum string_section section) ...@@ -2878,12 +2911,11 @@ add_objc_string (tree ident, enum string_section section)
chain = &TREE_CHAIN (*chain); chain = &TREE_CHAIN (*chain);
} }
decl = build_objc_string_decl (section);
type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1); type = build_sized_array_type (char_type_node, IDENTIFIER_LENGTH (ident) + 1);
decl = start_var_decl (type, IDENTIFIER_POINTER (DECL_NAME (decl))); decl = start_var_decl (type, buf);
string_expr = my_build_string (IDENTIFIER_LENGTH (ident) + 1, string_expr = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
IDENTIFIER_POINTER (ident)); IDENTIFIER_POINTER (ident));
TREE_CONSTANT (decl) = 1;
finish_var_decl (decl, string_expr); finish_var_decl (decl, string_expr);
*chain = tree_cons (decl, ident, NULL_TREE); *chain = tree_cons (decl, ident, NULL_TREE);
...@@ -2892,44 +2924,6 @@ add_objc_string (tree ident, enum string_section section) ...@@ -2892,44 +2924,6 @@ add_objc_string (tree ident, enum string_section section)
ADDR_EXPR, decl, 1)); ADDR_EXPR, decl, 1));
} }
static GTY(()) int class_names_idx;
static GTY(()) int meth_var_names_idx;
static GTY(()) int meth_var_types_idx;
static tree
build_objc_string_decl (enum string_section section)
{
tree decl, ident;
char buf[256];
if (section == class_names)
sprintf (buf, "_OBJC_CLASS_NAME_%d", class_names_idx++);
else if (section == meth_var_names)
sprintf (buf, "_OBJC_METH_VAR_NAME_%d", meth_var_names_idx++);
else if (section == meth_var_types)
sprintf (buf, "_OBJC_METH_VAR_TYPE_%d", meth_var_types_idx++);
ident = get_identifier (buf);
decl = build_decl (input_location,
VAR_DECL, ident, build_array_type (char_type_node, 0));
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 0;
TREE_USED (decl) = 1;
TREE_CONSTANT (decl) = 1;
DECL_CONTEXT (decl) = 0;
DECL_ARTIFICIAL (decl) = 1;
#ifdef OBJCPLUS
DECL_THIS_STATIC (decl) = 1; /* squash redeclaration errors */
#endif
make_decl_rtl (decl);
pushdecl_top_level (decl);
return decl;
}
void void
objc_declare_alias (tree alias_ident, tree class_ident) objc_declare_alias (tree alias_ident, tree class_ident)
{ {
...@@ -5334,8 +5328,8 @@ generate_dispatch_table (tree type, const char *name, int size, tree list) ...@@ -5334,8 +5328,8 @@ generate_dispatch_table (tree type, const char *name, int size, tree list)
decl = start_var_decl (type, synth_id_with_class_suffix decl = start_var_decl (type, synth_id_with_class_suffix
(name, objc_implementation_context)); (name, objc_implementation_context));
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, size));
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, list); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, list);
finish_var_decl (decl, finish_var_decl (decl,
...@@ -5658,11 +5652,15 @@ lookup_category (tree klass, tree cat_name) ...@@ -5658,11 +5652,15 @@ lookup_category (tree klass, tree cat_name)
/* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */ /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
static void static void
generate_category (tree cat) generate_category (struct imp_entry *impent)
{ {
tree decl;
tree initlist, cat_name_expr, class_name_expr; tree initlist, cat_name_expr, class_name_expr;
tree protocol_decl, category; tree protocol_decl, category;
tree cat = impent->imp_context;
implementation_template = impent->imp_template;
UOBJC_CLASS_decl = impent->class_decl;
UOBJC_METACLASS_decl = impent->meta_decl;
add_class_reference (CLASS_NAME (cat)); add_class_reference (CLASS_NAME (cat));
cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names); cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
...@@ -5680,30 +5678,32 @@ generate_category (tree cat) ...@@ -5680,30 +5678,32 @@ generate_category (tree cat)
else else
protocol_decl = 0; protocol_decl = 0;
decl = start_var_decl (objc_category_template, initlist = build_category_initializer (TREE_TYPE (UOBJC_CLASS_decl),
synth_id_with_class_suffix
("_OBJC_CATEGORY", objc_implementation_context));
initlist = build_category_initializer (TREE_TYPE (decl),
cat_name_expr, class_name_expr, cat_name_expr, class_name_expr,
UOBJC_INSTANCE_METHODS_decl, UOBJC_INSTANCE_METHODS_decl,
UOBJC_CLASS_METHODS_decl, UOBJC_CLASS_METHODS_decl,
protocol_decl); protocol_decl);
/* Finish and initialize the forward decl. */
finish_var_decl (decl, initlist); finish_var_decl (UOBJC_CLASS_decl, initlist);
} }
/* static struct objc_class _OBJC_METACLASS_Foo={ ... }; /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
static struct objc_class _OBJC_CLASS_Foo={ ... }; */ static struct objc_class _OBJC_CLASS_Foo={ ... }; */
static void static void
generate_shared_structures (int cls_flags) generate_shared_structures (struct imp_entry *impent)
{ {
tree decl;
tree name_expr, super_expr, root_expr; tree name_expr, super_expr, root_expr;
tree my_root_id = NULL_TREE, my_super_id = NULL_TREE; tree my_root_id, my_super_id;
tree cast_type, initlist, protocol_decl; tree cast_type, initlist, protocol_decl;
int cls_flags;
objc_implementation_context = impent->imp_context;
implementation_template = impent->imp_template;
UOBJC_CLASS_decl = impent->class_decl;
UOBJC_METACLASS_decl = impent->meta_decl;
cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ;
my_super_id = CLASS_SUPER_NAME (implementation_template); my_super_id = CLASS_SUPER_NAME (implementation_template);
if (my_super_id) if (my_super_id)
{ {
...@@ -5734,13 +5734,12 @@ generate_shared_structures (int cls_flags) ...@@ -5734,13 +5734,12 @@ generate_shared_structures (int cls_flags)
/* Install class `isa' and `super' pointers at runtime. */ /* Install class `isa' and `super' pointers at runtime. */
if (my_super_id) if (my_super_id)
{ super_expr = add_objc_string (my_super_id, class_names);
super_expr = add_objc_string (my_super_id, class_names);
super_expr = build_c_cast (input_location,
cast_type, super_expr); /* cast! */
}
else else
super_expr = build_int_cst (NULL_TREE, 0); super_expr = integer_zero_node;
super_expr = build_c_cast (input_location,
cast_type, super_expr); /* cast! */
root_expr = add_objc_string (my_root_id, class_names); root_expr = add_objc_string (my_root_id, class_names);
root_expr = build_c_cast (input_location, cast_type, root_expr); /* cast! */ root_expr = build_c_cast (input_location, cast_type, root_expr); /* cast! */
...@@ -5756,13 +5755,9 @@ generate_shared_structures (int cls_flags) ...@@ -5756,13 +5755,9 @@ generate_shared_structures (int cls_flags)
/* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */ /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
decl = start_var_decl (objc_class_template,
IDENTIFIER_POINTER
(DECL_NAME (UOBJC_METACLASS_decl)));
initlist initlist
= build_shared_structure_initializer = build_shared_structure_initializer
(TREE_TYPE (decl), (TREE_TYPE (UOBJC_METACLASS_decl),
root_expr, super_expr, name_expr, root_expr, super_expr, name_expr,
convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)), convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
2 /*CLS_META*/, 2 /*CLS_META*/,
...@@ -5770,17 +5765,13 @@ generate_shared_structures (int cls_flags) ...@@ -5770,17 +5765,13 @@ generate_shared_structures (int cls_flags)
UOBJC_CLASS_VARIABLES_decl, UOBJC_CLASS_VARIABLES_decl,
protocol_decl); protocol_decl);
finish_var_decl (decl, initlist); finish_var_decl (UOBJC_METACLASS_decl, initlist);
/* static struct objc_class _OBJC_CLASS_Foo={ ... }; */ /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
decl = start_var_decl (objc_class_template,
IDENTIFIER_POINTER
(DECL_NAME (UOBJC_CLASS_decl)));
initlist initlist
= build_shared_structure_initializer = build_shared_structure_initializer
(TREE_TYPE (decl), (TREE_TYPE (UOBJC_CLASS_decl),
build_unary_op (input_location, ADDR_EXPR, UOBJC_METACLASS_decl, 0), build_unary_op (input_location, ADDR_EXPR, UOBJC_METACLASS_decl, 0),
super_expr, name_expr, super_expr, name_expr,
convert (integer_type_node, convert (integer_type_node,
...@@ -5791,7 +5782,7 @@ generate_shared_structures (int cls_flags) ...@@ -5791,7 +5782,7 @@ generate_shared_structures (int cls_flags)
UOBJC_INSTANCE_VARIABLES_decl, UOBJC_INSTANCE_VARIABLES_decl,
protocol_decl); protocol_decl);
finish_var_decl (decl, initlist); finish_var_decl (UOBJC_CLASS_decl, initlist);
} }
...@@ -9176,15 +9167,17 @@ finish_objc (void) ...@@ -9176,15 +9167,17 @@ finish_objc (void)
if (objc_static_instances) if (objc_static_instances)
generate_static_references (); generate_static_references ();
if (imp_list || class_names_chain /* forward declare categories */
|| meth_var_names_chain || meth_var_types_chain || sel_ref_chain) if (cat_count)
generate_objc_symtab_decl (); forward_declare_categories ();
for (impent = imp_list; impent; impent = impent->next) for (impent = imp_list; impent; impent = impent->next)
{ {
objc_implementation_context = impent->imp_context; objc_implementation_context = impent->imp_context;
implementation_template = impent->imp_template; implementation_template = impent->imp_template;
/* FIXME: This needs reworking to be more obvious. */
UOBJC_CLASS_decl = impent->class_decl; UOBJC_CLASS_decl = impent->class_decl;
UOBJC_METACLASS_decl = impent->meta_decl; UOBJC_METACLASS_decl = impent->meta_decl;
...@@ -9202,28 +9195,35 @@ finish_objc (void) ...@@ -9202,28 +9195,35 @@ finish_objc (void)
/* all of the following reference the string pool... */ /* all of the following reference the string pool... */
generate_ivar_lists (); generate_ivar_lists ();
generate_dispatch_tables (); generate_dispatch_tables ();
generate_shared_structures (impent->has_cxx_cdtors generate_shared_structures (impent);
? CLS_HAS_CXX_STRUCTORS
: 0);
} }
else else
{ {
generate_dispatch_tables (); generate_dispatch_tables ();
generate_category (objc_implementation_context); generate_category (impent);
} }
impent->class_decl = UOBJC_CLASS_decl;
impent->meta_decl = UOBJC_METACLASS_decl;
} }
/* If we are using an array of selectors, we must always /* If we are using an array of selectors, we must always
finish up the array decl even if no selectors were used. */ finish up the array decl even if no selectors were used. */
if (! flag_next_runtime || sel_ref_chain) if (flag_next_runtime)
build_selector_translation_table (); build_next_selector_translation_table ();
else
build_gnu_selector_translation_table ();
if (protocol_chain) if (protocol_chain)
generate_protocols (); generate_protocols ();
if ((flag_replace_objc_classes && imp_list) || flag_objc_gc) if (flag_next_runtime)
generate_objc_image_info (); generate_objc_image_info ();
if (imp_list || class_names_chain
|| meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
generate_objc_symtab_decl ();
/* Arrange for ObjC data structures to be initialized at run time. */ /* Arrange for ObjC data structures to be initialized at run time. */
if (objc_implementation_context || class_names_chain || objc_static_instances if (objc_implementation_context || class_names_chain || objc_static_instances
|| meth_var_names_chain || meth_var_types_chain || sel_ref_chain) || meth_var_names_chain || meth_var_types_chain || sel_ref_chain)
...@@ -9282,8 +9282,9 @@ generate_classref_translation_entry (tree chain) ...@@ -9282,8 +9282,9 @@ generate_classref_translation_entry (tree chain)
expr = add_objc_string (TREE_VALUE (chain), class_names); expr = add_objc_string (TREE_VALUE (chain), class_names);
expr = convert (type, expr); /* cast! */ expr = convert (type, expr); /* cast! */
/* The decl that is the one that we /* This is a class reference. It is re-written by the runtime,
forward declared in build_class_reference. */ but will be optimized away unless we force it. */
DECL_PRESERVE_P (decl) = 1;
finish_var_decl (decl, expr); finish_var_decl (decl, expr);
return; return;
} }
...@@ -9309,12 +9310,11 @@ handle_class_ref (tree chain) ...@@ -9309,12 +9310,11 @@ handle_class_ref (tree chain)
/* Make a decl for this name, so we can use its address in a tree. */ /* Make a decl for this name, so we can use its address in a tree. */
decl = build_decl (input_location, decl = build_decl (input_location,
VAR_DECL, get_identifier (string), char_type_node); VAR_DECL, get_identifier (string), TREE_TYPE (integer_zero_node));
DECL_EXTERNAL (decl) = 1; DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1; TREE_PUBLIC (decl) = 1;
pushdecl (decl); pushdecl (decl);
rest_of_decl_compilation (decl, 0, 0); finish_var_decl (decl, 0);
/* Make a decl for the address. */ /* Make a decl for the address. */
sprintf (string, "%sobjc_class_ref_%s", sprintf (string, "%sobjc_class_ref_%s",
...@@ -9322,15 +9322,17 @@ handle_class_ref (tree chain) ...@@ -9322,15 +9322,17 @@ handle_class_ref (tree chain)
exp = build1 (ADDR_EXPR, string_type_node, decl); exp = build1 (ADDR_EXPR, string_type_node, decl);
decl = build_decl (input_location, decl = build_decl (input_location,
VAR_DECL, get_identifier (string), string_type_node); VAR_DECL, get_identifier (string), string_type_node);
DECL_INITIAL (decl) = exp;
TREE_STATIC (decl) = 1; TREE_STATIC (decl) = 1;
TREE_USED (decl) = 1; TREE_USED (decl) = 1;
DECL_READ_P (decl) = 1; DECL_READ_P (decl) = 1;
/* Force the output of the decl as this forces the reference of the class. */ DECL_ARTIFICIAL (decl) = 1;
mark_decl_referenced (decl); DECL_INITIAL (decl) = error_mark_node;
/* We must force the reference. */
DECL_PRESERVE_P (decl) = 1;
pushdecl (decl); pushdecl (decl);
rest_of_decl_compilation (decl, 0, 0); finish_var_decl (decl, exp);
} }
static void static void
...@@ -9381,17 +9383,21 @@ handle_impent (struct imp_entry *impent) ...@@ -9381,17 +9383,21 @@ handle_impent (struct imp_entry *impent)
{ {
tree decl, init; tree decl, init;
init = build_int_cst (c_common_type_for_size (BITS_PER_WORD, 1), 0); init = integer_zero_node;
decl = build_decl (input_location, decl = build_decl (input_location,
VAR_DECL, get_identifier (string), TREE_TYPE (init)); VAR_DECL, get_identifier (string), TREE_TYPE (init));
TREE_PUBLIC (decl) = 1; TREE_PUBLIC (decl) = 1;
TREE_READONLY (decl) = 1; TREE_READONLY (decl) = 1;
TREE_USED (decl) = 1; TREE_USED (decl) = 1;
TREE_CONSTANT (decl) = 1; TREE_CONSTANT (decl) = 1;
DECL_CONTEXT (decl) = 0; DECL_CONTEXT (decl) = NULL_TREE;
DECL_ARTIFICIAL (decl) = 1; DECL_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = init; TREE_STATIC (decl) = 1;
assemble_variable (decl, 1, 0, 0); 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) ;
} }
} }
...@@ -9406,16 +9412,24 @@ generate_objc_image_info (void) ...@@ -9406,16 +9412,24 @@ generate_objc_image_info (void)
{ {
tree decl; tree decl;
int flags int flags
= ((flag_replace_objc_classes && imp_list ? 1 : 0) = ((flag_replace_objc_classes && imp_count ? 1 : 0)
| (flag_objc_gc ? 2 : 0)); | (flag_objc_gc ? 2 : 0));
VEC(constructor_elt,gc) *v = NULL; VEC(constructor_elt,gc) *v = NULL;
tree array_type = build_sized_array_type (integer_type_node, 2); tree array_type;
if (!flags)
return; /* No need for an image_info entry. */
array_type = build_sized_array_type (integer_type_node, 2);
decl = start_var_decl (array_type, "_OBJC_IMAGE_INFO"); decl = start_var_decl (array_type, "_OBJC_IMAGE_INFO");
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags)); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags));
/* If we need this (determined above) it is because the runtime wants to
refer to it in a manner hidden from the compiler. So we must force the
output. */
DECL_PRESERVE_P (decl) = 1;
finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v)); finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v));
} }
......
2010-07-10 Iain Sandoe <iains@gcc.gnu.org>
PR objc/44140
* objc.dg/lto/trivial-1_0.m: New.
* objc.dg/lto/lto.exp: New.
* obj-c++.dg/lto/trivial-1_0.mm: New.
* obj-c++.dg/lto/lto.exp: New.
* objc.dg/symtab-1.m: Adjust sizes.
* objc.dg/image-info.m: Do not run for gnu-runtime.
2010-07-09 Bernd Schmidt <bernds@codesourcery.com> 2010-07-09 Bernd Schmidt <bernds@codesourcery.com>
* gcc.dg/pr32370.c: Allow another kind of error message. * gcc.dg/pr32370.c: Allow another kind of error message.
......
# Copyright (C) 2010 Free Software Foundation, Inc.
# This program 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 of the License, or
# (at your option) any later version.
#
# This program 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/>.
#
# Based on gcc/testsuite/gcc.dg/lto/lto.exp.
# Test link-time optimization across multiple files.
#
# Programs are broken into multiple files. Each one is compiled
# separately with LTO information. The final executable is generated
# by collecting all the generated object files using regular LTO or WHOPR.
if $tracelevel then {
strace $tracelevel
}
# Load procedures from common libraries.
load_lib standard.exp
load_lib obj-c++-dg.exp
# Load the language-independent compabibility support procedures.
load_lib lto.exp
# If LTO has not been enabled, bail.
if { ![check_effective_target_lto] } {
return
}
global LTO_OPTIONS
set LTO_OPTIONS [list \
{-O0 -fwhopr -fgnu-runtime} \
{-O2 -fwhopr -fgnu-runtime} \
{-O0 -flto -fgnu-runtime} \
{-O2 -flto -fgnu-runtime} \
]
obj-c++_init
lto_init no-mathlib
# Define an identifier for use with this suite to avoid name conflicts
# with other lto tests running at the same time.
set sid "obj_cpp_lto"
set tests [lsort [glob -nocomplain $srcdir/$subdir/*_0.mm]]
# Main loop.
foreach src $tests {
# If we're only testing specific files and this isn't one of them, skip it.
if ![runtest_file_p $runtests $src] then {
continue
}
lto-execute $src $sid
}
# darwin targets can also run code with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
set LTO_OPTIONS [list \
{-O0 -fwhopr -fnext-runtime} \
{-O2 -fwhopr -fnext-runtime} \
{-O0 -flto -fnext-runtime} \
{-O2 -flto -fnext-runtime} \
]
foreach src $tests {
# If we're only testing specific files and this isn't one of them, skip it.
if ![runtest_file_p $runtests $src] then {
continue
}
lto-execute $src $sid
}
}
lto_finish
/* { dg-lto-do run } */
/* { dg-skip-if "Needs OBJC2 ABI" { "*-*-darwin*" && lp64 } { "*" } { "" } } */
extern "C" {
extern int printf (char *,...) ;
extern void abort (void) ;
}
typedef struct objc_class *Class;
struct objc_class {
Class isa;
/* other stuff... */
} ;
@interface myRootObject {
@public
Class isa;
}
+initialize;
+(Class)class;
@end
@implementation myRootObject
++initialize {
return self;
}
+(Class)class {
return (Class)self;
}
@end
int main(void)
{
Class cl = [myRootObject class];
if (cl != (Class)0) {
printf((char *)"trivial OK\n");
return 0;
}
abort () ;
}
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
/* Contributed by Ziemowit Laski <zlaski@apple.com>. */ /* Contributed by Ziemowit Laski <zlaski@apple.com>. */
/* { dg-do compile { target { *-*-darwin* } } } */ /* { dg-do compile { target { *-*-darwin* } } } */
/* { 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-obj-c++-shared/Object1.h"
......
# Copyright (C) 2010 Free Software Foundation, Inc.
# This program 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 of the License, or
# (at your option) any later version.
#
# This program 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/>.
#
# Based on gcc/testsuite/gcc.dg/lto/lto.exp.
# Test link-time optimization across multiple files.
#
# Programs are broken into multiple files. Each one is compiled
# separately with LTO information. The final executable is generated
# by collecting all the generated object files using regular LTO or WHOPR.
if $tracelevel then {
strace $tracelevel
}
# Load procedures from common libraries.
load_lib standard.exp
load_lib objc-dg.exp
# Load the language-independent compabibility support procedures.
load_lib lto.exp
# If LTO has not been enabled, bail.
if { ![check_effective_target_lto] } {
return
}
global LTO_OPTIONS
set LTO_OPTIONS [list \
{-O0 -fwhopr -fgnu-runtime} \
{-O2 -fwhopr -fgnu-runtime} \
{-O0 -flto -fgnu-runtime} \
{-O2 -flto -fgnu-runtime} \
]
objc_init
lto_init no-mathlib
# Define an identifier for use with this suite to avoid name conflicts
# with other lto tests running at the same time.
set sid "objc_lto"
set tests [lsort [glob -nocomplain $srcdir/$subdir/*_0.m]]
# Main loop.
foreach src $tests {
# If we're only testing specific files and this isn't one of them, skip it.
if ![runtest_file_p $runtests $src] then {
continue
}
lto-execute $src $sid
}
# darwin targets can also run code with the NeXT runtime.
if [istarget "*-*-darwin*" ] {
set LTO_OPTIONS [list \
{-O0 -fwhopr -fnext-runtime} \
{-O2 -fwhopr -fnext-runtime} \
{-O0 -flto -fnext-runtime} \
{-O2 -flto -fnext-runtime} \
]
foreach src $tests {
# If we're only testing specific files and this isn't one of them, skip it.
if ![runtest_file_p $runtests $src] then {
continue
}
lto-execute $src $sid
}
}
lto_finish
/* { dg-lto-do run } */
/* { dg-skip-if "" { "*-*-darwin*" && lp64 } { "*" } { "" } } */
extern int printf (char *,...) ;
typedef struct objc_class *Class;
struct objc_class {
Class isa;
/* other stuff... */
} ;
@interface myRootObject {
@public
Class isa;
}
+initialize;
+(Class)class;
@end
@implementation myRootObject
++initialize {
return self;
}
+(Class)class {
return (Class)self;
}
@end
int main(void)
{
[myRootObject class];
printf("trivial OK\n");
return 0;
}
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
-(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 { i?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.long\t0\n\t.space 4\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 { *-*-darwin* && { lp64 } } } } } */ /* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.quad\t0\n\t.quad\t0\n\t.word\t2\n\t.word\t0\n\t.space 4\n\t.quad\tL_OBJC_CLASS_Derived.*\n\t.quad\tL_OBJC_CLASS_Base.*\n" { target { *86*-*-darwin* && { lp64 } } } } } */
/* { dg-final { scan-assembler "L_OBJC_SYMBOLS.*:\n\t.quad\t0\n\t.quad\t0\n\t.short\t2\n\t.short\t0\n\t.space 4\n\t.quad\tL_OBJC_CLASS_Derived.*\n\t.quad\tL_OBJC_CLASS_Base.*\n" { target { powerpc*-*-darwin* && { lp64 } } } } } */
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