public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Variable tracking (location lists support) - part 2
@ 2004-02-02 20:37 Josef Zlomek
  2004-02-06  3:34 ` Roger Sayle
                   ` (2 more replies)
  0 siblings, 3 replies; 44+ messages in thread
From: Josef Zlomek @ 2004-02-02 20:37 UTC (permalink / raw)
  To: gcc-patches

Hello,

this patch adds location list support to dwarf2out.c.
This generates the location list debug info from the NOTE_INSN_VAR_LOCATION
notes produces by the first patch of variable tracking.

Bootstrapped/regtested x86-64 (standalone and together with the first part).

Josef

2004-02-02  Daniel Berlin <dberlin@dberlin.org>
            Josef Zlomek  <zlomekj@suse.cz>

        * dwarf2out.c (struct gcc_debug_hooks): Call dwarf2out_begin_function
        at the beginning of function, call dwarf2out_var_location for
        NOTE_INSN_VAR_LOCATION note.
	(struct var_loc_node, struct var_loc_list_def, loclabel_num,
	decl_loc_table, decl_loc_table_allocated, decl_loc_table_in_use,
	DECL_LOC_TABLE_INCREMENT): New.
	(lookup_decl_loc): New function.
	(add_var_loc_to_decl): New function.
	(based_loc_descr): Added parameter can_use_fbreg, DW_OP_fbreg is used
	only if can_use_fbreg.
	(mem_loc_descriptor): Added parameter can_use_fbreg, pass it to other
	functions.
	(loc_descriptor): Likewise. Process VAR_LOCATION.
	(concat_loc_descriptor): Call loc_descriptor with can_use_fbreg == true.
	(loc_descriptor_from_tree): Call mem_loc_descriptor with
	can_use_fbreg == true.
	(add_location_or_const_value_attribute): Added parameter enum
	dwarf_attribute attr, generate attribute ATTR.  Create the location list.
	(add_bound_info): Call loc_descriptor with can_use_fbreg == true.
	(gen_formal_parameter_die): Call add_location_or_const_value_attribute
	with attr == DW_AT_location.
	(gen_subprogram_die): Generate the location list for DW_AT_frame_base
	if frame_base_decl is defined and has a location list.
	(gen_variable_die): Call add_location_or_const_value_attribute with
	attr == DW_AT_location.
        (dwarf2out_var_location): New function.
        (dwarf2out_begin_function): New function.
	(dwarf2out_init): Create decl_loc_table and initialize
	decl_loc_table_allocated and decl_loc_table_in_use.

*** vt-main-part1/gcc/dwarf2out.c	2004-02-02 07:56:34.000000000 +0100
--- vt-main-part2/gcc/dwarf2out.c	2004-02-02 07:56:23.000000000 +0100
*************** static bool dwarf2out_ignore_block (tree
*** 3251,3256 ****
--- 3251,3258 ----
  static void dwarf2out_global_decl (tree);
  static void dwarf2out_imported_module_or_decl (tree, tree);
  static void dwarf2out_abstract_function (tree);
+ static void dwarf2out_var_location (rtx);
+ static void dwarf2out_begin_function (tree);
  
  /* The debug hooks structure.  */
  
*************** const struct gcc_debug_hooks dwarf2_debu
*** 3269,3275 ****
    dwarf2out_begin_prologue,
    debug_nothing_int_charstar,	/* end_prologue */
    dwarf2out_end_epilogue,
!   debug_nothing_tree,		/* begin_function */
    debug_nothing_int,		/* end_function */
    dwarf2out_decl,		/* function_decl */
    dwarf2out_global_decl,
--- 3271,3277 ----
    dwarf2out_begin_prologue,
    debug_nothing_int_charstar,	/* end_prologue */
    dwarf2out_end_epilogue,
!   dwarf2out_begin_function,
    debug_nothing_int,		/* end_function */
    dwarf2out_decl,		/* function_decl */
    dwarf2out_global_decl,
*************** const struct gcc_debug_hooks dwarf2_debu
*** 3281,3287 ****
    dwarf2out_abstract_function,	/* outlining_inline_function */
    debug_nothing_rtx,		/* label */
    debug_nothing_int,		/* handle_pch */
!   debug_nothing_rtx		/* var_location */
  };
  #endif
  \f
