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.  Not sure if this is the most reasonable piece of
assemble_variable to split out to a hook though.

I'm not sure we want to backport this though (there isn't even a bugreport
about it?).

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
>
>
>
>

Reply via email to