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


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?

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)


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