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 that applies post VTA merge.
Alexandre, most of merging was trivial, only non-trivial change was
needed to dw_loc_list that is essentially code broken out of
add_location_or_const_value_attribute.  I hope I backported everything
correctly, but it would be nice if you could check.

Honza

	* dwarf2out.c (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.

Index: dwarf2out.c
===================================================================
*** dwarf2out.c	(revision 151325)
--- dwarf2out.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 89,94 ****
--- 89,95 ----
  #include "hashtab.h"
  #include "cgraph.h"
  #include "input.h"
+ #include "gimple.h"
  
  #ifdef DWARF2_DEBUGGING_INFO
  static void dwarf2out_source_line (unsigned int, const char *, int, bool);
*************** loc_descr_plus_const (dw_loc_descr_ref *
*** 4633,4638 ****
--- 4634,4649 ----
      }
  }
  
+ /* 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
*** 5916,5923 ****
  					       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);
--- 5927,5934 ----
  					       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
*** 5925,5931 ****
  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 *);
--- 5936,5942 ----
  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)
*** 10984,10990 ****
        || !DECL_THREAD_LOCAL_P (base))
      return NULL;
  
!   loc_result = loc_descriptor_from_tree_1 (MEM_EXPR (mem), 2);
    if (loc_result == NULL)
      return NULL;
  
--- 10995,11001 ----
        || !DECL_THREAD_LOCAL_P (base))
      return NULL;
  
!   loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 2);
    if (loc_result == NULL)
      return NULL;
  
*************** mem_loc_descriptor (rtx rtl, enum machin
*** 11171,11176 ****
--- 11182,11203 ----
        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
*** 11305,11310 ****
--- 11332,11352 ----
  						   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.  */
+       if (dump_file)
+ 	{
+ 	  fprintf (stderr, "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
*** 11948,11963 ****
    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;
  
--- 11990,12270 ----
    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;
!     }
!   if (dump_file)
!     fprintf (dump_file, "Don't know how to merge two location lists with multiple locations.\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_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
*** 11968,11973 ****
--- 12275,12282 ----
    switch (TREE_CODE (loc))
      {
      case ERROR_MARK:
+       if (dump_file)
+ 	fprintf (dump_file, "ERROR_MARK in the expression\n");
        return 0;
  
      case PLACEHOLDER_EXPR:
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 11975,11989 ****
--- 12284,12305 ----
  	 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.  */
+       if (dump_file)
+ 	fprintf (dump_file, "PLACEHOLDER_EXPR in the expression\n");
        return 0;
  
      case CALL_EXPR:
+       if (dump_file)
+ 	fprintf (dump_file, "CALL_EXPR in the expression\n");
+       /* There are no opcodes for these operations.  */
        return 0;
  
      case PREINCREMENT_EXPR:
      case PREDECREMENT_EXPR:
      case POSTINCREMENT_EXPR:
      case POSTDECREMENT_EXPR:
+       if (dump_file)
+ 	fprintf (dump_file, "PRE/POST INDCREMENT/DECREMENT in the expression\n");
        /* There are no opcodes for these operations.  */
        return 0;
  
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 11993,11999 ****
  	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))
--- 12309,12315 ----
  	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
*** 12053,12069 ****
  
      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);
--- 12369,12397 ----
  
      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)
! 	  {
! 	    if (dump_file)
! 	      {
! 	        fprintf (dump_file, "Expansion for decl failed. No RTL ");
! 	  	print_generic_decl (dump_file, loc, 0);
! 		fprintf (dump_file, "\n");
! 	      }
! 	    return 0;
! 	  }
  	else if (CONST_INT_P (rtl))
  	  {
  	    HOST_WIDE_INT val = INTVAL (rtl);
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12072,12078 ****
  	    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);
--- 12400,12410 ----
  	    ret = int_loc_descriptor (val);
  	  }
  	else if (GET_CODE (rtl) == CONST_STRING)
