This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: dwarf2out tree expression expansion improvements


On Wed, 16 Sep 2009, Jan Hubicka wrote:

> Hi,
> this is updated patch.  I kept the dumping but added function for it so
> it less obstructates the source code.  I can remove it if it seems
> better, but I think it is useful.  If it is accepted, I will add same
> dumping into RTL expasion.  
> 
> The patch also adds dump file for final where part of messages depart.
> The output looks like following:
> 
> Failed to expand as dwarf: _rtx
> Reason: DECL has no RTL
> 
> Failed to expand as dwarf: tem
> Reason: DECL has no RTL
> 
> Failed to expand as dwarf: orig_code
> Reason: DECL has no RTL
> 
> Failed to expand as dwarf: mask
> (reg/v:DI 246 [ mask ])
> Reason: failed to produce loc descriptor for rtl
> 
> Failed to expand as dwarf: is_mode
> Reason: DECL has no RTL
> 
> Failed to expand as dwarf: inner_mode
> Reason: DECL has no RTL
> 
> Failed to expand as dwarf: orig_pos
> Reason: DECL has no RTL
> 
> Failed to expand as dwarf: offset
> (reg/v:DI 117 [ offset ])
> Reason: failed to produce loc descriptor for rtl
> 
> (this is excerpt from combine.c compilation. With inline tracking or
> variable bound arrays we expand more exotic expressions too and thus
> get more interesting set of failure reasons)
> 
> Other part of dwarf processing happens at the end of compilation unit
> that has no dump file, perhaps we can just open the .final dump there
> too?  It is technically IPA pass, I can also add pass called
> end_of_compilation to the end of queue.
> 
> I am bootstrapping/regtesting x86_64-linux now after some last minute
> changes, but since it was all in debug output, it should be fine. OK if
> it passes?

I'm happy with the changes.  If Jakub thinks the whole plan is sound
the patch is ok.  You might want to consider inlining the
dump_file && (dump_flags & TDF_DETAILS) check though.

Thanks,
Richard.