--- 3283,3289 ----
    dwarf2out_abstract_function,	/* outlining_inline_function */
    debug_nothing_rtx,		/* label */
    debug_nothing_int,		/* handle_pch */
!   dwarf2out_var_location
  };
  #endif
  \f
*************** static GTY(()) size_t file_table_last_lo
*** 3477,3482 ****
--- 3479,3512 ----
     The key is a DECL_UID() which is a unique number identifying each decl.  */
  static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
  
+ /* Node of the variable location list.  */
+ struct var_loc_node GTY ((chain_next ("%h.next")))
+ {
+   rtx GTY (()) var_loc_note;
+   const char * GTY (()) label;
+   struct var_loc_node * GTY (()) next;
+ };
+ 
+ /* Variable location list.  */
+ struct var_loc_list_def GTY (())
+ {
+   struct var_loc_node * GTY (()) first;
+ 
+   /* Do not mark the last element of the chained list because
+      it is marked through the chain.  */
+   struct var_loc_node * GTY ((skip ("%h"))) last;
+ 
+   /* DECL_UID of the variable decl.  */
+   unsigned int decl_id;
+ };
+ typedef struct var_loc_list_def var_loc_list;
+ 
+ /* Unique label counter.  */
+ static unsigned int loclabel_num = 0;
+ 
+ /* Table of decl location linked lists.  */
+ static GTY ((param_is (var_loc_list))) htab_t decl_loc_table;
+ 
  /* A pointer to the base of a list of references to DIE's that
     are uniquely identified by their tag, presence/absence of
     children DIE's, and list of attribute/value pairs.  */
*************** static void equate_type_number_to_die (t
*** 3651,3657 ****
--- 3681,3691 ----
  static hashval_t decl_die_table_hash (const void *);
  static int decl_die_table_eq (const void *, const void *);
  static dw_die_ref lookup_decl_die (tree);
+ static hashval_t decl_loc_table_hash (const void *);
+ static int decl_loc_table_eq (const void *, const void *);
+ static var_loc_list *lookup_decl_loc (tree);
  static void equate_decl_number_to_die (tree, dw_die_ref);
+ static void add_var_loc_to_decl (tree, struct var_loc_node *);
  static void print_spaces (FILE *);
  static void print_die (dw_die_ref, FILE *);
  static void print_dwarf_line_table (FILE *);
*************** static dw_loc_descr_ref reg_loc_descript
*** 3717,3727 ****
  static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int);
  static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx);
  static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
! static dw_loc_descr_ref based_loc_descr (unsigned, HOST_WIDE_INT);
  static int is_based_loc (rtx);
! static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode);
  static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx);
! static dw_loc_descr_ref loc_descriptor (rtx);
  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 (tree);
--- 3751,3761 ----
  static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int);
  static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx);
  static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
! static dw_loc_descr_ref based_loc_descr (unsigned, HOST_WIDE_INT, bool);
  static int is_based_loc (rtx);
! static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, bool);
  static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx);
! static dw_loc_descr_ref loc_descriptor (rtx, bool);
  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 (tree);
*************** static void add_AT_location_description	
*** 3734,3740 ****
  static void add_data_member_location_attribute (dw_die_ref, tree);
  static void add_const_value_attribute (dw_die_ref, rtx);
  static rtx rtl_for_decl_location (tree);
! static void add_location_or_const_value_attribute (dw_die_ref, tree);
  static void tree_add_const_value_attribute (dw_die_ref, tree);
  static void add_name_attribute (dw_die_ref, const char *);
  static void add_comp_dir_attribute (dw_die_ref);
--- 3768,3775 ----
  static void add_data_member_location_attribute (dw_die_ref, tree);
  static void add_const_value_attribute (dw_die_ref, rtx);
  static rtx rtl_for_decl_location (tree);
! static void add_location_or_const_value_attribute (dw_die_ref, tree,
! 						   enum dwarf_attribute);
  static void tree_add_const_value_attribute (dw_die_ref, tree);
  static void add_name_attribute (dw_die_ref, const char *);
  static void add_comp_dir_attribute (dw_die_ref);