! 	  {
! 	    if (dump_file)
! 	      fprintf (stderr, "Failed to expand CONST_STRING\n");
! 	    return 0;
! 	  }
  	else if (CONSTANT_P (rtl))
  	  {
  	    ret = new_loc_descr (DW_OP_addr, 0, 0);
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12085,12117 ****
  
  	    /* 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:
--- 12417,12459 ----
  
  	    /* 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 && dump_file)
! 	      {
! 	        fprintf (dump_file, "Failed to produce loc descriptor for rtl\n");
! 		print_rtl (dump_file, 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
*** 12127,12152 ****
  	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;
--- 12469,12503 ----
  	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)
+ 	  {
+ 	    if (dump_file)
+ 	      fprintf (stderr, "Can not encode bitfield accesses.\n");
+ 	    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
*** 12156,12162 ****
        if (host_integerp (loc, 0))
  	ret = int_loc_descriptor (tree_low_cst (loc, 0));
        else
! 	return 0;
        break;
  
      case CONSTRUCTOR:
--- 12507,12517 ----
        if (host_integerp (loc, 0))
  	ret = int_loc_descriptor (tree_low_cst (loc, 0));
        else
! 	{
! 	  if (dump_file)
! 	    fprintf (stderr, "Integer operand is not host integer.\n");
! 	  return 0;
! 	}
        break;
  
      case CONSTRUCTOR:
*************** loc_descriptor_from_tree_1 (tree loc, in
*** 12226,12236 ****
        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;
  	}
  
--- 12581,12591 ----
        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
*** 12274,12286 ****
        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:
--- 12629,12643 ----
        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
*** 12297,12307 ****
        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:
--- 12654,12664 ----
        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
*** 12321,12349 ****
      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;
        }
--- 12678,12706 ----
      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
*** 12357,12363 ****
  	 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
--- 12714,12724 ----
  	 up, for instance, with the C STMT_EXPR.  */
        if ((unsigned int) TREE_CODE (loc)
  	  >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
! 	{
!           if (dump_file)
! 	    fprintf (dump_file, "language specific tree in the expression\n");
! 	  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
*** 12370,12401 ****
  #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'
--- 12731,12794 ----
  #endif
      }
  
+   if (!ret && !list_ret)
+     return 0;
+ 
    /* Show if we can't fill the request for an address.  */
    if (want_address && !have_address)
!     {
!       if (dump_file)
! 	fprintf (stderr, "Want address but have only value.\n");
!       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)
! 	{
! 	  if (dump_file)
! 	    {
! 	      fprintf (dump_file, "DWARF address size mismatch. %i %i\n",
! 		       (int)size, DWARF2_ADDR_SIZE);
! 	      print_generic_expr (dump_file, loc, 0);
! 	    }
! 	  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)
!     {
!       if (dump_file)
!         fprintf (dump_file, "Multiple locations needed where only one is assumed\n");
!       return NULL;
!     }
!   return ret->expr;
  }
  
  /* Given a value, round it up to the lowest multiple of `boundary'
*************** field_byte_offset (const_tree decl)
*** 12602,12611 ****
  
  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
--- 12995,13008 ----
  
  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)
*** 13243,13278 ****
    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.  */
--- 13640,13645 ----
*************** fortran_common (tree decl, HOST_WIDE_INT
*** 13323,13382 ****
    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
--- 13690,13695 ----
*************** add_location_or_const_value_attribute (d
*** 13394,13399 ****
--- 13707,13713 ----
  {
    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
*** 13515,13532 ****
        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;
--- 13829,13846 ----
        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,
*** 13943,13949 ****
      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
--- 14257,14263 ----
      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,
*** 13954,13960 ****
  	  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;
--- 14268,14274 ----
  	  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,
*** 13966,13975 ****
  	   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)
--- 14280,14289 ----
  	   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,
*** 13980,13986 ****
  	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;
--- 14294,14303 ----
  	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
*** 14586,14597 ****
  	       && 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);
  	    }
--- 14903,14914 ----
  	       && 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
*** 14685,14691 ****
      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));
--- 15002,15008 ----
      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
*** 15443,15449 ****
  
        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.  */
--- 15760,15766 ----
  
        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
*** 15613,15619 ****
      {
        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);
--- 15930,15936 ----
      {
        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
*** 15621,15642 ****
  	{
  	  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);
  		}
  	    }
--- 15938,15960 ----
  	{
  	  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
*** 15652,15658 ****
        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
--- 15970,15976 ----
        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
*** 15663,15672 ****
  	  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);
--- 15981,15990 ----
  	  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
*** 15677,15684 ****
  	}
        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);
--- 15995,16002 ----
  	}
        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
*** 15691,15705 ****
  	  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);
--- 16009,16024 ----
  	  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
*** 15762,15771 ****
        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),
--- 16081,16087 ----
        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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]