This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


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

Re: DWARF2 fix for Fortran


On Tue, Oct 31, 2000 at 12:23:38PM -0800, Richard Henderson wrote:
> A bit of a hack.  Incidentally, it is clear how to emit debug info for
> all of these -- dwarf2 has a fairly comprehensive expression evaluator.
> 
> I'm currently testing a patch to emit them.

Here it is.  This passed make check on alpha with alpha/elf.h hacked to
make dwarf2 the default.  I'd be curious to see if this passes the Ada
test cases that caused the other hacks to be added.

As for testing the output itself, I mostly relied on readelf to dump out
the information.  The gdb in cvs as of today doesn't seem to do anything
with the information.  I'm presuming that means that it just doesn't
expect it to be there rather than the format is in some way invalid.  If
debugger folk would like to take a look,

  gcc/testsuite/g77.f-torture/execute/19981119-0.f

is a nice simple standalone test case.


r~


        * dwarf2out.c (struct dw_loc_descr_struct): Add dw_loc_addr.
        (size_of_locs): Set it.
        (output_loc_operands): Use it to compute branch displacement.
        (int_loc_descriptor): New.
        (mem_loc_descriptor): Dereference memory in the proper size.
        Use DW_OP_plus_uconst when possible.  Use int_loc_descriptor.
        (loc_descriptor_from_tree): New.
        (rtl_for_decl_location): Break out from ...
        (add_location_or_const_value_attribute): ... here.
        (add_bound_info): Use loc_descriptor_from_tree.

Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarf2out.c,v
retrieving revision 1.212
diff -c -p -d -r1.212 dwarf2out.c
*** dwarf2out.c	2000/10/20 17:35:18	1.212
--- dwarf2out.c	2000/11/01 00:06:33
*************** typedef struct dw_loc_descr_struct
*** 2176,2181 ****
--- 2176,2182 ----
    enum dwarf_location_atom dw_loc_opc;
    dw_val_node dw_loc_oprnd1;
    dw_val_node dw_loc_oprnd2;
+   int dw_loc_addr;
  }
  dw_loc_descr_node;
  
*************** size_of_locs (loc)
*** 2645,2651 ****
    register unsigned long size = 0;
  
    for (; loc != NULL; loc = loc->dw_loc_next)
!     size += size_of_loc_descr (loc);
  
    return size;
  }
--- 2646,2655 ----
    register unsigned long size = 0;
  
    for (; loc != NULL; loc = loc->dw_loc_next)
!     {
!       loc->dw_loc_addr = size;
!       size += size_of_loc_descr (loc);
!     }
  
    return size;
  }
*************** output_loc_operands (loc)
*** 2683,2690 ****
        break;
      case DW_OP_skip:
      case DW_OP_bra:
!       ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
!       fputc ('\n', asm_out_file);
        break;
  #else
      case DW_OP_addr:
--- 2687,2703 ----
        break;
      case DW_OP_skip:
      case DW_OP_bra:
!       {
! 	int offset;
! 
! 	if (val1->val_class == dw_val_class_loc)
! 	  offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3);
! 	else
! 	  abort ();
! 
! 	ASM_OUTPUT_DWARF_DATA2 (asm_out_file, offset);
! 	fputc ('\n', asm_out_file);
!       }
        break;
  #else
      case DW_OP_addr:
*************** static dw_die_ref modified_type_die	PARA
*** 3426,3436 ****
--- 3439,3451 ----
  static int type_is_enum			PARAMS ((tree));
  static unsigned int reg_number		PARAMS ((rtx));
  static dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx));
+ static dw_loc_descr_ref int_loc_descriptor PARAMS ((HOST_WIDE_INT));
  static dw_loc_descr_ref based_loc_descr	PARAMS ((unsigned, long));
  static int is_based_loc			PARAMS ((rtx));
  static dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode));
  static dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx));
  static dw_loc_descr_ref loc_descriptor	PARAMS ((rtx));
+ static dw_loc_descr_ref loc_descriptor_from_tree PARAMS ((tree, int));
  static HOST_WIDE_INT ceiling		PARAMS ((HOST_WIDE_INT, unsigned int));
  static tree field_type			PARAMS ((tree));
  static unsigned int simple_type_align_in_bits PARAMS ((tree));
*************** static void add_AT_location_description	
*** 3440,3445 ****
--- 3455,3461 ----
  						 enum dwarf_attribute, rtx));
  static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
  static void add_const_value_attribute	PARAMS ((dw_die_ref, rtx));
+ static rtx rtl_for_decl_location	PARAMS ((tree));
  static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
  static void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree));
  static void add_name_attribute		PARAMS ((dw_die_ref, const char *));