*************** lookup_decl_die (tree decl)
*** 5229,5234 ****
--- 5264,5291 ----
    return htab_find_with_hash (decl_die_table, decl, DECL_UID (decl));
  }
  
+ /* Returns a hash value for X (which really is a var_loc_list).  */
+ 
+ static hashval_t
+ decl_loc_table_hash (const void *x)
+ {
+   return (hashval_t) ((const var_loc_list *) x)->decl_id;
+ }
+ 
+ static int
+ decl_loc_table_eq (const void *x, const void *y)
+ {
+   return (((const var_loc_list *) x)->decl_id == DECL_UID ((const tree) y));
+ }
+ 
+ /* Return the var_loc list associated with a given declaration.  */
+ 
+ static inline var_loc_list *
+ lookup_decl_loc (tree decl)
+ {
+   return htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl));
+ }
+ 
  /* Equate a DIE to a particular declaration.  */
  
  static void
*************** equate_decl_number_to_die (tree decl, dw
*** 5241,5246 ****
--- 5298,5342 ----
    *slot = decl_die;
    decl_die->decl_id = decl_id;
  }
+ 
+ /* Add a variable location node to the linked list for DECL.  */
+ 
+ static void
+ add_var_loc_to_decl (tree decl, struct var_loc_node *loc)
+ {
+   unsigned int decl_id = DECL_UID (decl);
+   var_loc_list *temp;
+   void **slot;
+ 
+   slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
+   if (*slot == NULL)
+     {
+       temp = ggc_alloc_cleared (sizeof (var_loc_list));
+       temp->decl_id = decl_id;
+       *slot = temp;
+     }
+   else
+     temp = *slot;
+ 
+   if (temp->last)
+     {
+       /* If the current location is the same as the end of the list,
+ 	 we have nothing to do.  */
+       if (!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->var_loc_note),
+ 			NOTE_VAR_LOCATION_LOC (loc->var_loc_note)))
+ 	{
+ 	  /* Add LOC to the end of list and update LAST.  */
+ 	  temp->last->next = loc;
+ 	  temp->last = loc;
+ 	}
+     }
+   /* Do not add empty location to the beginning of the list.  */
+   else if (NOTE_VAR_LOCATION_LOC (loc->var_loc_note) != NULL_RTX)
+     {
+       temp->first = loc;
+       temp->last = loc;
+     }
+ }
  \f
  /* Keep track of the number of spaces used to indent the
     output of the debugging routines that print the structure of
*************** int_loc_descriptor (HOST_WIDE_INT i)
*** 8193,8199 ****
  /* Return a location descriptor that designates a base+offset location.  */
  
  static dw_loc_descr_ref