> Honza
> 
> 	* dwarf2out.c: Include tree-pass.h and gimple.h
> 	(loc_list_plus_const): New function.
> 	(loc_descriptor_from_tree_1): Rename to ...
> 	(loc_descriptor_from_tree): ... remove original.
> 	(loc_list_from_tree): New function.
> 	(add_AT_location_description): Accept location list.
> 	(tls_mem_loc_descriptor): Update call of loc_descriptor_from_tree.
> 	(mem_loc_descriptor): Handle CONCAT and VAR_LOCATION.
> 	(secname_for_decl): Move up.
> 	(hidden_reference_p): New function; break out from ...
> 	(loc_by_refernece): ... here; move up.
> 	(dw_loc_list): New function.
> 	(single_element_loc_list): New function.
> 	(single_element_loc_list_p): New function.
> 	(add_loc_descr_to_each): New function.
> 	(add_loc_list): New function.
> 	(loc_descr_from_tree): Make wraper of loc_list_from_tree.
> 	(loc_list_from_tree): Reroganized from loc_descr_from_tree;
> 	add diagnostics why expansion failed.
> 	(add_location_or_const_value_attribute): Support location lists.
> 	(add_bound_info): Likewise.
> 	(descr_info_loc): Update call of loc_descriptor_from_tree.
> 	(gen_variable_die): Work on location lists.
> 	* final.c (pass_final): Add dump file.
> 	* Makefile.in (dwarf2out.o): Add new dependencies.
> 
> Index: final.c
> ===================================================================
> *** final.c	(revision 151743)
> --- final.c	(working copy)
> *************** struct rtl_opt_pass pass_final =
> *** 4304,4310 ****
>   {
>    {
>     RTL_PASS,
> !   NULL,                                 /* name */
>     NULL,                                 /* gate */
>     rest_of_handle_final,                 /* execute */
>     NULL,                                 /* sub */
> --- 4304,4310 ----
>   {
>    {
>     RTL_PASS,
> !   "final",                              /* name */
>     NULL,                                 /* gate */
>     rest_of_handle_final,                 /* execute */
>     NULL,                                 /* sub */
> Index: dwarf2out.c
> ===================================================================
> *** dwarf2out.c	(revision 151743)
> --- dwarf2out.c	(working copy)
> *************** along with GCC; see the file COPYING3.  
> *** 89,94 ****
> --- 89,96 ----
>   #include "hashtab.h"
>   #include "cgraph.h"
>   #include "input.h"
> + #include "gimple.h"
> + #include "tree-pass.h"
>   
>   #ifdef DWARF2_DEBUGGING_INFO
>   static void dwarf2out_source_line (unsigned int, const char *, int, bool);
> *************** loc_descr_plus_const (dw_loc_descr_ref *
> *** 4655,4660 ****
> --- 4657,4672 ----
>       }
>   }
>   
> + /* Add a constant OFFSET to a location list.  */
> + 
> + static void
> + loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset)
> + {
> +   dw_loc_list_ref d;
> +   for (d = list_head; d != NULL; d = d->dw_loc_next)
> +     loc_descr_plus_const (&d->expr, offset);
> + }
> + 
>   /* Return the size of a location descriptor.  */
>   
>   static unsigned long
> *************** static dw_loc_descr_ref concat_loc_descr
> *** 5938,5945 ****
>   					       enum var_init_status);
>   static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
>   					enum var_init_status);
> ! static dw_loc_descr_ref loc_descriptor_from_tree_1 (tree, int);
> ! static dw_loc_descr_ref loc_descriptor_from_tree (tree);
>   static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
>   static tree field_type (const_tree);
>   static unsigned int simple_type_align_in_bits (const_tree);
> --- 5950,5957 ----
>   					       enum var_init_status);
>   static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
>   					enum var_init_status);
> ! static dw_loc_list_ref loc_list_from_tree (tree, int);
> ! static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
>   static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
>   static tree field_type (const_tree);
>   static unsigned int simple_type_align_in_bits (const_tree);
> *************** static unsigned int simple_decl_align_in
> *** 5947,5953 ****
>   static unsigned HOST_WIDE_INT simple_type_size_in_bits (const_tree);
>   static HOST_WIDE_INT field_byte_offset (const_tree);
>   static void add_AT_location_description	(dw_die_ref, enum dwarf_attribute,
> ! 					 dw_loc_descr_ref);
>   static void add_data_member_location_attribute (dw_die_ref, tree);
>   static void add_const_value_attribute (dw_die_ref, rtx);
>   static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
> --- 5959,5965 ----
>   static unsigned HOST_WIDE_INT simple_type_size_in_bits (const_tree);
>   static HOST_WIDE_INT field_byte_offset (const_tree);
>   static void add_AT_location_description	(dw_die_ref, enum dwarf_attribute,
> ! 					 dw_loc_list_ref);
>   static void add_data_member_location_attribute (dw_die_ref, tree);
>   static void add_const_value_attribute (dw_die_ref, rtx);
>   static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
> *************** tls_mem_loc_descriptor (rtx mem)
> *** 11006,11012 ****
>         || !DECL_THREAD_LOCAL_P (base))
>       return NULL;
>   
> !   loc_result = loc_descriptor_from_tree_1 (MEM_EXPR (mem), 2);
>     if (loc_result == NULL)
>       return NULL;
>   
> --- 11018,11024 ----
>         || !DECL_THREAD_LOCAL_P (base))
>       return NULL;
>   
> !   loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 2);
>     if (loc_result == NULL)
>       return NULL;
>   
> *************** tls_mem_loc_descriptor (rtx mem)
> *** 11016,11021 ****
> --- 11028,11053 ----
>     return loc_result;
>   }
>   
> + /* Output debug info about reason why we failed to expand expression as dwarf
> +    expression.  */
> + 
> + static void
> + expansion_failed (tree expr, rtx rtl, char const *reason)
> + {
> +   if (dump_file && (dump_flags & TDF_DETAILS))
> +     {
> +       fprintf (dump_file, "Failed to expand as dwarf: ");
> +       if (expr)
> +         print_generic_expr (dump_file, expr, dump_flags);
> +       if (rtl)
> +  	{
> +  	  fprintf (dump_file, "\n");
> + 	  print_rtl (dump_file, rtl);
> + 	}
> +       fprintf (dump_file, "\nReason: %s\n", reason);
> +     }
> + }
> + 
>   /* The following routine converts the RTL for a variable or parameter
>      (resident in memory) into an equivalent Dwarf representation of a
>      mechanism for getting the address of that same variable onto the top of a
> *************** mem_loc_descriptor (rtx rtl, enum machin
> *** 11163,11169 ****
>   	     FIXME: might try to use DW_OP_const_value here, though
>   	     DW_OP_piece complicates it.  */
>   	  if (!marked)
> ! 	    return 0;
>   	}
>   
>         if (GET_CODE (rtl) == SYMBOL_REF
> --- 11195,11205 ----
>   	     FIXME: might try to use DW_OP_const_value here, though
>   	     DW_OP_piece complicates it.  */
>   	  if (!marked)
> ! 	    {
> ! 	      expansion_failed (NULL_TREE, rtl,
> ! 				"Constant was removed from constant pool.\n");
> ! 	      return 0;
> ! 	    }
>   	}
>   
>         if (GET_CODE (rtl) == SYMBOL_REF
> *************** mem_loc_descriptor (rtx rtl, enum machin
> *** 11193,11198 ****
> --- 11229,11250 ----
>         VEC_safe_push (rtx, gc, used_rtx_array, rtl);
>         break;
>   
> +     case CONCAT:
> +       {
> +         rtx x0 = XEXP (rtl, 0);
> +         rtx x1 = XEXP (rtl, 1);
> +         dw_loc_descr_ref x0_ref = mem_loc_descriptor (x0, GET_MODE (x0), VAR_INIT_STATUS_INITIALIZED);
> +         dw_loc_descr_ref x1_ref = mem_loc_descriptor (x1, GET_MODE (x1), VAR_INIT_STATUS_INITIALIZED);
> + 	if (x0_ref == 0 || x1_ref == 0)
> + 	  return 0;
> + 	mem_loc_result = x0_ref;
> + 	add_loc_descr_op_piece (&mem_loc_result, GET_MODE_SIZE (GET_MODE (x0)));
> + 
> + 	add_loc_descr (&mem_loc_result, x1_ref);
> + 	add_loc_descr_op_piece (&mem_loc_result, GET_MODE_SIZE (GET_MODE (x1)));
> +       }
> +       break;
> + 
>       case PRE_MODIFY:
>         /* Extract the PLUS expression nested inside and fall into
>   	 PLUS code below.  */
> *************** mem_loc_descriptor (rtx rtl, enum machin
> *** 11327,11332 ****
> --- 11379,11397 ----
>   						   VAR_INIT_STATUS_INITIALIZED);
>         break;
>   
> +     case VAR_LOCATION:
> +       if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
> + 	{
> + 	  mem_loc_result = mem_loc_descriptor (XEXP (XEXP (rtl, 1), 0), mode, initialized);
> + 	  break;
> + 	}
> +       /* TODO: We can handle this case via OP_piece of dwarf stack machine operatoins.
> + 	 It should not be common case however.  */
> +       expansion_failed (NULL_TREE, rtl,
> + 			"Multipart value can not be used in value expression.\n");
> +       return 0;
> +       break;
> + 
>       case EQ:
>         op = DW_OP_eq;
>         goto do_scompare;
> *************** loc_descriptor (rtx rtl, enum machine_mo
> *** 11972,11987 ****
>     return loc_result;
>   }
>   
> ! /* Similar, but generate the descriptor from trees instead of rtl.  This comes
> !    up particularly with variable length arrays.  WANT_ADDRESS is 2 if this is
> !    a top-level invocation of loc_descriptor_from_tree; is 1 if this is not a
> !    top-level invocation, and we require the address of LOC; is 0 if we require
> !    the value of LOC.  */
>   
>   static dw_loc_descr_ref
> ! loc_descriptor_from_tree_1 (tree loc, int want_address)
>   {
> !   dw_loc_descr_ref ret, ret1;
>     int have_address = 0;
>     enum dwarf_location_atom op;
>   
> --- 12037,12318 ----
>     return loc_result;
>   }
>   
> ! /* We need to figure out what section we should use as the base for the
> !    address ranges where a given location is valid.
> !    1. If this particular DECL has a section associated with it, use that.
> !    2. If this function has a section associated with it, use that.
> !    3. Otherwise, use the text section.
> !    XXX: If you split a variable across multiple sections, we won't notice.  */
> ! 
> ! static const char *
> ! secname_for_decl (const_tree decl)
> ! {
> !   const char *secname;
> ! 
> !   if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
> !     {
> !       tree sectree = DECL_SECTION_NAME (decl);
> !       secname = TREE_STRING_POINTER (sectree);
> !     }
> !   else if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
> !     {
> !       tree sectree = DECL_SECTION_NAME (current_function_decl);
> !       secname = TREE_STRING_POINTER (sectree);
> !     }
> !   else if (cfun && in_cold_section_p)
> !     secname = crtl->subsections.cold_section_label;
> !   else
> !     secname = text_section_label;
> ! 
> !   return secname;
> ! }
> ! 
> ! static bool
> ! hidden_reference_p (tree decl)
> ! {
> !   return ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL
> !   	   || (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl)))
> ! 	  && DECL_BY_REFERENCE (decl));
> ! }
> ! 
> ! /* Dereference a location expression LOC if DECL is passed by invisible
> !    reference.  */
>   
>   static dw_loc_descr_ref
> ! loc_by_reference (dw_loc_descr_ref loc, tree decl)
> ! {
> !   HOST_WIDE_INT size;
> !   enum dwarf_location_atom op;
> ! 
> !   if (loc == NULL)
> !     return NULL;
> ! 
> !   if (!hidden_reference_p (decl))
> !     return loc;
> ! 
> !   /* If loc is DW_OP_reg{0...31,x}, don't add DW_OP_deref, instead
> !      change it into corresponding DW_OP_breg{0...31,x} 0.  Then the
> !      location expression is considered to be address of a memory location,
> !      rather than the register itself.  */
> !   if (((loc->dw_loc_opc >= DW_OP_reg0 && loc->dw_loc_opc <= DW_OP_reg31)
> !        || loc->dw_loc_opc == DW_OP_regx)
> !       && (loc->dw_loc_next == NULL
> ! 	  || (loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_uninit
> ! 	      && loc->dw_loc_next->dw_loc_next == NULL)))
> !     {
> !       if (loc->dw_loc_opc == DW_OP_regx)
> ! 	{
> ! 	  loc->dw_loc_opc = DW_OP_bregx;
> ! 	  loc->dw_loc_oprnd2.v.val_int = 0;
> ! 	}
> !       else
> ! 	{
> ! 	  loc->dw_loc_opc
> ! 	    = (enum dwarf_location_atom)
> ! 	      (loc->dw_loc_opc + (DW_OP_breg0 - DW_OP_reg0));
> ! 	  loc->dw_loc_oprnd1.v.val_int = 0;
> ! 	}
> !       return loc;
> !     }
> ! 
> !   size = int_size_in_bytes (TREE_TYPE (decl));
> !   if (size > DWARF2_ADDR_SIZE || size == -1)
> !     return 0;
> !   else if (size == DWARF2_ADDR_SIZE)
> !     op = DW_OP_deref;
> !   else
> !     op = DW_OP_deref_size;
> !   add_loc_descr (&loc, new_loc_descr (op, size, 0));
> !   return loc;
> ! }
> ! 
> ! /* Return dwarf representation of location list representing for
> !    LOC_LIST of DECL.  */
> ! 
> ! static dw_loc_list_ref
> ! dw_loc_list (var_loc_list * loc_list, tree decl, bool toplevel)
> ! {
> !   const char *endname, *secname;
> !   dw_loc_list_ref list;
> !   rtx varloc;
> !   enum var_init_status initialized;
> !   struct var_loc_node *node;
> !   dw_loc_descr_ref descr;
> !   char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
> ! 
> !   bool by_reference = hidden_reference_p (decl);
> ! 
> !   /* Now that we know what section we are using for a base,
> !      actually construct the list of locations.
> !      The first location information is what is passed to the
> !      function that creates the location list, and the remaining
> !      locations just get added on to that list.
> !      Note that we only know the start address for a location
> !      (IE location changes), so to build the range, we use
> !      the range [current location start, next location start].
> !      This means we have to special case the last node, and generate
> !      a range of [last location start, end of function label].  */
> ! 
> !   node = loc_list->first;
> !   varloc = NOTE_VAR_LOCATION (node->var_loc_note);
> !   secname = secname_for_decl (decl);
> ! 
> !   if (NOTE_VAR_LOCATION_LOC (node->var_loc_note))
> !     initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
> !   else
> !     initialized = VAR_INIT_STATUS_INITIALIZED;
> ! 
> !   if (!toplevel || by_reference)
> !     descr = loc_by_reference (mem_loc_descriptor (varloc,
> ! 						  TYPE_MODE (TREE_TYPE (decl)),
> ! 						  initialized),
> ! 			      decl);
> !   else
> !     descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
> !     					      initialized), decl);
> ! 
> !   if (!current_function_decl)
> !     endname = text_end_label;
> !   else
> !     {
> !       ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
> ! 				   current_function_funcdef_no);
> !       endname = ggc_strdup (label_id);
> !     }
> !   list = new_loc_list (descr, node->label, node->next ? node->next->label : endname, secname, 1);
> !   node = node->next;
> ! 
> !   if (!node)
> !     return NULL;
> ! 
> !   for (; node->next; node = node->next)
> !     if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
> !       {
> ! 	/* The variable has a location between NODE->LABEL and
> ! 	   NODE->NEXT->LABEL.  */
> ! 	enum var_init_status initialized =
> ! 	  NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
> ! 	varloc = NOTE_VAR_LOCATION (node->var_loc_note);
> ! 	if (!toplevel || by_reference)
> ! 	  descr = mem_loc_descriptor (varloc, TYPE_MODE (TREE_TYPE (decl)), initialized);
> ! 	else
> ! 	  descr = loc_descriptor (varloc, DECL_MODE (decl), initialized);
> ! 	descr = loc_by_reference (descr, decl);
> ! 	add_loc_descr_to_loc_list (&list, descr,
> ! 				   node->label, node->next->label, secname);
> !       }
> ! 
> !   /* If the variable has a location at the last label
> !      it keeps its location until the end of function.  */
> !   if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
> !     {
> !       enum var_init_status initialized =
> ! 	NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
> ! 
> !       varloc = NOTE_VAR_LOCATION (node->var_loc_note);
> !       descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
> !       						initialized), decl);
> !       add_loc_descr_to_loc_list (&list, descr, node->label, endname, secname);
> !     }
> !   return list;
> ! }
> ! 
> ! /* Return single element location list containing loc descr REF.  */
> ! 
> ! static dw_loc_list_ref
> ! single_element_loc_list (dw_loc_descr_ref ref)
> ! {
> !   return new_loc_list (ref, NULL, NULL, NULL, 0);
> ! }
> ! 
> ! /* Return if the loc_list has only single element and thus can be represented
> !    as location description.   */
> ! 
> ! static bool
> ! single_element_loc_list_p (dw_loc_list_ref list)
> ! {
> !   return (!list->dw_loc_next && !list->begin && !list->end);
> ! }
> ! 
> ! /* To each location in list LIST add loc descr REF.  */
> ! 
> ! static void
> ! add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
>   {
> !   dw_loc_descr_ref copy;
> !   add_loc_descr (&list->expr, ref);
> !   list = list->dw_loc_next;
> !   while (list)
> !     {
> !       copy = GGC_CNEW (dw_loc_descr_node);
> !       memcpy (copy, ref, sizeof (dw_loc_descr_node));
> !       add_loc_descr (&list->expr, copy);
> !       while (copy->dw_loc_next)
> ! 	{
> !           dw_loc_descr_ref new_copy = GGC_CNEW (dw_loc_descr_node);
> ! 	  memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
> ! 	  copy->dw_loc_next = new_copy;
> ! 	  copy = new_copy;
> ! 	}
> !       list = list->dw_loc_next;
> !     }
> ! }
> ! 
> ! /* Given two lists RET and LIST
> !    produce location list that is result of adding expression in LIST
> !    to expression in RET on each possition in program.
> !    Might be destructive on both RET and LIST.
> ! 
> !    TODO: We handle only simple cases of RET or LIST having at most one
> !    element. General case would inolve sorting the lists in program order
> !    and merging them that will need some additional work.  
> !    Adding that will improve quality of debug info especially for SRA-ed
> !    structures.  */
> ! 
> ! static void
> ! add_loc_list (dw_loc_list_ref *ret, dw_loc_list_ref list)
> ! {
> !   if (!list)
> !     return;
> !   if (!*ret)
> !     {
> !       *ret = list;
> !       return;
> !     }
> !   if (!list->dw_loc_next)
> !     {
> !       add_loc_descr_to_each (*ret, list->expr);
> !       return;
> !     }
> !   if (!(*ret)->dw_loc_next)
> !     {
> !       add_loc_descr_to_each (list, (*ret)->expr);
> !       *ret = list;
> !       return;
> !     }
> !   expansion_failed (NULL_TREE, NULL_RTX,
> ! 		    "Don't know how to merge two non-trivial"
> ! 		    " location lists.\n");
> !   *ret = NULL;
> !   return;
> ! }
> ! 
> ! /* Generate Dwarf location list representing LOC.
> !    If WANT_ADDRESS is 0, expression computing LOC will be computed
> !    If WANT_ADDRESS is 1, expression computing address of LOC will be returned
> !    if WANT_ADDRESS is 2, expression computing address useable in location
> !      will be returned (i.e. DW_OP_reg can be used
> !      to refer to register values) 
> !    TODO: Dwarf4 adds types to the stack machine that ought to be used here
> !    DW_OP_stack_value will help in cases where we fail to find address of the
> !    expression.
> !  */
> ! 
> ! static dw_loc_list_ref
> ! loc_list_from_tree (tree loc, int want_address)
> ! {
> !   dw_loc_descr_ref ret = NULL, ret1 = NULL;
> !   dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
>     int have_address = 0;
>     enum dwarf_location_atom op;
>   
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 11992,11997 ****
> --- 12323,12329 ----
>     switch (TREE_CODE (loc))
>       {
>       case ERROR_MARK:
> +       expansion_failed (loc, NULL_RTX, "ERROR_MARK");
>         return 0;
>   
>       case PLACEHOLDER_EXPR:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 11999,12023 ****
>   	 position of other fields.  We don't try to encode this here.  The
>   	 only user of this is Ada, which encodes the needed information using
>   	 the names of types.  */
>         return 0;
>   
>       case CALL_EXPR:
>         return 0;
>   
>       case PREINCREMENT_EXPR:
>       case PREDECREMENT_EXPR:
>       case POSTINCREMENT_EXPR:
>       case POSTDECREMENT_EXPR:
>         /* There are no opcodes for these operations.  */
>         return 0;
>   
>       case ADDR_EXPR:
>         /* If we already want an address, there's nothing we can do.  */
>         if (want_address)
> ! 	return 0;
>   
>         /* Otherwise, process the argument and look for the address.  */
> !       return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 1);
>   
>       case VAR_DECL:
>         if (DECL_THREAD_LOCAL_P (loc))
> --- 12331,12362 ----
>   	 position of other fields.  We don't try to encode this here.  The
>   	 only user of this is Ada, which encodes the needed information using
>   	 the names of types.  */
> +       expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR");
>         return 0;
>   
>       case CALL_EXPR:
> +       expansion_failed (loc, NULL_RTX, "CALL_EXPR");
> +       /* There are no opcodes for these operations.  */
>         return 0;
>   
>       case PREINCREMENT_EXPR:
>       case PREDECREMENT_EXPR:
>       case POSTINCREMENT_EXPR:
>       case POSTDECREMENT_EXPR:
> +       expansion_failed (loc, NULL_RTX, "PRE/POST INDCREMENT/DECREMENT");
>         /* There are no opcodes for these operations.  */
>         return 0;
>   
>       case ADDR_EXPR:
>         /* If we already want an address, there's nothing we can do.  */
>         if (want_address)
> !         {
> ! 	  expansion_failed (loc, NULL_RTX, "need address of ADDR_EXPR");
> ! 	  return 0;
> ! 	}
>   
>         /* Otherwise, process the argument and look for the address.  */
> !       return loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
>   
>       case VAR_DECL:
>         if (DECL_THREAD_LOCAL_P (loc))
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12077,12093 ****
>   
>       case PARM_DECL:
>         if (DECL_HAS_VALUE_EXPR_P (loc))
> ! 	return loc_descriptor_from_tree_1 (DECL_VALUE_EXPR (loc),
> ! 					   want_address);
>         /* FALLTHRU */
>   
>       case RESULT_DECL:
>       case FUNCTION_DECL:
>         {
>   	rtx rtl = rtl_for_decl_location (loc);
>   
> ! 	if (rtl == NULL_RTX)
> ! 	  return 0;
>   	else if (CONST_INT_P (rtl))
>   	  {
>   	    HOST_WIDE_INT val = INTVAL (rtl);
> --- 12416,12439 ----
>   
>       case PARM_DECL:
>         if (DECL_HAS_VALUE_EXPR_P (loc))
> ! 	return loc_list_from_tree (DECL_VALUE_EXPR (loc),
> ! 					      want_address);
>         /* FALLTHRU */
>   
>       case RESULT_DECL:
>       case FUNCTION_DECL:
>         {
>   	rtx rtl = rtl_for_decl_location (loc);
> + 	var_loc_list *loc_list = lookup_decl_loc (loc);
>   
> ! 	if (loc_list && loc_list->first
> ! 	    && (list_ret = dw_loc_list (loc_list, loc, want_address == 2)))
> ! 	  have_address = 1;
> ! 	else if (rtl == NULL_RTX)
> ! 	  {
> ! 	    expansion_failed (loc, NULL_RTX, "DECL has no RTL");
> ! 	    return 0;
> ! 	  }
>   	else if (CONST_INT_P (rtl))
>   	  {
>   	    HOST_WIDE_INT val = INTVAL (rtl);
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12096,12102 ****
>   	    ret = int_loc_descriptor (val);
>   	  }
>   	else if (GET_CODE (rtl) == CONST_STRING)
> ! 	  return 0;
>   	else if (CONSTANT_P (rtl))
>   	  {
>   	    ret = new_loc_descr (DW_OP_addr, 0, 0);
> --- 12442,12451 ----
>   	    ret = int_loc_descriptor (val);
>   	  }
>   	else if (GET_CODE (rtl) == CONST_STRING)
> ! 	  {
> ! 	    expansion_failed (loc, NULL_RTX, "CONST_STRING");
> ! 	    return 0;
> ! 	  }
>   	else if (CONSTANT_P (rtl))
>   	  {
>   	    ret = new_loc_descr (DW_OP_addr, 0, 0);
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12109,12141 ****
>   
>   	    /* Certain constructs can only be represented at top-level.  */
>   	    if (want_address == 2)
> - 	      return loc_descriptor (rtl, VOIDmode,
> - 				     VAR_INIT_STATUS_INITIALIZED);
> - 
> - 	    mode = GET_MODE (rtl);
> - 	    if (MEM_P (rtl))
>   	      {
> ! 		rtl = XEXP (rtl, 0);
>   		have_address = 1;
>   	      }
> ! 	    ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
>   	  }
>         }
>         break;
>   
>       case INDIRECT_REF:
> !       ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
>         have_address = 1;
>         break;
>   
>       case COMPOUND_EXPR:
> !       return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), want_address);
>   
>       CASE_CONVERT:
>       case VIEW_CONVERT_EXPR:
>       case SAVE_EXPR:
>       case MODIFY_EXPR:
> !       return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), want_address);
>   
>       case COMPONENT_REF:
>       case BIT_FIELD_REF:
> --- 12458,12498 ----
>   
>   	    /* Certain constructs can only be represented at top-level.  */
>   	    if (want_address == 2)
>   	      {
> ! 	        ret = loc_descriptor (rtl, VOIDmode,
> ! 				      VAR_INIT_STATUS_INITIALIZED);
>   		have_address = 1;
>   	      }
> ! 	    if (!ret)
> ! 	      {
> ! 		mode = GET_MODE (rtl);
> ! 		if (MEM_P (rtl))
> ! 		  {
> ! 		    rtl = XEXP (rtl, 0);
> ! 		    have_address = 1;
> ! 		  }
> ! 		ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
> ! 	      }
> ! 	    if (!ret)
> ! 	      expansion_failed (loc, rtl,
> ! 				"failed to produce loc descriptor for rtl");
>   	  }
>         }
>         break;
>   
>       case INDIRECT_REF:
> !       list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
>         have_address = 1;
>         break;
>   
>       case COMPOUND_EXPR:
> !       return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address);
>   
>       CASE_CONVERT:
>       case VIEW_CONVERT_EXPR:
>       case SAVE_EXPR:
>       case MODIFY_EXPR:
> !       return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address);
>   
>       case COMPONENT_REF:
>       case BIT_FIELD_REF:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12151,12176 ****
>   	obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
>   				   &unsignedp, &volatilep, false);
>   
> ! 	if (obj == loc)
> ! 	  return 0;
>   
> ! 	ret = loc_descriptor_from_tree_1 (obj, 1);
> ! 	if (ret == 0
> ! 	    || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
>   	  return 0;
>   
>   	if (offset != NULL_TREE)
>   	  {
>   	    /* Variable offset.  */
> ! 	    ret1 = loc_descriptor_from_tree_1 (offset, 0);
> ! 	    if (ret1 == 0)
>   	      return 0;
> ! 	    add_loc_descr (&ret, ret1);
> ! 	    add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
>   	  }
>   
>   	bytepos = bitpos / BITS_PER_UNIT;
> ! 	loc_descr_plus_const (&ret, bytepos);
>   
>   	have_address = 1;
>   	break;
> --- 12508,12542 ----
>   	obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
>   				   &unsignedp, &volatilep, false);
>   
> ! 	gcc_assert (obj != loc);
>   
> ! 	list_ret = loc_list_from_tree (obj, 1);
> ! 	if (list_ret == 0)
>   	  return 0;
> + 	if (bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
> + 	  {
> + 	    expansion_failed (loc, NULL_RTX,
> + 			      "bitfield access");
> + 	    return 0;
> + 	  }
>   
>   	if (offset != NULL_TREE)
>   	  {
>   	    /* Variable offset.  */
> ! 	    list_ret1 = loc_list_from_tree (offset, 0);
> ! 	    if (list_ret1 == 0)
>   	      return 0;
> ! 	    add_loc_list (&list_ret, list_ret1);
> ! 	    if (!list_ret)
> ! 	      return 0;
> ! 	    add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_plus, 0, 0));
>   	  }
>   
>   	bytepos = bitpos / BITS_PER_UNIT;
> ! 	if (bytepos > 0)
> ! 	  add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
> ! 	else if (bytepos < 0)
> ! 	  loc_list_plus_const (list_ret, bytepos); 
>   
>   	have_address = 1;
>   	break;
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12180,12186 ****
>         if (host_integerp (loc, 0))
>   	ret = int_loc_descriptor (tree_low_cst (loc, 0));
>         else
> ! 	return 0;
>         break;
>   
>       case CONSTRUCTOR:
> --- 12546,12556 ----
>         if (host_integerp (loc, 0))
>   	ret = int_loc_descriptor (tree_low_cst (loc, 0));
>         else
> ! 	{
> ! 	  expansion_failed (loc, NULL_RTX,
> ! 			    "Integer operand is not host integer");
> ! 	  return 0;
> ! 	}
>         break;
>   
>       case CONSTRUCTOR:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12250,12260 ****
>         if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
>   	  && host_integerp (TREE_OPERAND (loc, 1), 0))
>   	{
> ! 	  ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
> ! 	  if (ret == 0)
>   	    return 0;
>   
> ! 	  loc_descr_plus_const (&ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
>   	  break;
>   	}
>   
> --- 12620,12630 ----
>         if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
>   	  && host_integerp (TREE_OPERAND (loc, 1), 0))
>   	{
> ! 	  list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
> ! 	  if (list_ret == 0)
>   	    return 0;
>   
> ! 	  loc_list_plus_const (list_ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
>   	  break;
>   	}
>   
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12298,12310 ****
>         goto do_binop;
>   
>       do_binop:
> !       ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
> !       ret1 = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
> !       if (ret == 0 || ret1 == 0)
>   	return 0;
>   
> !       add_loc_descr (&ret, ret1);
> !       add_loc_descr (&ret, new_loc_descr (op, 0, 0));
>         break;
>   
>       case TRUTH_NOT_EXPR:
> --- 12668,12682 ----
>         goto do_binop;
>   
>       do_binop:
> !       list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
> !       list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
> !       if (list_ret == 0 || list_ret1 == 0)
>   	return 0;
>   
> !       add_loc_list (&list_ret, list_ret1);
> !       if (list_ret == 0)
> ! 	return 0;
> !       add_loc_descr_to_each (list_ret, new_loc_descr (op, 0, 0));
>         break;
>   
>       case TRUTH_NOT_EXPR:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12321,12331 ****
>         goto do_unop;
>   
>       do_unop:
> !       ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
> !       if (ret == 0)
>   	return 0;
>   
> !       add_loc_descr (&ret, new_loc_descr (op, 0, 0));
>         break;
>   
>       case MIN_EXPR:
> --- 12693,12703 ----
>         goto do_unop;
>   
>       do_unop:
> !       list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
> !       if (list_ret == 0)
>   	return 0;
>   
> !       add_loc_descr_to_each (list_ret, new_loc_descr (op, 0, 0));
>         break;
>   
>       case MIN_EXPR:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12345,12373 ****
>       case COND_EXPR:
>         {
>   	dw_loc_descr_ref lhs
> ! 	  = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
> ! 	dw_loc_descr_ref rhs
> ! 	  = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 2), 0);
>   	dw_loc_descr_ref bra_node, jump_node, tmp;
>   
> ! 	ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
> ! 	if (ret == 0 || lhs == 0 || rhs == 0)
>   	  return 0;
>   
>   	bra_node = new_loc_descr (DW_OP_bra, 0, 0);
> ! 	add_loc_descr (&ret, bra_node);
>   
> ! 	add_loc_descr (&ret, rhs);
>   	jump_node = new_loc_descr (DW_OP_skip, 0, 0);
> ! 	add_loc_descr (&ret, jump_node);
>   
> ! 	add_loc_descr (&ret, lhs);
>   	bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
>   	bra_node->dw_loc_oprnd1.v.val_loc = lhs;
>   
>   	/* ??? Need a node to point the skip at.  Use a nop.  */
>   	tmp = new_loc_descr (DW_OP_nop, 0, 0);
> ! 	add_loc_descr (&ret, tmp);
>   	jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
>   	jump_node->dw_loc_oprnd1.v.val_loc = tmp;
>         }
> --- 12717,12745 ----
>       case COND_EXPR:
>         {
>   	dw_loc_descr_ref lhs
> ! 	  = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
> ! 	dw_loc_list_ref rhs
> ! 	  = loc_list_from_tree (TREE_OPERAND (loc, 2), 0);
>   	dw_loc_descr_ref bra_node, jump_node, tmp;
>   
> ! 	list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
> ! 	if (list_ret == 0 || lhs == 0 || rhs == 0)
>   	  return 0;
>   
>   	bra_node = new_loc_descr (DW_OP_bra, 0, 0);
> ! 	add_loc_descr_to_each (list_ret, bra_node);
>   
> ! 	add_loc_list (&list_ret, rhs);
>   	jump_node = new_loc_descr (DW_OP_skip, 0, 0);
> ! 	add_loc_descr_to_each (list_ret, jump_node);
>   
> ! 	add_loc_descr_to_each (list_ret, lhs);
>   	bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
>   	bra_node->dw_loc_oprnd1.v.val_loc = lhs;
>   
>   	/* ??? Need a node to point the skip at.  Use a nop.  */
>   	tmp = new_loc_descr (DW_OP_nop, 0, 0);
> ! 	add_loc_descr_to_each (list_ret, tmp);
>   	jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
>   	jump_node->dw_loc_oprnd1.v.val_loc = tmp;
>         }
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12381,12387 ****
>   	 up, for instance, with the C STMT_EXPR.  */
>         if ((unsigned int) TREE_CODE (loc)
>   	  >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
> ! 	return 0;
>   
>   #ifdef ENABLE_CHECKING
>         /* Otherwise this is a generic code; we should just lists all of
> --- 12753,12763 ----
>   	 up, for instance, with the C STMT_EXPR.  */
>         if ((unsigned int) TREE_CODE (loc)
>   	  >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
> ! 	{
> ! 	  expansion_failed (loc, NULL_RTX,
> ! 			    "language specific tree node");
> ! 	  return 0;
> ! 	}
>   
>   #ifdef ENABLE_CHECKING
>         /* Otherwise this is a generic code; we should just lists all of
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12394,12425 ****
>   #endif
>       }
>   
>     /* Show if we can't fill the request for an address.  */
>     if (want_address && !have_address)
> !     return 0;
>   
>     /* If we've got an address and don't want one, dereference.  */
> !   if (!want_address && have_address && ret)
>       {
>         HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
>   
>         if (size > DWARF2_ADDR_SIZE || size == -1)
> ! 	return 0;
>         else if (size == DWARF2_ADDR_SIZE)
>   	op = DW_OP_deref;
>         else
>   	op = DW_OP_deref_size;
>   
> !       add_loc_descr (&ret, new_loc_descr (op, size, 0));
>       }
>   
> !   return ret;
>   }
>   
> ! static inline dw_loc_descr_ref
> ! loc_descriptor_from_tree (tree loc)
>   {
> !   return loc_descriptor_from_tree_1 (loc, 2);
>   }
>   
>   /* Given a value, round it up to the lowest multiple of `boundary'
> --- 12770,12829 ----
>   #endif
>       }
>   
> +   if (!ret && !list_ret)
> +     return 0;
> + 
>     /* Show if we can't fill the request for an address.  */
>     if (want_address && !have_address)
> !     {
> !       expansion_failed (loc, NULL_RTX,
> ! 			"Want address and only have value");
> !       return 0;
> !     }
> ! 
> !   gcc_assert (!ret || !list_ret);
>   
>     /* If we've got an address and don't want one, dereference.  */
> !   if (!want_address && have_address)
>       {
>         HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
>   
>         if (size > DWARF2_ADDR_SIZE || size == -1)
> ! 	{
> ! 	  expansion_failed (loc, NULL_RTX,
> ! 			    "DWARF address size mismatch");
> ! 	  return 0;
> ! 	}
>         else if (size == DWARF2_ADDR_SIZE)
>   	op = DW_OP_deref;
>         else
>   	op = DW_OP_deref_size;
>   
> !       if (ret)
> !         add_loc_descr (&ret, new_loc_descr (op, size, 0));
> !       else
> ! 	add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0));
>       }
> +   if (ret)
> +     list_ret = single_element_loc_list (ret);
>   
> !   return list_ret;
>   }
>   
> ! /* Same as above but return only single location expression.  */
> ! static dw_loc_descr_ref
> ! loc_descriptor_from_tree (tree loc, int want_address)
>   {
> !   dw_loc_list_ref ret = loc_list_from_tree (loc, want_address);
> !   if (!ret)
> !     return NULL;
> !   if (ret->dw_loc_next)
> !     {
> !       expansion_failed (loc, NULL_RTX,
> ! 			"Location list where only loc descriptor needed");
> !       return NULL;
> !     }
> !   return ret->expr;
>   }
>   
>   /* Given a value, round it up to the lowest multiple of `boundary'
> *************** field_byte_offset (const_tree decl)
> *** 12626,12635 ****
>   
>   static inline void
>   add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind,
> ! 			     dw_loc_descr_ref descr)
>   {
> !   if (descr != 0)
> !     add_AT_loc (die, attr_kind, descr);
>   }
>   
>   /* Attach the specialized form of location attribute used for data members of
> --- 13030,13043 ----
>   
>   static inline void
>   add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind,
> ! 			     dw_loc_list_ref descr)
>   {
> !   if (descr == 0)
> !     return;
> !   if (single_element_loc_list_p (descr))
> !     add_AT_loc (die, attr_kind, descr->expr);
> !   else
> !     add_AT_loc_list (die, attr_kind, descr);
>   }
>   
>   /* Attach the specialized form of location attribute used for data members of
> *************** rtl_for_decl_location (tree decl)
> *** 13267,13302 ****
>     return rtl;
>   }
>   
> - /* We need to figure out what section we should use as the base for the
> -    address ranges where a given location is valid.
> -    1. If this particular DECL has a section associated with it, use that.
> -    2. If this function has a section associated with it, use that.
> -    3. Otherwise, use the text section.
> -    XXX: If you split a variable across multiple sections, we won't notice.  */
> - 
> - static const char *
> - secname_for_decl (const_tree decl)
> - {
> -   const char *secname;
> - 
> -   if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
> -     {
> -       tree sectree = DECL_SECTION_NAME (decl);
> -       secname = TREE_STRING_POINTER (sectree);
> -     }
> -   else if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
> -     {
> -       tree sectree = DECL_SECTION_NAME (current_function_decl);
> -       secname = TREE_STRING_POINTER (sectree);
> -     }
> -   else if (cfun && in_cold_section_p)
> -     secname = crtl->subsections.cold_section_label;
> -   else
> -     secname = text_section_label;
> - 
> -   return secname;
> - }
> - 
>   /* Check whether decl is a Fortran COMMON symbol.  If not, NULL_TREE is
>      returned.  If so, the decl for the COMMON block is returned, and the
>      value is the offset into the common block for the symbol.  */
> --- 13675,13680 ----
> *************** fortran_common (tree decl, HOST_WIDE_INT
> *** 13347,13406 ****
>     return cvar;
>   }
>   
> - /* Dereference a location expression LOC if DECL is passed by invisible
> -    reference.  */
> - 
> - static dw_loc_descr_ref
> - loc_by_reference (dw_loc_descr_ref loc, tree decl)
> - {
> -   HOST_WIDE_INT size;
> -   enum dwarf_location_atom op;
> - 
> -   if (loc == NULL)
> -     return NULL;
> - 
> -   if ((TREE_CODE (decl) != PARM_DECL
> -        && TREE_CODE (decl) != RESULT_DECL
> -        && TREE_CODE (decl) != VAR_DECL)
> -       || !DECL_BY_REFERENCE (decl))
> -     return loc;
> - 
> -   /* If loc is DW_OP_reg{0...31,x}, don't add DW_OP_deref, instead
> -      change it into corresponding DW_OP_breg{0...31,x} 0.  Then the
> -      location expression is considered to be address of a memory location,
> -      rather than the register itself.  */
> -   if (((loc->dw_loc_opc >= DW_OP_reg0 && loc->dw_loc_opc <= DW_OP_reg31)
> -        || loc->dw_loc_opc == DW_OP_regx)
> -       && (loc->dw_loc_next == NULL
> - 	  || (loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_uninit
> - 	      && loc->dw_loc_next->dw_loc_next == NULL)))
> -     {
> -       if (loc->dw_loc_opc == DW_OP_regx)
> - 	{
> - 	  loc->dw_loc_opc = DW_OP_bregx;
> - 	  loc->dw_loc_oprnd2.v.val_int = 0;
> - 	}
> -       else
> - 	{
> - 	  loc->dw_loc_opc
> - 	    = (enum dwarf_location_atom)
> - 	      (loc->dw_loc_opc + (DW_OP_breg0 - DW_OP_reg0));
> - 	  loc->dw_loc_oprnd1.v.val_int = 0;
> - 	}
> -       return loc;
> -     }
> - 
> -   size = int_size_in_bytes (TREE_TYPE (decl));
> -   if (size > DWARF2_ADDR_SIZE || size == -1)
> -     return 0;
> -   else if (size == DWARF2_ADDR_SIZE)
> -     op = DW_OP_deref;
> -   else
> -     op = DW_OP_deref_size;
> -   add_loc_descr (&loc, new_loc_descr (op, size, 0));
> -   return loc;
> - }
> - 
>   /* Generate *either* a DW_AT_location attribute or else a DW_AT_const_value
>      data attribute for a variable or a parameter.  We generate the
>      DW_AT_const_value attribute only in those cases where the given variable
> --- 13725,13730 ----
> *************** add_location_or_const_value_attribute (d
> *** 13418,13423 ****
> --- 13742,13748 ----
>   {
>     rtx rtl;
>     dw_loc_descr_ref descr;
> +   dw_loc_list_ref descr_list;
>     var_loc_list *loc_list;
>     struct var_loc_node *node;
>     if (TREE_CODE (decl) == ERROR_MARK)
> *************** add_location_or_const_value_attribute (d
> *** 13539,13556 ****
>         if (descr)
>   	{
>   	  descr = loc_by_reference (descr, decl);
> ! 	  add_AT_location_description (die, attr, descr);
>   	  return;
>   	}
>       }
>   
>     /* We couldn't get any rtl, so try directly generating the location
>        description from the tree.  */
> !   descr = loc_descriptor_from_tree (decl);
> !   if (descr)
>       {
>         descr = loc_by_reference (descr, decl);
> !       add_AT_location_description (die, attr, descr);
>         return;
>       }
>     /* None of that worked, so it must not really have a location;
> --- 13864,13881 ----
>         if (descr)
>   	{
>   	  descr = loc_by_reference (descr, decl);
> ! 	  add_AT_location_description (die, attr, single_element_loc_list (descr));
>   	  return;
>   	}
>       }
>   
>     /* We couldn't get any rtl, so try directly generating the location
>        description from the tree.  */
> !   descr_list = loc_list_from_tree (decl, hidden_reference_p (decl) ? 0 : 2);
> !   if (descr_list)
>       {
>         descr = loc_by_reference (descr, decl);
> !       add_AT_location_description (die, attr, descr_list);
>         return;
>       }
>     /* None of that worked, so it must not really have a location;
> *************** add_bound_info (dw_die_ref subrange_die,
> *** 13967,13973 ****
>       case RESULT_DECL:
>         {
>   	dw_die_ref decl_die = lookup_decl_die (bound);
> ! 	dw_loc_descr_ref loc;
>   
>   	/* ??? Can this happen, or should the variable have been bound
>   	   first?  Probably it can, since I imagine that we try to create
> --- 14292,14298 ----
>       case RESULT_DECL:
>         {
>   	dw_die_ref decl_die = lookup_decl_die (bound);
> ! 	dw_loc_list_ref loc;
>   
>   	/* ??? Can this happen, or should the variable have been bound
>   	   first?  Probably it can, since I imagine that we try to create
> *************** add_bound_info (dw_die_ref subrange_die,
> *** 13978,13984 ****
>   	  add_AT_die_ref (subrange_die, bound_attr, decl_die);
>   	else
>   	  {
> ! 	    loc = loc_descriptor_from_tree_1 (bound, 0);
>   	    add_AT_location_description (subrange_die, bound_attr, loc);
>   	  }
>   	break;
> --- 14303,14309 ----
>   	  add_AT_die_ref (subrange_die, bound_attr, decl_die);
>   	else
>   	  {
> ! 	    loc = loc_list_from_tree (bound, 0);
>   	    add_AT_location_description (subrange_die, bound_attr, loc);
>   	  }
>   	break;
> *************** add_bound_info (dw_die_ref subrange_die,
> *** 13990,13999 ****
>   	   evaluate the value of the array bound.  */
>   
>   	dw_die_ref ctx, decl_die;
> ! 	dw_loc_descr_ref loc;
>   
> ! 	loc = loc_descriptor_from_tree (bound);
> ! 	if (loc == NULL)
>   	  break;
>   
>   	if (current_function_decl == 0)
> --- 14315,14324 ----
>   	   evaluate the value of the array bound.  */
>   
>   	dw_die_ref ctx, decl_die;
> ! 	dw_loc_list_ref list;
>   
> ! 	list = loc_list_from_tree (bound, 2);
> ! 	if (list == NULL)
>   	  break;
>   
>   	if (current_function_decl == 0)
> *************** add_bound_info (dw_die_ref subrange_die,
> *** 14004,14010 ****
>   	decl_die = new_die (DW_TAG_variable, ctx, bound);
>   	add_AT_flag (decl_die, DW_AT_artificial, 1);
>   	add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
> ! 	add_AT_loc (decl_die, DW_AT_location, loc);
>   
>   	add_AT_die_ref (subrange_die, bound_attr, decl_die);
>   	break;
> --- 14329,14338 ----
>   	decl_die = new_die (DW_TAG_variable, ctx, bound);
>   	add_AT_flag (decl_die, DW_AT_artificial, 1);
>   	add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
> ! 	if (list->dw_loc_next)
> ! 	  add_AT_loc_list (decl_die, DW_AT_location, list);
> ! 	else
> ! 	  add_AT_loc (decl_die, DW_AT_location, list->expr);
>   
>   	add_AT_die_ref (subrange_die, bound_attr, decl_die);
>   	break;
> *************** gen_array_type_die (tree type, dw_die_re
> *** 14610,14621 ****
>   	       && DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
>   	{
>   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> ! 	  dw_loc_descr_ref loc = loc_descriptor_from_tree (szdecl);
>   
>   	  size = int_size_in_bytes (TREE_TYPE (szdecl));
>   	  if (loc && size > 0)
>   	    {
> ! 	      add_AT_loc (array_die, DW_AT_string_length, loc);
>   	      if (size != DWARF2_ADDR_SIZE)
>   		add_AT_unsigned (array_die, DW_AT_byte_size, size);
>   	    }
> --- 14938,14949 ----
>   	       && DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
>   	{
>   	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> ! 	  dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2);
>   
>   	  size = int_size_in_bytes (TREE_TYPE (szdecl));
>   	  if (loc && size > 0)
>   	    {
> ! 	      add_AT_location_description (array_die, DW_AT_string_length, loc);
>   	      if (size != DWARF2_ADDR_SIZE)
>   		add_AT_unsigned (array_die, DW_AT_byte_size, size);
>   	    }
> *************** descr_info_loc (tree val, tree base_decl
> *** 14709,14715 ****
>       CASE_CONVERT:
>         return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
>       case VAR_DECL:
> !       return loc_descriptor_from_tree_1 (val, 0);
>       case INTEGER_CST:
>         if (host_integerp (val, 0))
>   	return int_loc_descriptor (tree_low_cst (val, 0));
> --- 15037,15043 ----
>       CASE_CONVERT:
>         return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
>       case VAR_DECL:
> !       return loc_descriptor_from_tree (val, 0);
>       case INTEGER_CST:
>         if (host_integerp (val, 0))
>   	return int_loc_descriptor (tree_low_cst (val, 0));
> *************** gen_subprogram_die (tree decl, dw_die_re
> *** 15467,15473 ****
>   
>         if (cfun->static_chain_decl)
>   	add_AT_location_description (subr_die, DW_AT_static_link,
> ! 		 loc_descriptor_from_tree (cfun->static_chain_decl));
>       }
>   
>     /* Generate child dies for template paramaters.  */
> --- 15795,15801 ----
>   
>         if (cfun->static_chain_decl)
>   	add_AT_location_description (subr_die, DW_AT_static_link,
> ! 		 loc_list_from_tree (cfun->static_chain_decl, 2));
>       }
>   
>     /* Generate child dies for template paramaters.  */
> *************** gen_variable_die (tree decl, tree origin
> *** 15637,15643 ****
>       {
>         tree field;
>         dw_die_ref com_die;
> !       dw_loc_descr_ref loc;
>         die_node com_die_arg;
>   
>         var_die = lookup_decl_die (decl_or_origin);
> --- 15965,15971 ----
>       {
>         tree field;
>         dw_die_ref com_die;
> !       dw_loc_list_ref loc;
>         die_node com_die_arg;
>   
>         var_die = lookup_decl_die (decl_or_origin);
> *************** gen_variable_die (tree decl, tree origin
> *** 15645,15666 ****
>   	{
>   	  if (get_AT (var_die, DW_AT_location) == NULL)
>   	    {
> ! 	      loc = loc_descriptor_from_tree (com_decl);
>   	      if (loc)
>   		{
>   		  if (off)
>   		    {
>   		      /* Optimize the common case.  */
> ! 		      if (loc->dw_loc_opc == DW_OP_addr
> ! 			  && loc->dw_loc_next == NULL
> ! 			  && GET_CODE (loc->dw_loc_oprnd1.v.val_addr)
>   			     == SYMBOL_REF)
> ! 			loc->dw_loc_oprnd1.v.val_addr
> ! 			  = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
>   			else
> ! 			  loc_descr_plus_const (&loc, off);
>   		    }
> ! 		  add_AT_loc (var_die, DW_AT_location, loc);
>   		  remove_AT (var_die, DW_AT_declaration);
>   		}
>   	    }
> --- 15973,15995 ----
>   	{
>   	  if (get_AT (var_die, DW_AT_location) == NULL)
>   	    {
> ! 	      loc = loc_list_from_tree (com_decl, off ? 1 : 2);
>   	      if (loc)
>   		{
>   		  if (off)
>   		    {
>   		      /* Optimize the common case.  */
> ! 		      if (single_element_loc_list_p (loc)
> ! 			  && loc->expr->dw_loc_opc == DW_OP_addr
> ! 			  && loc->expr->dw_loc_next == NULL
> ! 			  && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr)
>   			     == SYMBOL_REF)
> ! 			loc->expr->dw_loc_oprnd1.v.val_addr
> ! 			  = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
>   			else
> ! 			  loc_list_plus_const (loc, off);
>   		    }
> ! 		  add_AT_location_description (var_die, DW_AT_location, loc);
>   		  remove_AT (var_die, DW_AT_declaration);
>   		}
>   	    }
> *************** gen_variable_die (tree decl, tree origin
> *** 15676,15682 ****
>         com_die_arg.decl_id = DECL_UID (com_decl);
>         com_die_arg.die_parent = context_die;
>         com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
> !       loc = loc_descriptor_from_tree (com_decl);
>         if (com_die == NULL)
>   	{
>   	  const char *cnam
> --- 16005,16011 ----
>         com_die_arg.decl_id = DECL_UID (com_decl);
>         com_die_arg.die_parent = context_die;
>         com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
> !       loc = loc_list_from_tree (com_decl, 2);
>         if (com_die == NULL)
>   	{
>   	  const char *cnam
> *************** gen_variable_die (tree decl, tree origin
> *** 15687,15696 ****
>   	  add_name_and_src_coords_attributes (com_die, com_decl);
>   	  if (loc)
>   	    {
> ! 	      add_AT_loc (com_die, DW_AT_location, loc);
>   	      /* Avoid sharing the same loc descriptor between
>   		 DW_TAG_common_block and DW_TAG_variable.  */
> ! 	      loc = loc_descriptor_from_tree (com_decl);
>   	    }
>             else if (DECL_EXTERNAL (decl))
>   	    add_AT_flag (com_die, DW_AT_declaration, 1);
> --- 16016,16025 ----
>   	  add_name_and_src_coords_attributes (com_die, com_decl);
>   	  if (loc)
>   	    {
> ! 	      add_AT_location_description (com_die, DW_AT_location, loc);
>   	      /* Avoid sharing the same loc descriptor between
>   		 DW_TAG_common_block and DW_TAG_variable.  */
> ! 	      loc = loc_list_from_tree (com_decl, 2);
>   	    }
>             else if (DECL_EXTERNAL (decl))
>   	    add_AT_flag (com_die, DW_AT_declaration, 1);
> *************** gen_variable_die (tree decl, tree origin
> *** 15701,15708 ****
>   	}
>         else if (get_AT (com_die, DW_AT_location) == NULL && loc)
>   	{
> ! 	  add_AT_loc (com_die, DW_AT_location, loc);
> ! 	  loc = loc_descriptor_from_tree (com_decl);
>   	  remove_AT (com_die, DW_AT_declaration);
>   	}
>         var_die = new_die (DW_TAG_variable, com_die, decl);
> --- 16030,16037 ----
>   	}
>         else if (get_AT (com_die, DW_AT_location) == NULL && loc)
>   	{
> ! 	  add_AT_location_description (com_die, DW_AT_location, loc);
> ! 	  loc = loc_list_from_tree (com_decl, 2);
>   	  remove_AT (com_die, DW_AT_declaration);
>   	}
>         var_die = new_die (DW_TAG_variable, com_die, decl);
> *************** gen_variable_die (tree decl, tree origin
> *** 15715,15729 ****
>   	  if (off)
>   	    {
>   	      /* Optimize the common case.  */
> ! 	      if (loc->dw_loc_opc == DW_OP_addr
> ! 		  && loc->dw_loc_next == NULL
> ! 		  && GET_CODE (loc->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
> ! 		loc->dw_loc_oprnd1.v.val_addr
> ! 		  = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
>   	      else
> ! 		loc_descr_plus_const (&loc, off);
>   	    }
> ! 	  add_AT_loc (var_die, DW_AT_location, loc);
>   	}
>         else if (DECL_EXTERNAL (decl))
>   	add_AT_flag (var_die, DW_AT_declaration, 1);
> --- 16044,16059 ----
>   	  if (off)
>   	    {
>   	      /* Optimize the common case.  */
> ! 	      if (single_element_loc_list_p (loc)
> ! 		  && loc->expr->dw_loc_opc == DW_OP_addr
> ! 		  && loc->expr->dw_loc_next == NULL
> ! 		  && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
> ! 		loc->expr->dw_loc_oprnd1.v.val_addr
> ! 		  = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
>   	      else
> ! 		loc_list_plus_const (loc, off);
>   	    }
> ! 	  add_AT_location_description (var_die, DW_AT_location, loc);
>   	}
>         else if (DECL_EXTERNAL (decl))
>   	add_AT_flag (var_die, DW_AT_declaration, 1);
> *************** gen_variable_die (tree decl, tree origin
> *** 15786,15795 ****
>         tree type = TREE_TYPE (decl);
>   
>         add_name_and_src_coords_attributes (var_die, decl);
> !       if ((TREE_CODE (decl) == PARM_DECL
> ! 	   || TREE_CODE (decl) == RESULT_DECL
> ! 	   || TREE_CODE (decl) == VAR_DECL)
> ! 	  && DECL_BY_REFERENCE (decl))
>   	add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
>         else
>   	add_type_attribute (var_die, type, TREE_READONLY (decl),
> --- 16116,16122 ----
>         tree type = TREE_TYPE (decl);
>   
>         add_name_and_src_coords_attributes (var_die, decl);
> !       if (hidden_reference_p (decl))
>   	add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
>         else
>   	add_type_attribute (var_die, type, TREE_READONLY (decl),
> Index: Makefile.in
> ===================================================================
> *** Makefile.in	(revision 151743)
> --- Makefile.in	(working copy)
> *************** dwarf2out.o : dwarf2out.c $(CONFIG_H) $(
> *** 2731,2737 ****
>      output.h $(DIAGNOSTIC_H) $(REAL_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
>      libfuncs.h $(TOPLEV_H) dwarf2out.h reload.h $(GGC_H) $(EXCEPT_H) dwarf2asm.h \
>      $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) \
> !    $(MD5_H) $(INPUT_H) $(FUNCTION_H) $(VARRAY_H)
>   dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
>      $(FLAGS_H) $(RTL_H) $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) \
>      gt-dwarf2asm.h $(DWARF2_H) $(SPLAY_TREE_H) $(TARGET_H)
> --- 2731,2737 ----
>      output.h $(DIAGNOSTIC_H) $(REAL_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
>      libfuncs.h $(TOPLEV_H) dwarf2out.h reload.h $(GGC_H) $(EXCEPT_H) dwarf2asm.h \
>      $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) \
> !    $(MD5_H) $(INPUT_H) $(FUNCTION_H) $(VARRAY_H) $(GIMPLE_H) $(TREE_PASS_H)
>   dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
>      $(FLAGS_H) $(RTL_H) $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) \
>      gt-dwarf2asm.h $(DWARF2_H) $(SPLAY_TREE_H) $(TARGET_H)
> 
> 

-- 
Richard Guenther <rguenther@suse.de>
Novell / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 - GF: Markus Rex


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]