*************** reg_loc_descriptor (rtl)
*** 7173,7178 ****
--- 7189,7234 ----
    return loc_result;
  }
  
+ /* Return a location descriptor that designates a constant.  */
+ 
+ static dw_loc_descr_ref
+ int_loc_descriptor (i)
+      HOST_WIDE_INT i;
+ {
+   enum dwarf_location_atom op;
+ 
+   /* Pick the smallest representation of a constant, rather than just
+      defaulting to the LEB encoding.  */
+   if (i >= 0)
+     {
+       if (i <= 31)
+ 	op = DW_OP_lit0 + i;
+       else if (i <= 0xff)
+ 	op = DW_OP_const1u;
+       else if (i <= 0xffff)
+ 	op = DW_OP_const2u;
+       else if (HOST_BITS_PER_WIDE_INT == 32
+ 	       || i <= 0xffffffff)
+ 	op = DW_OP_const4u;
+       else
+ 	op = DW_OP_constu;
+     }
+   else
+     {
+       if (i >= -0x80)
+ 	op = DW_OP_const1s;
+       else if (i >= -0x8000)
+ 	op = DW_OP_const2s;
+       else if (HOST_BITS_PER_WIDE_INT == 32
+ 	       || i >= -0x80000000)
+ 	op = DW_OP_const4s;
+       else
+ 	op = DW_OP_consts;
+     }
+ 
+   return new_loc_descr (op, i, 0);
+ }
+ 
  /* Return a location descriptor that designates a base+offset location.  */
  
  static dw_loc_descr_ref
*************** mem_loc_descriptor (rtl, mode)
*** 7274,7285 ****
        break;
  
      case MEM:
!       mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
!       add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
        break;
  
!      case LABEL_REF:
!        /* Some ports can transform a symbol ref into a label ref, because
   	 the symbol ref is too far away and has to be dumped into a constant
   	 pool.  */
      case CONST:
--- 7330,7351 ----
        break;
  
      case MEM:
!       {
! 	dw_loc_descr_ref deref;
! 
! 	mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
! 
! 	if (GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE)
! 	  deref = new_loc_descr (DW_OP_deref, 0, 0);
! 	else
! 	  deref = new_loc_descr (DW_OP_deref_size, GET_MODE_SIZE (mode), 0);
! 
! 	add_loc_descr (&mem_loc_result, deref);
!       }
        break;
  
!     case LABEL_REF:
!       /* Some ports can transform a symbol ref into a label ref, because
   	 the symbol ref is too far away and has to be dumped into a constant
   	 pool.  */
      case CONST:
*************** mem_loc_descriptor (rtl, mode)
*** 7306,7329 ****
  					  INTVAL (XEXP (rtl, 1)));
        else
  	{
! 	  add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0),
! 							      mode));
! 	  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));
  	}
        break;
  
      case MULT:
        /* If a pseudo-reg is optimized away, it is possible for it to
  	 be replaced with a MEM containing a multiply.  */
!       add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0), mode));
!       add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1), mode));
        add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
        break;
  
      case CONST_INT:
!       mem_loc_result = new_loc_descr (DW_OP_constu, INTVAL (rtl), 0);
        break;
  
      default:
--- 7372,7408 ----
  					  INTVAL (XEXP (rtl, 1)));
        else
  	{
! 	  mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
! 
! 	  if (GET_CODE (XEXP (rtl, 1)) == CONST_INT
! 	      && INTVAL (XEXP (rtl, 1)) >= 0)
! 	    {
! 	      add_loc_descr (&mem_loc_result,
! 			     new_loc_descr (DW_OP_plus_uconst,
! 					    INTVAL (XEXP (rtl, 1)), 0));
! 	    }
! 	  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));
! 	    }
  	}
        break;
  
      case MULT:
        /* If a pseudo-reg is optimized away, it is possible for it to
  	 be replaced with a MEM containing a multiply.  */
!       add_loc_descr (&mem_loc_result,
! 		     mem_loc_descriptor (XEXP (rtl, 0), mode));
!       add_loc_descr (&mem_loc_result,
! 		     mem_loc_descriptor (XEXP (rtl, 1), mode));
        add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
        break;
  
      case CONST_INT:
!       mem_loc_result = int_loc_descriptor (INTVAL (rtl));
        break;
  
      default:
*************** loc_descriptor (rtl)
*** 7399,7404 ****
--- 7478,7737 ----
    return loc_result;
  }
  