! based_loc_descr (unsigned int reg, HOST_WIDE_INT offset)
  {
    dw_loc_descr_ref loc_result;
    /* For the "frame base", we use the frame pointer or stack pointer
--- 8300,8306 ----
  /* Return a location descriptor that designates a base+offset location.  */
  
  static dw_loc_descr_ref
! based_loc_descr (unsigned int reg, HOST_WIDE_INT offset, bool can_use_fbreg)
  {
    dw_loc_descr_ref loc_result;
    /* For the "frame base", we use the frame pointer or stack pointer
*************** based_loc_descr (unsigned int reg, HOST_
*** 8203,8209 ****
  					 ? HARD_FRAME_POINTER_REGNUM
  					 : STACK_POINTER_REGNUM);
  
!   if (reg == fp_reg)
      loc_result = new_loc_descr (DW_OP_fbreg, offset, 0);
    else if (reg <= 31)
      loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0);
--- 8310,8316 ----
  					 ? HARD_FRAME_POINTER_REGNUM
  					 : STACK_POINTER_REGNUM);
  
!   if (reg == fp_reg && can_use_fbreg)
      loc_result = new_loc_descr (DW_OP_fbreg, offset, 0);
    else if (reg <= 31)
      loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0);
*************** is_based_loc (rtx rtl)
*** 8237,8246 ****
     MODE is the mode of the memory reference, needed to handle some
     autoincrement addressing modes.
  
     Return 0 if we can't represent the location.  */
  
  static dw_loc_descr_ref
! mem_loc_descriptor (rtx rtl, enum machine_mode mode)
  {
    dw_loc_descr_ref mem_loc_result = NULL;
  
--- 8344,8358 ----
     MODE is the mode of the memory reference, needed to handle some
     autoincrement addressing modes.
  
+    CAN_USE_FBREG is a flag whether we can use DW_AT_frame_base in the location
+    list for RTL. We can't use it when we are emitting location list for
+    virtual variable frame_base_decl (i.e. a location list for DW_AT_frame_base)
+    which describes how frame base changes when !frame_pointer_needed.
+ 
     Return 0 if we can't represent the location.  */
  
  static dw_loc_descr_ref
! mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
  {
    dw_loc_descr_ref mem_loc_result = NULL;
  
*************** mem_loc_descriptor (rtx rtl, enum machin
*** 8286,8296 ****
  	 memory) so DWARF consumers need to be aware of the subtle
  	 distinction between OP_REG and OP_BASEREG.  */
        if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
! 	mem_loc_result = based_loc_descr (reg_number (rtl), 0);
        break;
  
      case MEM:
!       mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
        if (mem_loc_result != 0)
  	add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
        break;
--- 8398,8409 ----
  	 memory) so DWARF consumers need to be aware of the subtle
  	 distinction between OP_REG and OP_BASEREG.  */
        if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
! 	mem_loc_result = based_loc_descr (reg_number (rtl), 0, can_use_fbreg);
        break;
  
      case MEM:
!       mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
! 					   can_use_fbreg);
        if (mem_loc_result != 0)
  	add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
        break;
*************** mem_loc_descriptor (rtx rtl, enum machin
*** 8357,8366 ****
      plus:
        if (is_based_loc (rtl))
  	mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)),
! 					  INTVAL (XEXP (rtl, 1)));
        else
  	{
! 	  mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
  	  if (mem_loc_result == 0)
  	    break;
  
--- 8470,8481 ----
      plus:
        if (is_based_loc (rtl))
  	mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)),
! 					  INTVAL (XEXP (rtl, 1)),
! 					  can_use_fbreg);
        else
  	{
! 	  mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode,
! 					       can_use_fbreg);
  	  if (mem_loc_result == 0)
  	    break;
  
*************** mem_loc_descriptor (rtx rtl, enum machin
*** 8372,8378 ****
  	  else
  	    {
  	      add_loc_descr (&mem_loc_result,
! 			     mem_loc_descriptor (XEXP (rtl, 1), mode));
  	      add_loc_descr (&mem_loc_result,
  			     new_loc_descr (DW_OP_plus, 0, 0));
  	    }
--- 8487,8494 ----
  	  else
  	    {
  	      add_loc_descr (&mem_loc_result,
! 			     mem_loc_descriptor (XEXP (rtl, 1), mode,
! 						 can_use_fbreg));
  	      add_loc_descr (&mem_loc_result,
  			     new_loc_descr (DW_OP_plus, 0, 0));
  	    }
*************** mem_loc_descriptor (rtx rtl, enum machin
*** 8383,8390 ****
        {
  	/* If a pseudo-reg is optimized away, it is possible for it to
  	   be replaced with a MEM containing a multiply.  */
! 	dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode);
! 	dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode);
  
  	if (op0 == 0 || op1 == 0)
  	  break;
--- 8499,8508 ----
        {
  	/* If a pseudo-reg is optimized away, it is possible for it to
  	   be replaced with a MEM containing a multiply.  */
! 	dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
! 						   can_use_fbreg);
! 	dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
! 						   can_use_fbreg);
  
  	if (op0 == 0 || op1 == 0)
  	  break;
*************** mem_loc_descriptor (rtx rtl, enum machin
*** 8403,8413 ****
        /* If this is a MEM, return its address.  Otherwise, we can't
  	 represent this.  */
        if (GET_CODE (XEXP (rtl, 0)) == MEM)
! 	return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode);
        else
  	return 0;
  
      default:
        abort ();
      }
  
