On Thu, Jun 30, 2011 at 12:50 PM, Iain Sandoe <develo...@sandoe-acoustics.co.uk> wrote: > > On 30 Jun 2011, at 11:27, Richard Guenther wrote: > >> On Wed, Jun 29, 2011 at 7:47 PM, Iain Sandoe >> <develo...@sandoe-acoustics.co.uk> wrote: >>> >>> The bug arises because of the use, by the ObjC FE, of two old target >>> macros >>> that emit efficient representations of class definitions and references. >>> >>> This 'works fine' (however wrong it might be conceptually), until LTO is >>> engaged, whereupon the definitions vanish without trace (since no >>> corresponding real variable is ever created). >>> >>> --- >>> >>> The patch creates appropriate variables in the FE and tags them as ObjC >>> meta-data (in the same manner as is done for other objc meta-data). >>> >>> We then intercept them in varasm.c with a hook that allows the target to >>> declare that it has completely handled the output of a variable - >>> allowing >>> us to handle them in the required special manner. >>> >>> FAOD, It is necessary to preserve this mechanism for emitting the >>> definitions and references to permit linkage with existing system >>> libraries. >>> >>> ---- >>> >>> If the patch is acceptable, then I would expect to follow up with a patch >>> to >>> remove ASM_DECLARE_CLASS_REFERENCE and ASM_DECLARE_UNRESOLVED_REFERENCE >>> from >>> the tree - since this is their only use. >>> >>> ---- >>> >>> bootstrapped on i686-linux, i686-darwin9, x86_64-darwin10, (checked to >>> do >>> the Right Thing on darwin). >>> >>> Mike has already given this a 'seems reasonable' in the PR thread, >>> however, >>> I need an approver for the varasm.c and target hook changes. >>> >>> OK for trunk & 4.6? >> >> Where does the target handle output of the variable? If it is in the hook >> then that hook is misnamed - it should then probably be called >> assemble_variable. > > It is in the hook, > hence named "handled_assemble_variable_p" > .. allowing us to test if the target has completed the work and finish > assemble_variable () early. > > Does that explain it better? - would an expanded comment help? > > (I am happy to use any name generally agreed, but IMO the name should convey > the idea that the result should be tested to determine if the target did the > work, or it will be confusing to maintain).
Well, as it certainly isn't a predicate but is supposed to do the actual work simply calling it assemble_variable is better. >> Not sure if this is the most reasonable piece of >> assemble_variable to split out to a hook though. > > It is only used by darwin at present - so nothing is split out for any other > target (the default hook is simply 'false'). Yes, I've seen that. Still a hook like this should be generally useful, and you still process through some pieces of assemble_variable while you choose to skip some other piece - it should probably be documented which part of assemble_variable is supposed to be handled by the hook. I'll defer to Richard for this (and the approval). > Initially, I thought about simply moving the ASM_DECLARE_CLASS_REFERENCE and > ASM_DECLARE_UNRESOLVED_REFERENCE to varasm.c > > However, there seems to be a general move to use hooks instead of macros, > and this seemed like a good time to make the change (and pave the way to > remove those two macros from the tree). > > If the consensus is a preference to retain the macros - I could re-work the > patch to do that. No, a hook is definitely better. >> I'm not sure we want to backport this though (there isn't even a bugreport >> about it?). > > PR48109, reported initially against 4.6.0 (before it forked); > ... I guess it's also wrong code under LTO. So the ChangeLog should mention this PR. Richard. > thanks > Iain > >> >> Thanks, >> Richard. >> >>> Iain >>> >>> === >>> >>> gcc/ >>> >>> * target.def (handled_assemble_variable_p): New hook. >>> * varasm.c (assemble_variable): Allow target to handle variable >>> output >>> in some special manner. >>> * doc/tm.texi: Regenerate. >>> * config/darwin.c (darwin_objc1_section): Handle class defs/refs. >>> (darwin_handled_assemble_variable_p): New. >>> * config/darwin-protos.h (darwin_handled_assemble_variable_p): New. >>> * config/darwin.h (TARGET_ASM_HANDLED_ASSEMBLE_VARIABLE_P): New. >>> >>> gcc/objc/ >>> >>> *objc-next-runtime-abi-01.c (handle_next_class_ref): Don't emit >>> lazy >>> refs. for >>> cases where the class is local. Declare a real, meta-data item >>> tagged as >>> a class reference. >>> (handle_next_impent): Declare a real, meta-data item tagged as a >>> class def. >>> >>> === >>> >>> Index: gcc/target.def >>> =================================================================== >>> --- gcc/target.def (revision 175628) >>> +++ gcc/target.def (working copy) >>> @@ -449,6 +449,13 @@ DEFHOOK >>> bool, (FILE *file, rtx x), >>> default_asm_output_addr_const_extra) >>> >>> +DEFHOOK >>> +(handled_assemble_variable_p, >>> + "Returns @code{true} iff the target has handled the assembly of the\ >>> + variable @var{var_decl}", >>> + bool, (tree var_decl), >>> + hook_bool_tree_false) >>> + >>> /* ??? The TARGET_PRINT_OPERAND* hooks are part of the asm_out struct, >>> even though that is not reflected in the macro name to override their >>> initializers. */ >>> Index: gcc/objc/objc-next-runtime-abi-01.c >>> =================================================================== >>> --- gcc/objc/objc-next-runtime-abi-01.c (revision 175628) >>> +++ gcc/objc/objc-next-runtime-abi-01.c (working copy) >>> @@ -2267,27 +2267,51 @@ generate_objc_symtab_decl (void) >>> init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl))); >>> } >>> >>> - >>> static void >>> handle_next_class_ref (tree chain) >>> { >>> + tree decl, exp; >>> + struct imp_entry *impent; >>> const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain)); >>> char *string = (char *) alloca (strlen (name) + 30); >>> >>> + for (impent = imp_list; impent; impent = impent->next) >>> + if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE >>> + && IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)) >>> + == IDENTIFIER_POINTER (TREE_VALUE (chain))) >>> + return; /* we declare this, no need for a lazy ref. */ >>> + >>> 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 >>> + decl = build_decl (UNKNOWN_LOCATION, >>> + VAR_DECL, get_identifier (string), char_type_node); >>> + TREE_PUBLIC (decl) = 1; >>> + DECL_EXTERNAL (decl) = 1; >>> + DECL_CONTEXT (decl) = NULL_TREE; >>> + finish_var_decl (decl, NULL); >>> + >>> + /* We build a variable to signal the reference. This will be >>> intercepted >>> + and output as a lazy reference. */ >>> + 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; >>> + DECL_ARTIFICIAL (decl) = 1; >>> + DECL_INITIAL (decl) = error_mark_node; >>> + >>> + /* We must force the reference. */ >>> + DECL_PRESERVE_P (decl) = 1; >>> + OBJCMETA (decl, objc_meta, get_identifier ("V1_CREF")); >>> + DECL_CONTEXT (decl) = NULL_TREE; >>> + finish_var_decl (decl, exp); >>> } >>> >>> static void >>> handle_next_impent (struct imp_entry *impent) >>> { >>> char buf[BUFSIZE]; >>> - >>> + tree decl; >>> switch (TREE_CODE (impent->imp_context)) >>> { >>> case CLASS_IMPLEMENTATION_TYPE: >>> @@ -2303,11 +2327,16 @@ handle_next_impent (struct imp_entry *impent) >>> return; >>> } >>> >>> -#ifdef ASM_DECLARE_CLASS_REFERENCE >>> - ASM_DECLARE_CLASS_REFERENCE (asm_out_file, buf); >>> -#else >>> - return ; /* NULL build for targets other than Darwin. */ >>> -#endif >>> + /* We build a variable to signal that this TU contains this class >>> metadata. */ >>> + decl = build_decl (UNKNOWN_LOCATION, >>> + VAR_DECL, get_identifier (buf), char_type_node); >>> + TREE_PUBLIC (decl) = 1; >>> + DECL_CONTEXT (decl) = NULL_TREE; >>> + OBJCMETA (decl, objc_meta, get_identifier ("V1_CDEF")); >>> + TREE_STATIC (decl) = 1; >>> + DECL_ARTIFICIAL (decl) = 1; >>> + DECL_INITIAL (decl) = error_mark_node; >>> + finish_var_decl (decl, NULL); >>> } >>> >>> static void >>> Index: gcc/varasm.c >>> =================================================================== >>> --- gcc/varasm.c (revision 175628) >>> +++ gcc/varasm.c (working copy) >>> @@ -2009,6 +2009,10 @@ assemble_variable (tree decl, int top_level ATTRIB >>> align_variable (decl, dont_output_data); >>> set_mem_align (decl_rtl, DECL_ALIGN (decl)); >>> >>> + /* Allow the target to handle the variable output in some special >>> manner. >>> */ >>> + if (targetm.asm_out.handled_assemble_variable_p (decl)) >>> + return; >>> + >>> if (TREE_PUBLIC (decl)) >>> maybe_assemble_visibility (decl); >>> >>> Index: gcc/config/darwin-protos.h >>> =================================================================== >>> --- gcc/config/darwin-protos.h (revision 175628) >>> +++ gcc/config/darwin-protos.h (working copy) >>> @@ -106,6 +106,7 @@ extern void darwin_asm_output_aligned_decl_local ( >>> extern void darwin_asm_output_aligned_decl_common (FILE *, tree, const >>> char >>> *, >>> unsigned HOST_WIDE_INT, >>> unsigned int); >>> +extern bool darwin_handled_assemble_variable_p (tree); >>> >>> extern bool darwin_binds_local_p (const_tree); >>> extern void darwin_cpp_builtins (struct cpp_reader *); >>> Index: gcc/config/darwin.c >>> =================================================================== >>> --- gcc/config/darwin.c (revision 175628) >>> +++ gcc/config/darwin.c (working copy) >>> @@ -1439,6 +1439,11 @@ darwin_objc1_section (tree decl ATTRIBUTE_UNUSED, >>> else if (!strncmp (p, "V2_CSTR", 7)) >>> return darwin_sections[objc_constant_string_object_section]; >>> >>> + else if (!strncmp (p, "V1_CREF", 7)) >>> + return darwin_sections[objc_cls_refs_section]; >>> + else if (!strncmp (p, "V1_CDEF", 7)) >>> + return data_section; >>> + >>> return base; >>> } >>> >>> @@ -2594,6 +2599,53 @@ darwin_assemble_visibility (tree decl, int vis) >>> "not supported in this configuration; ignored"); >>> } >>> >>> +/* For certain Objective-C metadata we handle the assembly of the >>> variables >>> + here (it must be here, rather than in darwin-c.c, to cater for LTO). >>> When >>> + we reference a class we emit a lazy ref, when we have class metadata >>> + (local to a specific object), we emit a tag so that linkage will be >>> + satisfied for the class. */ >>> + >>> +bool >>> +darwin_handled_assemble_variable_p (tree decl) >>> +{ >>> + tree meta; >>> + if (DECL_ATTRIBUTES (decl) >>> + && (meta = lookup_attribute ("OBJC1META", DECL_ATTRIBUTES >>> (decl)))) >>> + { >>> + const char *name; >>> + rtx decl_rtl, symbol; >>> + >>> + if (TREE_VALUE (meta) == get_identifier ("V1_CREF")) >>> + { >>> + tree exp = DECL_INITIAL (decl); >>> + gcc_assert (exp >>> + && exp != error_mark_node >>> + && TREE_CODE (exp) == ADDR_EXPR); >>> + exp = TREE_OPERAND (exp, 0); >>> + decl_rtl = DECL_RTL (exp); >>> + symbol = XEXP (decl_rtl, 0); >>> + name = XSTR (symbol, 0); >>> + targetm.asm_out.globalize_decl_name (asm_out_file, exp); >>> + fputs ("\t.lazy_reference\t",asm_out_file); >>> + assemble_name (asm_out_file, name); >>> + fputs ("\n",asm_out_file); >>> + return true; >>> + } >>> + else if (TREE_VALUE (meta) == get_identifier ("V1_CDEF")) >>> + { >>> + decl_rtl = DECL_RTL (decl); >>> + symbol = XEXP (decl_rtl, 0); >>> + name = XSTR (symbol, 0); >>> + targetm.asm_out.globalize_decl_name (asm_out_file, decl); >>> + fputs ("\t",asm_out_file); >>> + assemble_name (asm_out_file, name); >>> + fputs (" = 0\n",asm_out_file); >>> + return true; >>> + } >>> + } >>> + return false; >>> +} >>> + >>> /* VEC Used by darwin_asm_dwarf_section. >>> Maybe a hash tab would be better here - but the intention is that this >>> is >>> a very short list (fewer than 16 items) and each entry should (ideally, >>> Index: gcc/config/darwin.h >>> =================================================================== >>> --- gcc/config/darwin.h (revision 175628) >>> +++ gcc/config/darwin.h (working copy) >>> @@ -678,6 +678,9 @@ extern GTY(()) section * darwin_sections[NUM_DARWI >>> #undef TARGET_ASM_SELECT_SECTION >>> #define TARGET_ASM_SELECT_SECTION machopic_select_section >>> >>> +#undef TARGET_ASM_HANDLED_ASSEMBLE_VARIABLE_P >>> +#define TARGET_ASM_HANDLED_ASSEMBLE_VARIABLE_P >>> darwin_handled_assemble_variable_p >>> + >>> #undef TARGET_ASM_FUNCTION_SECTION >>> #define TARGET_ASM_FUNCTION_SECTION darwin_function_section >>> >>> >>> >>> > >