+ /* Similar, but generate the descriptor from trees instead of rtl.
+    This comes up particularly with variable length arrays.  */
+ 
+ static dw_loc_descr_ref
+ loc_descriptor_from_tree (loc, addressp)
+      tree loc;
+      int addressp;
+ {
+   dw_loc_descr_ref ret = NULL;
+   int indirect_size = 0;
+   int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc));
+   enum dwarf_location_atom op;
+ 
+   /* ??? Most of the time we do not take proper care for sign/zero
+      extending the values properly.  Hopefully this won't be a real
+      problem...  */
+ 
+   switch (TREE_CODE (loc))
+     {
+     case ERROR_MARK:
+       break;
+ 
+     case VAR_DECL:
+     case PARM_DECL:
+       {
+ 	rtx rtl = rtl_for_decl_location (loc);
+ 	enum machine_mode mode = DECL_MODE (loc);
+ 
+ 	if (CONSTANT_P (rtl))
+ 	  {
+ 	    ret = new_loc_descr (DW_OP_addr, 0, 0);
+ 	    ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
+ 	    ret->dw_loc_oprnd1.v.val_addr = rtl;
+ 	    indirect_size = GET_MODE_SIZE (mode);
+ 	  }
+ 	else
+ 	  {
+ 	    if (GET_CODE (rtl) == MEM)
+ 	      {
+ 		indirect_size = GET_MODE_SIZE (mode);
+ 		rtl = XEXP (rtl, 0);
+ 	      }
+ 	    ret = mem_loc_descriptor (rtl, mode);
+ 	  }
+       }
+       break;
+ 
+     case INDIRECT_REF:
+       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+       indirect_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (loc)));
+       break;
+ 
+     case COMPONENT_REF:
+     case BIT_FIELD_REF:
+     case ARRAY_REF:
+       {
+ 	tree obj, offset;
+ 	HOST_WIDE_INT bitsize, bitpos, bytepos;
+ 	enum machine_mode mode;
+ 	int volatilep;
+ 	unsigned int alignment;
+ 
+ 	obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
+ 				   &unsignedp, &volatilep, &alignment);
+ 	ret = loc_descriptor_from_tree (obj, 1);
+ 
+ 	if (offset != NULL_TREE)
+ 	  {
+ 	    /* Variable offset.  */
+ 	    add_loc_descr (&ret, loc_descriptor_from_tree (offset, 0));
+ 	    add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
+ 	  }
+ 
+ 	if (addressp)
+ 	  {
+ 	    /* We cannot address anything not on a unit boundary.  */
+ 	    if (bitpos % BITS_PER_UNIT != 0)
+ 	      abort ();
+ 	  }
+ 	else
+ 	  {
+ 	    if (bitpos % BITS_PER_UNIT != 0
+ 		|| bitsize % BITS_PER_UNIT != 0)
+ 	      {
+ 		/* ??? We could handle this by loading and shifting etc.
+ 		   Wait until someone needs it before expending the effort.  */
+ 		abort ();
+ 	      }
+ 
+ 	    indirect_size = bitsize / BITS_PER_UNIT;
+ 	  }
+ 
+ 	bytepos = bitpos / BITS_PER_UNIT;
+ 	if (bytepos > 0)
+ 	  add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
+ 	else if (bytepos < 0)
+ 	  {
+ 	    add_loc_descr (&ret, int_loc_descriptor (bytepos));
+ 	    add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
+ 	  }
+ 	break;
+       }
+ 
+     case INTEGER_CST:
+       if (host_integerp (loc, 0))
+ 	ret = int_loc_descriptor (tree_low_cst (loc, 0));
+       break;
+       break;
+ 
+     case BIT_AND_EXPR:
+       op = DW_OP_and;
+       goto do_binop;
+     case BIT_XOR_EXPR:
+       op = DW_OP_xor;
+       goto do_binop;
+     case BIT_IOR_EXPR:
+       op = DW_OP_or;
+       goto do_binop;
+     case TRUNC_DIV_EXPR:
+       op = DW_OP_div;
+       goto do_binop;
+     case MINUS_EXPR:
+       op = DW_OP_minus;
+       goto do_binop;
+     case TRUNC_MOD_EXPR:
+       op = DW_OP_mod;
+       goto do_binop;
+     case MULT_EXPR:
+       op = DW_OP_mul;
+       goto do_binop;
+     case LSHIFT_EXPR:
+       op = DW_OP_shl;
+       goto do_binop;
+     case RSHIFT_EXPR:
+       op = (unsignedp ? DW_OP_shr : DW_OP_shra);
+       goto do_binop;
+     case PLUS_EXPR:
+       if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
+ 	  && host_integerp (TREE_OPERAND (loc, 1), 0))
+ 	{
+ 	  ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+ 	  add_loc_descr (&ret,
+ 			 new_loc_descr (DW_OP_plus_uconst,
+ 					tree_low_cst (TREE_OPERAND (loc, 1),
+ 						      0),
+ 					0));
+ 	  break;
+ 	}
+       op = DW_OP_plus;
+       goto do_binop;
+     case LE_EXPR:
+       if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ 	break;
+       op = DW_OP_le;
+       goto do_binop;
+     case GE_EXPR:
+       if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ 	break;
+       op = DW_OP_ge;
+       goto do_binop;
+     case LT_EXPR:
+       if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ 	break;
+       op = DW_OP_lt;
+       goto do_binop;
+     case GT_EXPR:
+       if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ 	break;
+       op = DW_OP_gt;
+       goto do_binop;
+     case EQ_EXPR:
+       op = DW_OP_eq;
+       goto do_binop;
+     case NE_EXPR:
+       op = DW_OP_ne;
+       goto do_binop;
+ 
+     do_binop:
+       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+       add_loc_descr (&ret, loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0));
+       add_loc_descr (&ret, new_loc_descr (op, 0, 0));
+       break;
+ 
+     case BIT_NOT_EXPR:
+       op = DW_OP_not;
+       goto do_unop;
+     case ABS_EXPR:
+       op = DW_OP_abs;
+       goto do_unop;
+     case NEGATE_EXPR:
+       op = DW_OP_neg;
+       goto do_unop;
+ 
+     do_unop:
+       ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+       add_loc_descr (&ret, new_loc_descr (op, 0, 0));
+       break;
+ 
+     case MAX_EXPR:
+       loc = build (COND_EXPR, TREE_TYPE (loc),
+ 		   build (LT_EXPR, integer_type_node,
+ 			  TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
+ 		   TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
+       /* FALLTHRU */
+ 
+     case COND_EXPR:
+       {
+ 	dw_loc_descr_ref bra_node, jump_node, tmp;
+ 
+ 	ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0);
+ 	bra_node = new_loc_descr (DW_OP_bra, 0, 0);
+ 	add_loc_descr (&ret, bra_node);
+ 
+ 	tmp = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0);
+ 	add_loc_descr (&ret, tmp);
+ 	jump_node = new_loc_descr (DW_OP_skip, 0, 0);
+ 	add_loc_descr (&ret, jump_node);
+ 
+ 	tmp = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+ 	add_loc_descr (&ret, tmp);
+ 	bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
+ 	bra_node->dw_loc_oprnd1.v.val_loc = tmp;
+ 
+ 	/* ??? 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;
+       }
+       break;
+ 
+     default:
+       abort ();
+     }
+ 
+   /* If we can't fill the request for an address, die.  */
+   if (addressp && indirect_size == 0)
+     abort ();
+ 
+   /* If we've got an address and don't want one, dereference.  */
+   if (!addressp && indirect_size > 0)
+     {
+       if (indirect_size > DWARF2_ADDR_SIZE)
+ 	abort ();
+       if (indirect_size == DWARF2_ADDR_SIZE)
+ 	op = DW_OP_deref;
+       else
+ 	op = DW_OP_deref_size;
+       add_loc_descr (&ret, new_loc_descr (op, indirect_size, 0));
+     }
+ 
+   return ret;
+ }
+ 
  /* Given a value, round it up to the lowest multiple of `boundary'
     which is not less than the value itself.  */
  