--- 8521,8534 ----
        /* If this is a MEM, return its address.  Otherwise, we can't
  	 represent this.  */
        if (GET_CODE (XEXP (rtl, 0)) == MEM)
! 	return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode,
! 				   can_use_fbreg);
        else
  	return 0;
  
      default:
+       fprintf (stderr, "\nInvalid mem_loc_descriptor RTL:\n");
+       print_rtl (stderr, rtl);
        abort ();
      }
  
*************** static dw_loc_descr_ref
*** 8421,8428 ****
  concat_loc_descriptor (rtx x0, rtx x1)
  {
    dw_loc_descr_ref cc_loc_result = NULL;
!   dw_loc_descr_ref x0_ref = loc_descriptor (x0);
!   dw_loc_descr_ref x1_ref = loc_descriptor (x1);
  
    if (x0_ref == 0 || x1_ref == 0)
      return 0;
--- 8542,8549 ----
  concat_loc_descriptor (rtx x0, rtx x1)
  {
    dw_loc_descr_ref cc_loc_result = NULL;
!   dw_loc_descr_ref x0_ref = loc_descriptor (x0, true);
!   dw_loc_descr_ref x1_ref = loc_descriptor (x1, true);
  
    if (x0_ref == 0 || x1_ref == 0)
      return 0;
*************** concat_loc_descriptor (rtx x0, rtx x1)
*** 8449,8455 ****
     If we don't know how to describe it, return 0.  */
  
  static dw_loc_descr_ref
! loc_descriptor (rtx rtl)
  {
    dw_loc_descr_ref loc_result = NULL;
  
--- 8570,8576 ----
     If we don't know how to describe it, return 0.  */
  
  static dw_loc_descr_ref
! loc_descriptor (rtx rtl, bool can_use_fbreg)
  {
    dw_loc_descr_ref loc_result = NULL;
  
*************** loc_descriptor (rtx rtl)
*** 8470,8482 ****
        break;
  
      case MEM:
!       loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
        break;
  
      case CONCAT:
        loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1));
        break;
  
      default:
        abort ();
      }
--- 8591,8639 ----
        break;
  
      case MEM:
!       loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
! 				       can_use_fbreg);
        break;
  
      case CONCAT:
        loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1));
        break;
  
+     case VAR_LOCATION:
+       /* Single part.  */
+       if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
+ 	{
+ 	  loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), can_use_fbreg);
+ 	}
+       /* Multiple parts.  */
+       else
+ 	{
+ 	  rtvec par_elems = XVEC (XEXP (rtl, 1), 0);
+ 	  int num_elem = GET_NUM_ELEM (par_elems);
+ 	  enum machine_mode mode;
+ 	  int i;
+ 
+ 	  /* Create the first one, so we have something to add to.  */
+ 	  loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
+ 				       can_use_fbreg);
+ 	  mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
+ 	  add_loc_descr (&loc_result,
+ 			 new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
+ 	  for (i = 1; i < num_elem; i++)
+ 	    {
+ 	      dw_loc_descr_ref temp;
+ 
+ 	      temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
+ 				     can_use_fbreg);
+ 	      add_loc_descr (&loc_result, temp);
+ 	      mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
+ 	      add_loc_descr (&loc_result,
+ 			     new_loc_descr (DW_OP_piece,
+ 					    GET_MODE_SIZE (mode), 0));
+ 	    }
+ 	}
+       break;
+ 
      default:
        abort ();
      }
*************** loc_descriptor_from_tree (tree loc, int 
*** 8592,8598 ****
  		rtl = XEXP (rtl, 0);
  	      }
  
! 	    ret = mem_loc_descriptor (rtl, mode);
  	  }
        }
        break;
--- 8749,8755 ----
  		rtl = XEXP (rtl, 0);
  	      }
  
! 	    ret = mem_loc_descriptor (rtl, mode, true);
  	  }
        }
        break;
*************** loc_descriptor_from_tree (tree loc, int 
*** 8676,8682 ****
  	rtl = (*targetm.delegitimize_address) (rtl);
  
  	indirect_p = 1;
! 	ret = mem_loc_descriptor (rtl, mode);
  	break;
        }
  