*************** add_const_value_attribute (die, rtl)
*** 7767,7799 ****
      }
  
  }
- 
- /* Generate *either* an DW_AT_location attribute or else an 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
-    or parameter does not have a true "location" either in memory or in a
-    register.  This can happen (for example) when a constant is passed as an
-    actual argument in a call to an inline function.  (It's possible that
-    these things can crop up in other ways also.)  Note that one type of
-    constant value which can be passed into an inlined function is a constant
-    pointer.  This can happen for example if an actual argument in an inlined
-    function call evaluates to a compile-time constant address.  */
  
! static void
! add_location_or_const_value_attribute (die, decl)
!      register dw_die_ref die;
!      register tree decl;
  {
    register rtx rtl;
-   register tree declared_type;
-   register tree passed_type;
  
-   if (TREE_CODE (decl) == ERROR_MARK)
-     return;
- 
-   if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
-     abort ();
- 
    /* Here we have to decide where we are going to say the parameter "lives"
       (as far as the debugger is concerned).  We only have a couple of
       choices.  GCC provides us with DECL_RTL and with DECL_INCOMING_RTL.
--- 8100,8112 ----
      }
  
  }
  
! static rtx
! rtl_for_decl_location (decl)
!      tree decl;
  {
    register rtx rtl;
  
    /* Here we have to decide where we are going to say the parameter "lives"
       (as far as the debugger is concerned).  We only have a couple of
       choices.  GCC provides us with DECL_RTL and with DECL_INCOMING_RTL.
*************** add_location_or_const_value_attribute (d
*** 7876,7883 ****
      {
        if (rtl == NULL_RTX || is_pseudo_reg (rtl))
  	{
! 	  declared_type = type_main_variant (TREE_TYPE (decl));
! 	  passed_type = type_main_variant (DECL_ARG_TYPE (decl));
  
  	  /* This decl represents a formal parameter which was optimized out.
  	     Note that DECL_INCOMING_RTL may be NULL in here, but we handle
--- 8189,8196 ----
      {
        if (rtl == NULL_RTX || is_pseudo_reg (rtl))
  	{
! 	  tree declared_type = type_main_variant (TREE_TYPE (decl));
! 	  tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
  
  	  /* This decl represents a formal parameter which was optimized out.
  	     Note that DECL_INCOMING_RTL may be NULL in here, but we handle
*************** add_location_or_const_value_attribute (d
*** 7924,7937 ****
  	}
      }
  
!   if (rtl == NULL_RTX)
!     return;
! 
!   rtl = eliminate_regs (rtl, 0, NULL_RTX);
  #ifdef LEAF_REG_REMAP
!   if (current_function_uses_only_leaf_regs)
!     leaf_renumber_regs_insn (rtl);
  #endif
  
    switch (GET_CODE (rtl))
      {
--- 8237,8279 ----
  	}
      }
  
!   if (rtl != NULL_RTX)
!     {
!       rtl = eliminate_regs (rtl, 0, NULL_RTX);
  #ifdef LEAF_REG_REMAP
!       if (current_function_uses_only_leaf_regs)
! 	leaf_renumber_regs_insn (rtl);
  #endif
+     }
+ 
+   return rtl;
+ }
+ 
+ /* Generate *either* an DW_AT_location attribute or else an 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
+    or parameter does not have a true "location" either in memory or in a
+    register.  This can happen (for example) when a constant is passed as an
+    actual argument in a call to an inline function.  (It's possible that
+    these things can crop up in other ways also.)  Note that one type of
+    constant value which can be passed into an inlined function is a constant
+    pointer.  This can happen for example if an actual argument in an inlined
+    function call evaluates to a compile-time constant address.  */
+ 
+ static void
+ add_location_or_const_value_attribute (die, decl)
+      register dw_die_ref die;
+      register tree decl;
+ {
+   register rtx rtl;
+ 
+   if (TREE_CODE (decl) == ERROR_MARK)
+     return;
+ 
+   if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL)
+     abort ();
+ 
+   rtl = rtl_for_decl_location (decl);
  
    switch (GET_CODE (rtl))
      {
*************** add_bound_info (subrange_die, bound_attr
*** 8102,8117 ****
        /* Else leave out the attribute.  */
        break;
  
-     case MAX_EXPR:
      case VAR_DECL:
!     case COMPONENT_REF:
!     case COND_EXPR:
!       /* ??? These types of bounds can be created by the Ada front end,
! 	 and it isn't clear how to emit debug info for them.  */
!       break;
  
      default:
!       abort ();
      }
  }
  
--- 8444,8486 ----
        /* Else leave out the attribute.  */
        break;
  
      case VAR_DECL:
!     case PARM_DECL:
!       {
! 	dw_die_ref decl_die = lookup_decl_die (bound);
  
+ 	/* ??? Can this happen, or should the variable have been bound
+ 	   first?  Probably it can, since I imagine that we try to create
+ 	   the types of parameters in the order in which they exist in
+ 	   the list, and won't have created a forward reference to a 
+ 	   later parameter.  */
+ 	if (decl_die != NULL)
+ 	  add_AT_die_ref (subrange_die, bound_attr, decl_die);
+ 	break;
+       }
+ 
      default:
!       {
! 	/* Otherwise try to create a stack operation procedure to
! 	   evaluate the value of the array bound.  */
! 
! 	dw_die_ref ctx, decl_die;
! 	dw_loc_descr_ref loc;
! 
! 	loc = loc_descriptor_from_tree (bound, 0);
! 	if (loc == NULL)
! 	  break;
! 
! 	ctx = lookup_decl_die (current_function_decl);
! 
! 	decl_die = new_die (DW_TAG_variable, ctx);
! 	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;
!       }
      }
  }
  

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