--- 8833,8839 ----
  	rtl = (*targetm.delegitimize_address) (rtl);
  
  	indirect_p = 1;
! 	ret = mem_loc_descriptor (rtl, mode, true);
  	break;
        }
  
*************** rtl_for_decl_location (tree decl)
*** 9471,9486 ****
     function call evaluates to a compile-time constant address.  */
  
  static void
! add_location_or_const_value_attribute (dw_die_ref die, tree decl)
  {
    rtx rtl;
    dw_loc_descr_ref descr;
  
    if (TREE_CODE (decl) == ERROR_MARK)
      return;
    else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
      abort ();
  
    rtl = rtl_for_decl_location (decl);
    if (rtl == NULL_RTX)
      return;
--- 9628,9737 ----
     function call evaluates to a compile-time constant address.  */
  
  static void
! add_location_or_const_value_attribute (dw_die_ref die, tree decl,
! 				       enum dwarf_attribute attr)
  {
    rtx rtl;
    dw_loc_descr_ref descr;
+   var_loc_list *loc_list;
  
    if (TREE_CODE (decl) == ERROR_MARK)
      return;
    else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
      abort ();
  
+   /* See if we possibly have multiple locations for this variable.  */
+   loc_list = lookup_decl_loc (decl);
+ 
+   /* If it truly has multiple locations, the first and last node will
+      differ.  */
+   if (loc_list && loc_list->first != loc_list->last)
+     {
+       const char *secname;
+       const char *endname;
+       dw_loc_list_ref list;
+       rtx varloc;
+       struct var_loc_node *node;
+ 
+       /* 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, this
+ 	 won't notice.  */
+ 
+       if (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
+ 	secname = TEXT_SECTION_NAME;
+ 
+       /* 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);
+       list = new_loc_list (loc_descriptor (varloc, attr != DW_AT_frame_base),
+ 			   node->label, node->next->label, secname, 1);
+       node = node->next;
+ 
+       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.  */
+ 	    varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+ 	    add_loc_descr_to_loc_list (&list,
+ 				       loc_descriptor (varloc,
+ 						       attr != DW_AT_frame_base),
+ 				       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)
+ 	{
+ 	  char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
+ 
+ 	  varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+ 	  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);
+ 	    }
+ 	  add_loc_descr_to_loc_list (&list,
+ 				     loc_descriptor (varloc,
+ 						     attr != DW_AT_frame_base),
+ 				     node->label, endname, secname);
+ 	}
+ 
+       /* Finally, add the location list to the DIE, and we are done.  */
+       add_AT_loc_list (die, attr, list);
+       return;
+     }
+ 
    rtl = rtl_for_decl_location (decl);
    if (rtl == NULL_RTX)
      return;
*************** add_location_or_const_value_attribute (d
*** 9517,9525 ****
  	case REG:
  	case SUBREG:
  	case CONCAT:
! 	  descr = loc_descriptor (rtl);
  	}
!       add_AT_location_description (die, DW_AT_location, descr);
        break;
  
      case PARALLEL:
--- 9768,9776 ----
  	case REG:
  	case SUBREG:
  	case CONCAT:
! 	  descr = loc_descriptor (rtl, true);
  	}
!       add_AT_location_description (die, attr, descr);
        break;
  
      case PARALLEL:
*************** add_location_or_const_value_attribute (d
*** 9530,9536 ****
  	int i;
  
  	/* Create the first one, so we have something to add to.  */
! 	descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0));
  	mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
  	add_loc_descr (&descr,
  		       new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
--- 9781,9787 ----
  	int i;
  
  	/* Create the first one, so we have something to add to.  */
! 	descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), true);
  	mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
  	add_loc_descr (&descr,
  		       new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
*************** add_location_or_const_value_attribute (d
*** 9538,9544 ****
  	  {
  	    dw_loc_descr_ref temp;
  
! 	    temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0));
  	    add_loc_descr (&descr, temp);
  	    mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
  	    add_loc_descr (&descr,
--- 9789,9795 ----
  	  {
  	    dw_loc_descr_ref temp;
  
! 	    temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), true);
  	    add_loc_descr (&descr, temp);
  	    mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
  	    add_loc_descr (&descr,
*************** add_bound_info (dw_die_ref subrange_die,
*** 9684,9690 ****
  	  add_AT_flag (decl_die, DW_AT_artificial, 1);
  	  add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
  	  add_AT_location_description (decl_die, DW_AT_location,
! 				       loc_descriptor (loc));
  	  add_AT_die_ref (subrange_die, bound_attr, decl_die);
  	}
  
--- 9935,9941 ----
  	  add_AT_flag (decl_die, DW_AT_artificial, 1);
  	  add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
  	  add_AT_location_description (decl_die, DW_AT_location,
! 				       loc_descriptor (loc, true));
  	  add_AT_die_ref (subrange_die, bound_attr, decl_die);
  	}
  
*************** gen_formal_parameter_die (tree node, dw_
*** 10507,10513 ****
  
        equate_decl_number_to_die (node, parm_die);
        if (! DECL_ABSTRACT (node))
! 	add_location_or_const_value_attribute (parm_die, node);
  
        break;
  
--- 10758,10764 ----
  
        equate_decl_number_to_die (node, parm_die);
        if (! DECL_ABSTRACT (node))
! 	add_location_or_const_value_attribute (parm_die, node, DW_AT_location);
  
        break;
  
*************** gen_subprogram_die (tree decl, dw_die_re
*** 10841,10849 ****
        /* Define the "frame base" location for this routine.  We use the
  	 frame pointer or stack pointer registers, since the RTL for local
  	 variables is relative to one of them.  */
!       fp_reg
! 	= frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
!       add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg));
  
  #if 0
        /* ??? This fails for nested inline functions, because context_display
--- 11092,11108 ----
        /* Define the "frame base" location for this routine.  We use the
  	 frame pointer or stack pointer registers, since the RTL for local
  	 variables is relative to one of them.  */
!       if (frame_base_decl && lookup_decl_loc (frame_base_decl) != NULL)
! 	{
! 	  add_location_or_const_value_attribute (subr_die, frame_base_decl,
! 						 DW_AT_frame_base);
! 	}
!       else
! 	{
! 	  fp_reg
! 	    = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
! 	  add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg));
! 	}
  
  #if 0
        /* ??? This fails for nested inline functions, because context_display
*************** gen_variable_die (tree decl, dw_die_ref 
*** 11012,11018 ****
  
    if (! declaration && ! DECL_ABSTRACT (decl))
      {
!       add_location_or_const_value_attribute (var_die, decl);
        add_pubname (decl, var_die);
      }
    else
--- 11271,11277 ----
  
    if (! declaration && ! DECL_ABSTRACT (decl))
      {
!       add_location_or_const_value_attribute (var_die, decl, DW_AT_location);
        add_pubname (decl, var_die);
      }
    else
*************** init_file_table (void)
*** 12531,12536 ****
--- 12790,12850 ----
    file_table_last_lookup_index = 0;
  }
  
+ /* Called by the final INSN scan whenever we see a var location.  We
+    use it to drop labels in the right places, and throw the location in
+    our lookup table.  */
+ 
+ static void
+ dwarf2out_var_location (rtx loc_note)
+ {
+   char loclabel[MAX_ARTIFICIAL_LABEL_BYTES];
+   struct var_loc_node *newloc;
+   rtx prev_insn;
+   static rtx last_insn;
+   static const char *last_label;
+ 
+   if (!DECL_P (NOTE_VAR_LOCATION_DECL (loc_note)))
+     return;
+   prev_insn = PREV_INSN (loc_note);
+ 
+   newloc = ggc_alloc_cleared (sizeof (struct var_loc_node));
+   /* If the insn we processed last time is the previous insn
+      and it is also a var location note, use the label we emitted
+      last time.  */
+   if (last_insn != NULL_RTX
+       && last_insn == prev_insn
+       && GET_CODE (prev_insn) == NOTE
+       && NOTE_LINE_NUMBER (prev_insn) == NOTE_INSN_VAR_LOCATION)
+     {
+       newloc->label = last_label;
+     }
+   else
+     {
+       ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);
+       ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
+       loclabel_num++;
+       newloc->label = ggc_strdup (loclabel);
+     }
+   newloc->var_loc_note = loc_note;
+   newloc->next = NULL;
+ 
+   last_insn = loc_note;
+   last_label = newloc->label;
+ 
+   add_var_loc_to_decl (NOTE_VAR_LOCATION_DECL (loc_note), newloc);
+ }
+ 
+ /* We need to reset the locations at the beginning of each
+    function. We can't do this in the end_function hook, because the
+    declarations that use the locations won't have been outputted when
+    that hook is called.  */
+ 
+ static void
+ dwarf2out_begin_function (tree unused ATTRIBUTE_UNUSED)
+ {
+   htab_empty (decl_loc_table);
+ }
+ 
  /* Output a label to mark the beginning of a source code line entry
     and record information relating to this source line, in
     'line_info_table' for later output of the .debug_line section.  */
*************** dwarf2out_init (const char *filename ATT
*** 12707,12712 ****
--- 13021,13030 ----
    decl_die_table = htab_create_ggc (10, decl_die_table_hash,
  				    decl_die_table_eq, NULL);
  
+   /* Allocate the initial hunk of the decl_loc_table.  */
+   decl_loc_table = htab_create_ggc (10, decl_loc_table_hash,
+ 				    decl_loc_table_eq, NULL);
+ 
    /* Allocate the initial hunk of the decl_scope_table.  */
    VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table");
  

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2004-02-11 17:57 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-02-02 20:37 Variable tracking (location lists support) - part 2 Josef Zlomek
2004-02-06  3:34 ` Roger Sayle
2004-02-06 12:31   ` Josef Zlomek
2004-02-06 12:32     ` Josef Zlomek
2004-02-09 14:55       ` debug info breaks build (Was: Re: Variable tracking (location lists support) - part 2) Joern Rennecke
2004-02-09 15:45         ` Daniel Berlin
2004-02-09 16:34           ` Joern Rennecke
2004-02-09 17:26             ` Daniel Berlin
2004-02-09 21:48               ` Richard Henderson
2004-02-10 18:05                 ` Josef Zlomek
2004-02-10 18:12                   ` Daniel Berlin
2004-02-21 13:45                     ` Daniel Berlin
2004-02-21 13:45                   ` Josef Zlomek
2004-02-21 13:45                 ` Richard Henderson
2004-02-21 13:45               ` Daniel Berlin
2004-02-21 13:45             ` Joern Rennecke
2004-02-21 13:45           ` Daniel Berlin
2004-02-21 13:45         ` Joern Rennecke
2004-02-21 13:45       ` Variable tracking (location lists support) - part 2 Josef Zlomek
2004-02-06 13:41     ` Roger Sayle
2004-02-08 22:24       ` Roger Sayle
2004-02-08 23:01         ` Josef Zlomek
2004-02-21 13:45           ` Josef Zlomek
2004-02-21 13:45         ` Roger Sayle
2004-02-21 13:45       ` Roger Sayle
2004-02-21 13:45     ` Josef Zlomek
2004-02-21 13:45   ` Roger Sayle
2004-02-11 14:55 ` Kazu Hirata
2004-02-11 16:06   ` Josef Zlomek
2004-02-21 13:45     ` Josef Zlomek
2004-02-11 16:11   ` Rainer Orth
2004-02-11 17:15     ` Daniel Berlin
2004-02-11 17:32       ` Rainer Orth
2004-02-21 13:45         ` Rainer Orth
2004-02-21 13:45       ` Daniel Berlin
2004-02-21 13:45     ` Rainer Orth
2004-02-11 16:47   ` Daniel Berlin
2004-02-11 17:50     ` Kazu Hirata
2004-02-11 18:12       ` Zack Weinberg
2004-02-21 13:45         ` Zack Weinberg
2004-02-21 13:45       ` Kazu Hirata
2004-02-21 13:45     ` Daniel Berlin
2004-02-21 13:45   ` Kazu Hirata
2004-02-21 13:45 ` Josef Zlomek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).