]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR debug/47858 (IPA-SRA decreases quality of debug info)
authorJakub Jelinek <jakub@redhat.com>
Wed, 22 Jun 2011 10:41:58 +0000 (12:41 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 22 Jun 2011 10:41:58 +0000 (12:41 +0200)
PR debug/47858
* gimple.h (enum gimple_debug_subcode): Add GIMPLE_DEBUG_SOURCE_BIND.
(gimple_build_debug_source_bind_stat): New prototype.
(gimple_build_debug_source_bind): Define.
(gimple_debug_source_bind_p, gimple_debug_source_bind_get_var,
gimple_debug_source_bind_get_value,
gimple_debug_source_bind_get_value_ptr,
gimple_debug_source_bind_set_var,
gimple_debug_source_bind_set_value): New inlines.
* gimple.c (gimple_build_debug_source_bind_stat): New function.
* gimple-pretty-print.c (dump_gimple_debug): Handle
GIMPLE_DEBUG_SOURCE_BIND.
* sese.c (rename_uses): Handle gimple_debug_source_bind_p.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
* tree-parloops.c (eliminate_local_variables,
separate_decls_in_region): Likewise.
(separate_decls_in_region_debug): Renamed from
separate_decls_in_region_debug_bind.  Handle
gimple_debug_source_bind_p.
* tree.h (decl_debug_args_lookup, decl_debug_args_insert): New
prototypes.
(DECL_HAS_DEBUG_ARGS_P): Define.
(struct tree_function_decl): Add has_debug_args_flag field.
* tree.c (debug_args_for_decl): New variable.
(decl_debug_args_lookup, decl_debug_args_insert): New functions.
* tree-into-ssa.c (mark_def_sites): Handle uses in debug stmts.
(rewrite_debug_stmt_uses): New function.
(rewrite_stmt): Use it to rewrite debug stmt uses.
* rtl.def (DEBUG_PARAMETER_REF): New.
* rtl.h (DEBUG_PARAMETER_REF_DECL): Define.
* cselib.c (rtx_equal_for_cselib_1, cselib_hash_rtx): Handle
DEBUG_PARAMETER_REF.
* rtl.c (rtx_equal_p_cb, rtx_equal_p, iterative_hash_rtx): Likewise.
* print-rtl.c (print_rtx): Likewise.
* tree-sra.c (sra_ipa_reset_debug_stmts): Prefer replacing of
SSA_NAMEs with DEBUG_EXPR_DECLs initialized in source bind
debug stmts in the first bb.
* tree-inline.c (remap_ssa_name): If remapping default def
of a PARM_DECL fails, map to a DEBUG_EXPR_DECL set in
a source bind debug stmt.
(remap_gimple_stmt): Handle gimple_debug_source_bind_p.
(maybe_move_debug_stmts_to_successors): Likewise.
(copy_debug_stmt): Likewise.  Avoid shadowing a variable.
(tree_function_versioning): If DECL_HAS_DEBUG_ARGS_P, copy
debug args vector from old_decl to new_decl.
* ipa-prop.c (ipa_modify_call_arguments): For optimized away
or modified parameters, add debug bind stmts before call
setting DEBUG_EXPR_DECL which is remembered in debug args
vector.
* cfgexpand.c (expand_call_stmt): Call expand_debug_expr
on DECL_DEBUG_EXPRs from debug args vector.
(expand_debug_source_expr): New function.
(expand_debug_locations): Use it for source bind insns.
(expand_gimple_basic_block): Handle gimple_debug_source_bind_p.
* var-tracking.c (prepare_call_arguments): Add debug args
to call_arguments if any.
* dwarf2out.c (dwarf_stack_op_name, size_of_loc_descr,
output_loc_operands, output_loc_operands_raw,
resolve_addr_in_expr, compare_loc_operands): Handle
DW_OP_GNU_parameter_ref.
(get_ref_die_offset, parameter_ref_descriptor): New functions.
(mem_loc_descriptor): Handle DEBUG_PARAMETER_REF.
(gen_subprogram_die): Handle parameters identified by
DEBUG_PARAMETER_REF.

* dwarf2.h (enum dwarf_location_atom): Add DW_OP_GNU_parameter_ref.

From-SVN: r175288

23 files changed:
gcc/ChangeLog
gcc/cfgexpand.c
gcc/cselib.c
gcc/dwarf2out.c
gcc/gimple-pretty-print.c
gcc/gimple.c
gcc/gimple.h
gcc/ipa-prop.c
gcc/print-rtl.c
gcc/rtl.c
gcc/rtl.def
gcc/rtl.h
gcc/sese.c
gcc/tree-inline.c
gcc/tree-into-ssa.c
gcc/tree-parloops.c
gcc/tree-sra.c
gcc/tree-ssa-dce.c
gcc/tree.c
gcc/tree.h
gcc/var-tracking.c
include/ChangeLog
include/dwarf2.h

index 83c9b1021be4176fc893189d34c2cd0177bb8ba2..00391cbcb2a8c9dbf4437574f09f99ba2f2d5690 100644 (file)
@@ -1,3 +1,70 @@
+2011-06-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/47858
+       * gimple.h (enum gimple_debug_subcode): Add GIMPLE_DEBUG_SOURCE_BIND.
+       (gimple_build_debug_source_bind_stat): New prototype.
+       (gimple_build_debug_source_bind): Define.
+       (gimple_debug_source_bind_p, gimple_debug_source_bind_get_var,
+       gimple_debug_source_bind_get_value,
+       gimple_debug_source_bind_get_value_ptr,
+       gimple_debug_source_bind_set_var,
+       gimple_debug_source_bind_set_value): New inlines.
+       * gimple.c (gimple_build_debug_source_bind_stat): New function.
+       * gimple-pretty-print.c (dump_gimple_debug): Handle
+       GIMPLE_DEBUG_SOURCE_BIND.
+       * sese.c (rename_uses): Handle gimple_debug_source_bind_p.
+       * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
+       * tree-parloops.c (eliminate_local_variables,
+       separate_decls_in_region): Likewise.
+       (separate_decls_in_region_debug): Renamed from
+       separate_decls_in_region_debug_bind.  Handle
+       gimple_debug_source_bind_p.
+       * tree.h (decl_debug_args_lookup, decl_debug_args_insert): New
+       prototypes.
+       (DECL_HAS_DEBUG_ARGS_P): Define.
+       (struct tree_function_decl): Add has_debug_args_flag field.
+       * tree.c (debug_args_for_decl): New variable.
+       (decl_debug_args_lookup, decl_debug_args_insert): New functions.
+       * tree-into-ssa.c (mark_def_sites): Handle uses in debug stmts.
+       (rewrite_debug_stmt_uses): New function.
+       (rewrite_stmt): Use it to rewrite debug stmt uses.
+       * rtl.def (DEBUG_PARAMETER_REF): New.
+       * rtl.h (DEBUG_PARAMETER_REF_DECL): Define.
+       * cselib.c (rtx_equal_for_cselib_1, cselib_hash_rtx): Handle
+       DEBUG_PARAMETER_REF.
+       * rtl.c (rtx_equal_p_cb, rtx_equal_p, iterative_hash_rtx): Likewise.
+       * print-rtl.c (print_rtx): Likewise.
+       * tree-sra.c (sra_ipa_reset_debug_stmts): Prefer replacing of
+       SSA_NAMEs with DEBUG_EXPR_DECLs initialized in source bind
+       debug stmts in the first bb.
+       * tree-inline.c (remap_ssa_name): If remapping default def
+       of a PARM_DECL fails, map to a DEBUG_EXPR_DECL set in
+       a source bind debug stmt.
+       (remap_gimple_stmt): Handle gimple_debug_source_bind_p.
+       (maybe_move_debug_stmts_to_successors): Likewise.
+       (copy_debug_stmt): Likewise.  Avoid shadowing a variable.
+       (tree_function_versioning): If DECL_HAS_DEBUG_ARGS_P, copy
+       debug args vector from old_decl to new_decl.
+       * ipa-prop.c (ipa_modify_call_arguments): For optimized away
+       or modified parameters, add debug bind stmts before call
+       setting DEBUG_EXPR_DECL which is remembered in debug args
+       vector.
+       * cfgexpand.c (expand_call_stmt): Call expand_debug_expr
+       on DECL_DEBUG_EXPRs from debug args vector.
+       (expand_debug_source_expr): New function.
+       (expand_debug_locations): Use it for source bind insns.
+       (expand_gimple_basic_block): Handle gimple_debug_source_bind_p.
+       * var-tracking.c (prepare_call_arguments): Add debug args
+       to call_arguments if any.
+       * dwarf2out.c (dwarf_stack_op_name, size_of_loc_descr,
+       output_loc_operands, output_loc_operands_raw,
+       resolve_addr_in_expr, compare_loc_operands): Handle
+       DW_OP_GNU_parameter_ref.
+       (get_ref_die_offset, parameter_ref_descriptor): New functions.
+       (mem_loc_descriptor): Handle DEBUG_PARAMETER_REF.
+       (gen_subprogram_die): Handle parameters identified by
+       DEBUG_PARAMETER_REF.
+
 2011-06-22  Nathan Sidwell  <nathan@codesourcery.com>
 
        * doc/invoke.texi (ARM Options): Document -mtls-dialect option.
index efd3ed93c36bf0bfc29c7eeedf288915f5a87a75..000a790a683694f4301c302df5314c6519cc14db 100644 (file)
@@ -57,6 +57,8 @@ struct ssaexpand SA;
    of comminucating the profile info to the builtin expanders.  */
 gimple currently_expanding_gimple_stmt;
 
+static rtx expand_debug_expr (tree);
+
 /* Return an expression tree corresponding to the RHS of GIMPLE
    statement STMT.  */
 
@@ -1863,6 +1865,21 @@ expand_call_stmt (gimple stmt)
   SET_EXPR_LOCATION (exp, gimple_location (stmt));
   TREE_BLOCK (exp) = gimple_block (stmt);
 
+  /* Ensure RTL is created for debug args.  */
+  if (decl && DECL_HAS_DEBUG_ARGS_P (decl))
+    {
+      VEC(tree, gc) **debug_args = decl_debug_args_lookup (decl);
+      unsigned int ix;
+      tree dtemp;
+
+      if (debug_args)
+       for (ix = 1; VEC_iterate (tree, *debug_args, ix, dtemp); ix += 2)
+         {
+           gcc_assert (TREE_CODE (dtemp) == DEBUG_EXPR_DECL);
+           expand_debug_expr (dtemp);
+         }
+    }
+
   lhs = gimple_call_lhs (stmt);
   if (lhs)
     expand_assignment (lhs, exp, false);
@@ -3297,6 +3314,120 @@ expand_debug_expr (tree exp)
     }
 }
 
+/* Return an RTX equivalent to the source bind value of the tree expression
+   EXP.  */
+
+static rtx
+expand_debug_source_expr (tree exp)
+{
+  rtx op0 = NULL_RTX;
+  enum machine_mode mode = VOIDmode, inner_mode;
+
+  switch (TREE_CODE (exp))
+    {
+    case PARM_DECL:
+      {
+       rtx incoming = DECL_INCOMING_RTL (exp);
+       mode = DECL_MODE (exp);
+       if (incoming
+           && GET_MODE (incoming) != BLKmode
+           && ((REG_P (incoming) && HARD_REGISTER_P (incoming))
+               || (MEM_P (incoming)
+                   && REG_P (XEXP (incoming, 0))
+                   && HARD_REGISTER_P (XEXP (incoming, 0)))))
+         {
+           op0 = gen_rtx_ENTRY_VALUE (GET_MODE (incoming));
+           ENTRY_VALUE_EXP (op0) = incoming;
+           break;
+         }
+       if (incoming
+           && MEM_P (incoming)
+           && !TREE_ADDRESSABLE (exp)
+           && GET_MODE (incoming) != BLKmode
+           && (XEXP (incoming, 0) == virtual_incoming_args_rtx
+               || (GET_CODE (XEXP (incoming, 0)) == PLUS
+                   && XEXP (XEXP (incoming, 0), 0)
+                      == virtual_incoming_args_rtx
+                   && CONST_INT_P (XEXP (XEXP (incoming, 0), 1)))))
+         {
+           op0 = incoming;
+           break;
+         }
+       /* See if this isn't an argument that has been completely
+          optimized out.  */
+       if (!DECL_RTL_SET_P (exp)
+           && incoming == NULL_RTX
+           && DECL_ABSTRACT_ORIGIN (current_function_decl))
+         {
+           tree aexp = exp;
+           if (DECL_ABSTRACT_ORIGIN (exp))
+             aexp = DECL_ABSTRACT_ORIGIN (exp);
+           if (DECL_CONTEXT (aexp)
+               == DECL_ABSTRACT_ORIGIN (current_function_decl))
+             {
+               VEC(tree, gc) **debug_args;
+               unsigned int ix;
+               tree ddecl;
+#ifdef ENABLE_CHECKING
+               tree parm;
+               for (parm = DECL_ARGUMENTS (current_function_decl);
+                    parm; parm = DECL_CHAIN (parm))
+                 gcc_assert (parm != exp
+                             && DECL_ABSTRACT_ORIGIN (parm) != aexp);
+#endif
+               debug_args = decl_debug_args_lookup (current_function_decl);
+               if (debug_args != NULL)
+                 {
+                   for (ix = 0; VEC_iterate (tree, *debug_args, ix, ddecl);
+                        ix += 2)
+                     if (ddecl == aexp)
+                       return gen_rtx_DEBUG_PARAMETER_REF (mode, aexp);
+                 }
+             }
+         }
+       break;
+      }
+    default:
+      break;
+    }
+
+  if (op0 == NULL_RTX)
+    return NULL_RTX;
+
+  inner_mode = GET_MODE (op0);
+  if (mode == inner_mode)
+    return op0;
+
+  if (FLOAT_MODE_P (mode) && FLOAT_MODE_P (inner_mode))
+    {
+      if (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (inner_mode))
+       op0 = simplify_gen_subreg (mode, op0, inner_mode, 0);
+      else if (GET_MODE_BITSIZE (mode) < GET_MODE_BITSIZE (inner_mode))
+       op0 = simplify_gen_unary (FLOAT_TRUNCATE, mode, op0, inner_mode);
+      else
+       op0 = simplify_gen_unary (FLOAT_EXTEND, mode, op0, inner_mode);
+    }
+  else if (FLOAT_MODE_P (mode))
+    gcc_unreachable ();
+  else if (FLOAT_MODE_P (inner_mode))
+    {
+      if (TYPE_UNSIGNED (TREE_TYPE (exp)))
+       op0 = simplify_gen_unary (UNSIGNED_FIX, mode, op0, inner_mode);
+      else
+       op0 = simplify_gen_unary (FIX, mode, op0, inner_mode);
+    }
+  else if (CONSTANT_P (op0)
+          || GET_MODE_BITSIZE (mode) <= GET_MODE_BITSIZE (inner_mode))
+    op0 = simplify_gen_subreg (mode, op0, inner_mode,
+                              subreg_lowpart_offset (mode, inner_mode));
+  else if (TYPE_UNSIGNED (TREE_TYPE (exp)))
+    op0 = simplify_gen_unary (ZERO_EXTEND, mode, op0, inner_mode);
+  else
+    op0 = simplify_gen_unary (SIGN_EXTEND, mode, op0, inner_mode);
+
+  return op0;
+}
+
 /* Expand the _LOCs in debug insns.  We run this after expanding all
    regular insns, so that any variables referenced in the function
    will have their DECL_RTLs set.  */
@@ -3324,7 +3455,11 @@ expand_debug_locations (void)
          val = NULL_RTX;
        else
          {
-           val = expand_debug_expr (value);
+           if (INSN_VAR_LOCATION_STATUS (insn)
+               == VAR_INIT_STATUS_UNINITIALIZED)
+             val = expand_debug_source_expr (value);
+           else
+             val = expand_debug_expr (value);
            gcc_assert (last == get_last_insn ());
          }
 
@@ -3603,6 +3738,39 @@ expand_gimple_basic_block (basic_block bb)
                break;
            }
 
+         set_curr_insn_source_location (sloc);
+         set_curr_insn_block (sblock);
+       }
+      else if (gimple_debug_source_bind_p (stmt))
+       {
+         location_t sloc = get_curr_insn_source_location ();
+         tree sblock = get_curr_insn_block ();
+         tree var = gimple_debug_source_bind_get_var (stmt);
+         tree value = gimple_debug_source_bind_get_value (stmt);
+         rtx val;
+         enum machine_mode mode;
+
+         last = get_last_insn ();
+
+         set_curr_insn_source_location (gimple_location (stmt));
+         set_curr_insn_block (gimple_block (stmt));
+
+         mode = DECL_MODE (var);
+
+         val = gen_rtx_VAR_LOCATION (mode, var, (rtx)value,
+                                     VAR_INIT_STATUS_UNINITIALIZED);
+
+         emit_debug_insn (val);
+
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             /* We can't dump the insn with a TREE where an RTX
+                is expected.  */
+             PAT_VAR_LOCATION_LOC (val) = const0_rtx;
+             maybe_dump_rtl_for_gimple_stmt (stmt, last);
+             PAT_VAR_LOCATION_LOC (val) = (rtx)value;
+           }
+
          set_curr_insn_source_location (sloc);
          set_curr_insn_block (sblock);
        }
index e0697ecfca831ec967bbc613007a2e2d9a75d693..e575aff72fd8320dceffd96a098e9f082d117a3b 100644 (file)
@@ -812,6 +812,10 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, enum machine_mode memmode)
       return DEBUG_IMPLICIT_PTR_DECL (x)
             == DEBUG_IMPLICIT_PTR_DECL (y);
 
+    case DEBUG_PARAMETER_REF:
+      return DEBUG_PARAMETER_REF_DECL (x)
+            == DEBUG_PARAMETER_REF_DECL (y);
+
     case ENTRY_VALUE:
       /* ENTRY_VALUEs are function invariant, it is thus undesirable to
         use rtx_equal_for_cselib_1 to compare the operands.  */
@@ -963,6 +967,11 @@ cselib_hash_rtx (rtx x, int create, enum machine_mode memmode)
              + DECL_UID (DEBUG_IMPLICIT_PTR_DECL (x));
       return hash ? hash : (unsigned int) DEBUG_IMPLICIT_PTR;
 
+    case DEBUG_PARAMETER_REF:
+      hash += ((unsigned) DEBUG_PARAMETER_REF << 7)
+             + DECL_UID (DEBUG_PARAMETER_REF_DECL (x));
+      return hash ? hash : (unsigned int) DEBUG_PARAMETER_REF;
+
     case ENTRY_VALUE:
       /* ENTRY_VALUEs are function invariant, thus try to avoid
         recursing on argument if ENTRY_VALUE is one of the
index 480e4e06e77e23d903d849b3cf4fc4f9d302c712..6d536205dea36c68e50ef318eccd80a0955292bc 100644 (file)
@@ -4811,6 +4811,8 @@ dwarf_stack_op_name (unsigned int op)
       return "DW_OP_GNU_convert";
     case DW_OP_GNU_reinterpret:
       return "DW_OP_GNU_reinterpret";
+    case DW_OP_GNU_parameter_ref:
+      return "DW_OP_GNU_parameter_ref";
 
     default:
       return "OP_<unknown>";
@@ -5085,6 +5087,10 @@ size_of_loc_descr (dw_loc_descr_ref loc)
          = get_base_type_offset (loc->dw_loc_oprnd1.v.val_die_ref.die);
        size += size_of_uleb128 (o);
       }
+      break;
+    case DW_OP_GNU_parameter_ref:
+      size += 4;
+      break;
     default:
       break;
     }
@@ -5122,6 +5128,7 @@ size_of_locs (dw_loc_descr_ref loc)
 
 static HOST_WIDE_INT extract_int (const unsigned char *, unsigned);
 static void get_ref_die_offset_label (char *, dw_die_ref);
+static unsigned long int get_ref_die_offset (dw_die_ref);
 static void output_loc_sequence (dw_loc_descr_ref, int);
 
 /* Output location description stack opcode's operands (if any).
@@ -5467,6 +5474,15 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
       }
       break;
 
+    case DW_OP_GNU_parameter_ref:
+      {
+       unsigned long o;
+       gcc_assert (val1->val_class == dw_val_class_die_ref);
+       o = get_ref_die_offset (val1->v.val_die_ref.die);
+       dw2_asm_output_data (4, o, NULL);
+      }
+      break;
+
     default:
       /* Other codes have no operands.  */
       break;
@@ -5649,6 +5665,7 @@ output_loc_operands_raw (dw_loc_descr_ref loc)
     case DW_OP_GNU_deref_type:
     case DW_OP_GNU_convert:
     case DW_OP_GNU_reinterpret:
+    case DW_OP_GNU_parameter_ref:
       gcc_unreachable ();
       break;
 
@@ -6965,6 +6982,15 @@ get_base_type_offset (dw_die_ref ref)
   return ref->die_offset;
 }
 
+/* Return die_offset of a DIE reference other than base type.  */
+
+static unsigned long int
+get_ref_die_offset (dw_die_ref ref)
+{
+  gcc_assert (ref->die_offset);
+  return ref->die_offset;
+}
+
 /* Convert a DIE tag into its string name.  */
 
 static const char *
@@ -14507,6 +14533,34 @@ rotate_loc_descriptor (rtx rtl, enum machine_mode mode,
   return ret;
 }
 
+/* Helper function for mem_loc_descriptor.  Return DW_OP_GNU_parameter_ref
+   for DEBUG_PARAMETER_REF RTL.  */
+
+static dw_loc_descr_ref
+parameter_ref_descriptor (rtx rtl)
+{
+  dw_loc_descr_ref ret;
+  dw_die_ref ref;
+
+  if (dwarf_strict)
+    return NULL;
+  gcc_assert (TREE_CODE (DEBUG_PARAMETER_REF_DECL (rtl)) == PARM_DECL);
+  ref = lookup_decl_die (DEBUG_PARAMETER_REF_DECL (rtl));
+  ret = new_loc_descr (DW_OP_GNU_parameter_ref, 0, 0);
+  if (ref)
+    {
+      ret->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+      ret->dw_loc_oprnd1.v.val_die_ref.die = ref;
+      ret->dw_loc_oprnd1.v.val_die_ref.external = 0;
+    }
+  else
+    {
+      ret->dw_loc_oprnd1.val_class = dw_val_class_decl_ref;
+      ret->dw_loc_oprnd1.v.val_decl_ref = DEBUG_PARAMETER_REF_DECL (rtl);
+    }
+  return ret;
+}
+
 /* The following routine converts the RTL for a variable or parameter
    (resident in memory) into an equivalent Dwarf representation of a
    mechanism for getting the address of that same variable onto the top of a
@@ -14853,7 +14907,11 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
       mem_loc_result = new_loc_descr (DW_OP_GNU_entry_value, 0, 0);
       mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_loc;
       mem_loc_result->dw_loc_oprnd1.v.val_loc = op0;
-      return mem_loc_result;
+      break;
+
+    case DEBUG_PARAMETER_REF:
+      mem_loc_result = parameter_ref_descriptor (rtl);
+      break;
 
     case PRE_MODIFY:
       /* Extract the PLUS expression nested inside and fall into
@@ -20571,7 +20629,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                {
                  dw_loc_descr_ref reg, val;
                  enum machine_mode mode = GET_MODE (XEXP (XEXP (arg, 0), 1));
-                 dw_die_ref cdie;
+                 dw_die_ref cdie, tdie = NULL;
 
                  next_arg = XEXP (arg, 1);
                  if (REG_P (XEXP (XEXP (arg, 0), 0))
@@ -20602,6 +20660,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                      tlocc = XEXP (XEXP (arg, 0), 1);
                      continue;
                    }
+                 reg = NULL;
                  if (REG_P (XEXP (XEXP (arg, 0), 0)))
                    reg = reg_loc_descriptor (XEXP (XEXP (arg, 0), 0),
                                              VAR_INIT_STATUS_INITIALIZED);
@@ -20613,9 +20672,20 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                                                GET_MODE (mem),
                                                VAR_INIT_STATUS_INITIALIZED);
                    }
+                 else if (GET_CODE (XEXP (XEXP (arg, 0), 0))
+                          == DEBUG_PARAMETER_REF)
+                   {
+                     tree tdecl
+                       = DEBUG_PARAMETER_REF_DECL (XEXP (XEXP (arg, 0), 0));
+                     tdie = lookup_decl_die (tdecl);
+                     if (tdie == NULL)
+                       continue;
+                   }
                  else
                    continue;
-                 if (reg == NULL)
+                 if (reg == NULL
+                     && GET_CODE (XEXP (XEXP (arg, 0), 0))
+                        != DEBUG_PARAMETER_REF)
                    continue;
                  val = mem_loc_descriptor (XEXP (XEXP (arg, 0), 1), mode,
                                            VOIDmode,
@@ -20625,8 +20695,11 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                  if (die == NULL)
                    die = gen_call_site_die (decl, subr_die, ca_loc);
                  cdie = new_die (DW_TAG_GNU_call_site_parameter, die,
-                                 NULL_TREE);           
-                 add_AT_loc (cdie, DW_AT_location, reg);
+                                 NULL_TREE);
+                 if (reg != NULL)
+                   add_AT_loc (cdie, DW_AT_location, reg);
+                 else if (tdie != NULL)
+                   add_AT_die_ref (cdie, DW_AT_abstract_origin, tdie);
                  add_AT_loc (cdie, DW_AT_GNU_call_site_value, val);
                  if (next_arg != XEXP (arg, 1))
                    {
@@ -24208,6 +24281,7 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
          return false;
        break;
       case DW_OP_GNU_implicit_pointer:
+      case DW_OP_GNU_parameter_ref:
        if (loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref)
          {
            dw_die_ref ref
@@ -24748,6 +24822,10 @@ compare_loc_operands (dw_loc_descr_ref x, dw_loc_descr_ref y)
     case DW_OP_GNU_convert:
     case DW_OP_GNU_reinterpret:
       return valx1->v.val_die_ref.die == valy1->v.val_die_ref.die;
+    case DW_OP_GNU_parameter_ref:
+      return valx1->val_class == dw_val_class_die_ref
+            && valx1->val_class == valy1->val_class
+            && valx1->v.val_die_ref.die == valy1->v.val_die_ref.die;
     default:
       /* Other codes have no operands.  */
       return true;
index b27b1a5b0613f965bcbe6242aac10c3b471f92f0..eaf3e5fa995fcd045c77025a6adefaa63ad18710 100644 (file)
@@ -1,6 +1,6 @@
 /* Pretty formatting of GIMPLE statements and expressions.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011  Free Software Foundation, Inc.
    Contributed by Aldy Hernandez <aldyh@redhat.com> and
    Diego Novillo <dnovillo@google.com>
 
@@ -966,6 +966,17 @@ dump_gimple_debug (pretty_printer *buffer, gimple gs, int spc, int flags)
                         gimple_debug_bind_get_value (gs));
       break;
 
+    case GIMPLE_DEBUG_SOURCE_BIND:
+      if (flags & TDF_RAW)
+       dump_gimple_fmt (buffer, spc, flags, "%G SRCBIND <%T, %T>", gs,
+                        gimple_debug_source_bind_get_var (gs),
+                        gimple_debug_source_bind_get_value (gs));
+      else
+       dump_gimple_fmt (buffer, spc, flags, "# DEBUG %T s=> %T",
+                        gimple_debug_source_bind_get_var (gs),
+                        gimple_debug_source_bind_get_value (gs));
+      break;
+
     default:
       gcc_unreachable ();
     }
index fd9757908f06d36ac88c277e0137643c570eb60c..e3095d7e261916cc8c00a30ae068878634bb6b17 100644 (file)
@@ -1,6 +1,6 @@
 /* Gimple IR support functions.
 
-   Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
    Contributed by Aldy Hernandez <aldyh@redhat.com>
 
 This file is part of GCC.
@@ -866,6 +866,30 @@ gimple_build_debug_bind_stat (tree var, tree value, gimple stmt MEM_STAT_DECL)
 }
 
 
+/* Build a new GIMPLE_DEBUG_SOURCE_BIND statement.
+
+   VAR is bound to VALUE; block and location are taken from STMT.  */
+
+gimple
+gimple_build_debug_source_bind_stat (tree var, tree value,
+                                    gimple stmt MEM_STAT_DECL)
+{
+  gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG,
+                                        (unsigned)GIMPLE_DEBUG_SOURCE_BIND, 2
+                                        PASS_MEM_STAT);
+
+  gimple_debug_source_bind_set_var (p, var);
+  gimple_debug_source_bind_set_value (p, value);
+  if (stmt)
+    {
+      gimple_set_block (p, gimple_block (stmt));
+      gimple_set_location (p, gimple_location (stmt));
+    }
+
+  return p;
+}
+
+
 /* Build a GIMPLE_OMP_CRITICAL statement.
 
    BODY is the sequence of statements for which only one thread can execute.
index 7d97adbe7adfcc0e00221c6b6c994183f04acf8b..184c9733ee5900798ed23d568b7ac17db3147bee 100644 (file)
@@ -1,6 +1,6 @@
 /* Gimple IR definitions.
 
-   Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
    Contributed by Aldy Hernandez <aldyh@redhat.com>
 
 This file is part of GCC.
@@ -117,12 +117,13 @@ enum gf_mask {
     GF_PREDICT_TAKEN           = 1 << 15
 };
 
-/* Currently, there's only one type of gimple debug stmt.  Others are
+/* Currently, there are only two types of gimple debug stmt.  Others are
    envisioned, for example, to enable the generation of is_stmt notes
    in line number information, to mark sequence points, etc.  This
    subcode is to be used to tell them apart.  */
 enum gimple_debug_subcode {
-  GIMPLE_DEBUG_BIND = 0
+  GIMPLE_DEBUG_BIND = 0,
+  GIMPLE_DEBUG_SOURCE_BIND = 1
 };
 
 /* Masks for selecting a pass local flag (PLF) to work on.  These
@@ -823,6 +824,9 @@ gimple gimple_build_assign_with_ops_stat (enum tree_code, tree, tree,
 gimple gimple_build_debug_bind_stat (tree, tree, gimple MEM_STAT_DECL);
 #define gimple_build_debug_bind(var,val,stmt)                  \
   gimple_build_debug_bind_stat ((var), (val), (stmt) MEM_STAT_INFO)
+gimple gimple_build_debug_source_bind_stat (tree, tree, gimple MEM_STAT_DECL);
+#define gimple_build_debug_source_bind(var,val,stmt)                   \
+  gimple_build_debug_source_bind_stat ((var), (val), (stmt) MEM_STAT_INFO)
 
 gimple gimple_build_call_vec (tree, VEC(tree, heap) *);
 gimple gimple_build_call (tree, unsigned, ...);
@@ -3583,6 +3587,70 @@ gimple_debug_bind_has_value_p (gimple dbg)
 
 #undef GIMPLE_DEBUG_BIND_NOVALUE
 
+/* Return true if S is a GIMPLE_DEBUG SOURCE BIND statement.  */
+
+static inline bool
+gimple_debug_source_bind_p (const_gimple s)
+{
+  if (is_gimple_debug (s))
+    return s->gsbase.subcode == GIMPLE_DEBUG_SOURCE_BIND;
+
+  return false;
+}
+
+/* Return the variable bound in a GIMPLE_DEBUG source bind statement.  */
+
+static inline tree
+gimple_debug_source_bind_get_var (gimple dbg)
+{
+  GIMPLE_CHECK (dbg, GIMPLE_DEBUG);
+  gcc_gimple_checking_assert (gimple_debug_source_bind_p (dbg));
+  return gimple_op (dbg, 0);
+}
+
+/* Return the value bound to the variable in a GIMPLE_DEBUG source bind
+   statement.  */
+
+static inline tree
+gimple_debug_source_bind_get_value (gimple dbg)
+{
+  GIMPLE_CHECK (dbg, GIMPLE_DEBUG);
+  gcc_gimple_checking_assert (gimple_debug_source_bind_p (dbg));
+  return gimple_op (dbg, 1);
+}
+
+/* Return a pointer to the value bound to the variable in a
+   GIMPLE_DEBUG source bind statement.  */
+
+static inline tree *
+gimple_debug_source_bind_get_value_ptr (gimple dbg)
+{
+  GIMPLE_CHECK (dbg, GIMPLE_DEBUG);
+  gcc_gimple_checking_assert (gimple_debug_source_bind_p (dbg));
+  return gimple_op_ptr (dbg, 1);
+}
+
+/* Set the variable bound in a GIMPLE_DEBUG source bind statement.  */
+
+static inline void
+gimple_debug_source_bind_set_var (gimple dbg, tree var)
+{
+  GIMPLE_CHECK (dbg, GIMPLE_DEBUG);
+  gcc_gimple_checking_assert (gimple_debug_source_bind_p (dbg));
+  gimple_set_op (dbg, 0, var);
+}
+
+/* Set the value bound to the variable in a GIMPLE_DEBUG source bind
+   statement.  */
+
+static inline void
+gimple_debug_source_bind_set_value (gimple dbg, tree value)
+{
+  GIMPLE_CHECK (dbg, GIMPLE_DEBUG);
+  gcc_gimple_checking_assert (gimple_debug_source_bind_p (dbg));
+  gimple_set_op (dbg, 1, value);
+}
+
 /* Return the body for the OMP statement GS.  */
 
 static inline gimple_seq
index 10c11d41ae63c8dc2af1ad50abce011afc3434d6..aec1920c62ebe3c9fda375a038a6271c85ad121c 100644 (file)
@@ -1,5 +1,5 @@
 /* Interprocedural analyses.
-   Copyright (C) 2005, 2007, 2008, 2009, 2010
+   Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -2393,6 +2393,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
                           ipa_parm_adjustment_vec adjustments)
 {
   VEC(tree, heap) *vargs;
+  VEC(tree, gc) **debug_args = NULL;
   gimple new_stmt;
   gimple_stmt_iterator gsi;
   tree callee_decl;
@@ -2400,6 +2401,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
 
   len = VEC_length (ipa_parm_adjustment_t, adjustments);
   vargs = VEC_alloc (tree, heap, len);
+  callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl;
 
   gsi = gsi_for_stmt (stmt);
   for (i = 0; i < len; i++)
@@ -2490,6 +2492,42 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
                                           NULL, true, GSI_SAME_STMT);
          VEC_quick_push (tree, vargs, expr);
        }
+      if (!adj->copy_param && MAY_HAVE_DEBUG_STMTS)
+       {
+         unsigned int ix;
+         tree ddecl = NULL_TREE, origin = DECL_ORIGIN (adj->base), arg;
+         gimple def_temp;
+
+         arg = gimple_call_arg (stmt, adj->base_index);
+         if (!useless_type_conversion_p (TREE_TYPE (origin), TREE_TYPE (arg)))
+           {
+             if (!fold_convertible_p (TREE_TYPE (origin), arg))
+               continue;
+             arg = fold_convert_loc (gimple_location (stmt),
+                                     TREE_TYPE (origin), arg);
+           }
+         if (debug_args == NULL)
+           debug_args = decl_debug_args_insert (callee_decl);
+         for (ix = 0; VEC_iterate (tree, *debug_args, ix, ddecl); ix += 2)
+           if (ddecl == origin)
+             {
+               ddecl = VEC_index (tree, *debug_args, ix + 1);
+               break;
+             }
+         if (ddecl == NULL)
+           {
+             ddecl = make_node (DEBUG_EXPR_DECL);
+             DECL_ARTIFICIAL (ddecl) = 1;
+             TREE_TYPE (ddecl) = TREE_TYPE (origin);
+             DECL_MODE (ddecl) = DECL_MODE (origin);
+
+             VEC_safe_push (tree, gc, *debug_args, origin);
+             VEC_safe_push (tree, gc, *debug_args, ddecl);
+           }
+         def_temp = gimple_build_debug_bind (ddecl, unshare_expr (arg),
+                                             stmt);
+         gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
+       }
     }
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2498,7 +2536,6 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
       print_gimple_stmt (dump_file, gsi_stmt (gsi), 0, 0);
     }
 
-  callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl;
   new_stmt = gimple_build_call_vec (callee_decl, vargs);
   VEC_free (tree, heap, vargs);
   if (gimple_call_lhs (stmt))
index a0f9dfb5bee62f9c7e88e8b5c2b0267e1ea7d0a0..c20ff6c0c5f133e2643042db371eeec6c85a606a 100644 (file)
@@ -552,6 +552,8 @@ print_rtx (const_rtx in_rtx)
 #ifndef GENERATOR_FILE
        if (i == 0 && GET_CODE (in_rtx) == DEBUG_IMPLICIT_PTR)
          print_mem_expr (outfile, DEBUG_IMPLICIT_PTR_DECL (in_rtx));
+       else if (i == 0 && GET_CODE (in_rtx) == DEBUG_PARAMETER_REF)
+         print_mem_expr (outfile, DEBUG_PARAMETER_REF_DECL (in_rtx));
        else
          dump_addr (outfile, " ", XTREE (in_rtx, i));
 #endif
index e335a39b241ecf98383557a66636abe9b0e725e4..52e9e9ce3a89b258d85b4625819bbd328c273cca 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -413,6 +413,10 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
       return DEBUG_IMPLICIT_PTR_DECL (x)
             == DEBUG_IMPLICIT_PTR_DECL (y);
 
+    case DEBUG_PARAMETER_REF:
+      return DEBUG_PARAMETER_REF_DECL (x)
+            == DEBUG_PARAMETER_REF_DECL (x);
+
     case ENTRY_VALUE:
       return rtx_equal_p_cb (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y), cb);
 
@@ -548,6 +552,10 @@ rtx_equal_p (const_rtx x, const_rtx y)
       return DEBUG_IMPLICIT_PTR_DECL (x)
             == DEBUG_IMPLICIT_PTR_DECL (y);
 
+    case DEBUG_PARAMETER_REF:
+      return DEBUG_PARAMETER_REF_DECL (x)
+            == DEBUG_PARAMETER_REF_DECL (y);
+
     case ENTRY_VALUE:
       return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y));
 
@@ -660,6 +668,7 @@ iterative_hash_rtx (const_rtx x, hashval_t hash)
     case CONST_DOUBLE:
     case CONST_FIXED:
     case DEBUG_IMPLICIT_PTR:
+    case DEBUG_PARAMETER_REF:
       return hash;
     default:
       break;
index 8f04b2fe3cd2ff360c658f557016509ce781709e..a7de8f7b4aadb3892058736b4140944e3fe92da4 100644 (file)
@@ -727,6 +727,10 @@ DEF_RTL_EXPR(DEBUG_IMPLICIT_PTR, "debug_implicit_ptr", "t", RTX_OBJ)
    parameter.  */
 DEF_RTL_EXPR(ENTRY_VALUE, "entry_value", "0", RTX_OBJ)
 
+/* Used in VAR_LOCATION for a reference to a parameter that has
+   been optimized away completely.  */
+DEF_RTL_EXPR(DEBUG_PARAMETER_REF, "debug_parameter_ref", "t", RTX_OBJ)
+
 /* All expressions from this point forward appear only in machine
    descriptions.  */
 #ifdef GENERATOR_FILE
index f2c298397c6138169196428ffc4fd9c23c1df9d6..da18788a292fb3bca6c9964cdd557d66d983a72f 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -941,6 +941,9 @@ extern const char * const reg_note_name[];
 /* VAR_DECL/PARM_DECL DEBUG_IMPLICIT_PTR takes address of.  */
 #define DEBUG_IMPLICIT_PTR_DECL(RTX) XCTREE (RTX, 0, DEBUG_IMPLICIT_PTR)
 
+/* PARM_DECL DEBUG_PARAMETER_REF references.  */
+#define DEBUG_PARAMETER_REF_DECL(RTX) XCTREE (RTX, 0, DEBUG_PARAMETER_REF)
+
 /* Possible initialization status of a variable.   When requested
    by the user, this information is tracked and recorded in the DWARF
    debug information, along with the variable's location.  */
index 3ce83b9f7c1ae4c97717b614a69ead240da4d428..a03cbc9a0bdab3737a7eb0af1f6dec2082876938 100644 (file)
@@ -1,5 +1,5 @@
 /* Single entry single exit control flow regions.
-   Copyright (C) 2008, 2009, 2010
+   Copyright (C) 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Jan Sjodin <jan.sjodin@amd.com> and
    Sebastian Pop <sebastian.pop@amd.com>.
@@ -472,6 +472,8 @@ rename_uses (gimple copy, htab_t rename_map, gimple_stmt_iterator *gsi_tgt,
     {
       if (gimple_debug_bind_p (copy))
        gimple_debug_bind_reset_value (copy);
+      else if (gimple_debug_source_bind_p (copy))
+       return false;
       else
        gcc_unreachable ();
 
index c8b9f4c19da34c728185d8e19869f3fc8de5b527..6a8eae8694507cac0be500d98a857054326fea11 100644 (file)
@@ -1,5 +1,5 @@
 /* Tree inlining.
-   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Alexandre Oliva <aoliva@redhat.com>
 
@@ -188,6 +188,33 @@ remap_ssa_name (tree name, copy_body_data *id)
 
   if (processing_debug_stmt)
     {
+      if (TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL
+         && SSA_NAME_IS_DEFAULT_DEF (name)
+         && id->entry_bb == NULL
+         && single_succ_p (ENTRY_BLOCK_PTR))
+       {
+         tree vexpr = make_node (DEBUG_EXPR_DECL);
+         gimple def_temp;
+         gimple_stmt_iterator gsi;
+         tree val = SSA_NAME_VAR (name);
+
+         n = (tree *) pointer_map_contains (id->decl_map, val);
+         if (n != NULL)
+           val = *n;
+         if (TREE_CODE (val) != PARM_DECL)
+           {
+             processing_debug_stmt = -1;
+             return name;
+           }
+         def_temp = gimple_build_debug_source_bind (vexpr, val, NULL);
+         DECL_ARTIFICIAL (vexpr) = 1;
+         TREE_TYPE (vexpr) = TREE_TYPE (name);
+         DECL_MODE (vexpr) = DECL_MODE (SSA_NAME_VAR (name));
+         gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
+         gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
+         return vexpr;
+       }
+
       processing_debug_stmt = -1;
       return name;
     }
@@ -1403,6 +1430,14 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
          VEC_safe_push (gimple, heap, id->debug_stmts, copy);
          return copy;
        }
+      if (gimple_debug_source_bind_p (stmt))
+       {
+         copy = gimple_build_debug_source_bind
+                  (gimple_debug_source_bind_get_var (stmt),
+                   gimple_debug_source_bind_get_value (stmt), stmt);
+         VEC_safe_push (gimple, heap, id->debug_stmts, copy);
+         return copy;
+       }
 
       /* Create a new deep copy of the statement.  */
       copy = gimple_copy (stmt);
@@ -1478,7 +1513,7 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
 
   gimple_set_block (copy, new_block);
 
-  if (gimple_debug_bind_p (copy))
+  if (gimple_debug_bind_p (copy) || gimple_debug_source_bind_p (copy))
     return copy;
 
   /* Remap all the operands in COPY.  */
@@ -2151,22 +2186,33 @@ maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb)
            {
              si = ssi;
              gsi_prev (&ssi);
-             if (!single_pred_p (e->dest))
+             if (!single_pred_p (e->dest) && gimple_debug_bind_p (stmt))
                gimple_debug_bind_reset_value (stmt);
              gsi_remove (&si, false);
              gsi_insert_before (&dsi, stmt, GSI_SAME_STMT);
              continue;
            }
 
-         var = gimple_debug_bind_get_var (stmt);
-         if (single_pred_p (e->dest))
+         if (gimple_debug_bind_p (stmt))
            {
-             value = gimple_debug_bind_get_value (stmt);
-             value = unshare_expr (value);
+             var = gimple_debug_bind_get_var (stmt);
+             if (single_pred_p (e->dest))
+               {
+                 value = gimple_debug_bind_get_value (stmt);
+                 value = unshare_expr (value);
+               }
+             else
+               value = NULL_TREE;
+             new_stmt = gimple_build_debug_bind (var, value, stmt);
+           }
+         else if (gimple_debug_source_bind_p (stmt))
+           {
+             var = gimple_debug_source_bind_get_var (stmt);
+             value = gimple_debug_source_bind_get_value (stmt);
+             new_stmt = gimple_build_debug_source_bind (var, value, stmt);
            }
          else
-           value = NULL_TREE;
-         new_stmt = gimple_build_debug_bind (var, value, stmt);
+           gcc_unreachable ();
          gsi_insert_before (&dsi, new_stmt, GSI_SAME_STMT);
          VEC_safe_push (gimple, heap, id->debug_stmts, new_stmt);
          gsi_prev (&ssi);
@@ -2317,7 +2363,6 @@ copy_debug_stmt (gimple stmt, copy_body_data *id)
   t = id->block;
   if (gimple_block (stmt))
     {
-      tree *n;
       n = (tree *) pointer_map_contains (id->decl_map, gimple_block (stmt));
       if (n)
        t = *n;
@@ -2330,7 +2375,10 @@ copy_debug_stmt (gimple stmt, copy_body_data *id)
 
   processing_debug_stmt = 1;
 
-  t = gimple_debug_bind_get_var (stmt);
+  if (gimple_debug_source_bind_p (stmt))
+    t = gimple_debug_source_bind_get_var (stmt);
+  else
+    t = gimple_debug_bind_get_var (stmt);
 
   if (TREE_CODE (t) == PARM_DECL && id->debug_map
       && (n = (tree *) pointer_map_contains (id->debug_map, t)))
@@ -2347,15 +2395,24 @@ copy_debug_stmt (gimple stmt, copy_body_data *id)
   else
     walk_tree (&t, remap_gimple_op_r, &wi, NULL);
 
-  gimple_debug_bind_set_var (stmt, t);
+  if (gimple_debug_bind_p (stmt))
+    {
+      gimple_debug_bind_set_var (stmt, t);
 
-  if (gimple_debug_bind_has_value_p (stmt))
-    walk_tree (gimple_debug_bind_get_value_ptr (stmt),
-              remap_gimple_op_r, &wi, NULL);
+      if (gimple_debug_bind_has_value_p (stmt))
+       walk_tree (gimple_debug_bind_get_value_ptr (stmt),
+                  remap_gimple_op_r, &wi, NULL);
 
-  /* Punt if any decl couldn't be remapped.  */
-  if (processing_debug_stmt < 0)
-    gimple_debug_bind_reset_value (stmt);
+      /* Punt if any decl couldn't be remapped.  */
+      if (processing_debug_stmt < 0)
+       gimple_debug_bind_reset_value (stmt);
+    }
+  else if (gimple_debug_source_bind_p (stmt))
+    {
+      gimple_debug_source_bind_set_var (stmt, t);
+      walk_tree (gimple_debug_source_bind_get_value_ptr (stmt),
+                remap_gimple_op_r, &wi, NULL);
+    }
 
   processing_debug_stmt = 0;
 
@@ -5001,6 +5058,20 @@ tree_function_versioning (tree old_decl, tree new_decl,
   new_version_node = cgraph_get_node (new_decl);
   gcc_checking_assert (new_version_node);
 
+  /* Copy over debug args.  */
+  if (DECL_HAS_DEBUG_ARGS_P (old_decl))
+    {
+      VEC(tree, gc) **new_debug_args, **old_debug_args;
+      gcc_checking_assert (decl_debug_args_lookup (new_decl) == NULL);
+      DECL_HAS_DEBUG_ARGS_P (new_decl) = 0;
+      old_debug_args = decl_debug_args_lookup (old_decl);
+      if (old_debug_args)
+       {
+         new_debug_args = decl_debug_args_insert (new_decl);
+         *new_debug_args = VEC_copy (tree, gc, *old_debug_args);
+       }
+    }
+
   /* Output the inlining info for this abstract function, since it has been
      inlined.  If we don't do this now, we can lose the information about the
      variables in the function when the blocks get blown away as soon as we
index f138e5b72c9e6c039de24ec6cfe20937b643aa5d..0db9085f0530b66eba8c4d13d916e1920653aa84 100644 (file)
@@ -1,5 +1,5 @@
 /* Rewrite a program in Normal form into SSA.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
@@ -745,7 +745,17 @@ mark_def_sites (basic_block bb, gimple stmt, bitmap kills)
   set_rewrite_uses (stmt, false);
 
   if (is_gimple_debug (stmt))
-    return;
+    {
+      FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+       {
+         tree sym = USE_FROM_PTR (use_p);
+         gcc_assert (DECL_P (sym));
+         set_rewrite_uses (stmt, true);
+       }
+      if (rewrite_uses_p (stmt))
+       SET_BIT (interesting_blocks, bb->index);
+      return;
+    }
 
   /* If a variable is used before being set, then the variable is live
      across a block boundary, so mark it live-on-entry to BB.  */
@@ -1279,6 +1289,73 @@ get_reaching_def (tree var)
 }
 
 
+/* Helper function for rewrite_stmt.  Rewrite uses in a debug stmt.  */
+
+static void
+rewrite_debug_stmt_uses (gimple stmt)
+{
+  use_operand_p use_p;
+  ssa_op_iter iter;
+  bool update = false;
+
+  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+    {
+      tree var = USE_FROM_PTR (use_p), def = NULL_TREE;
+      gcc_assert (DECL_P (var));
+      if (var_ann (var) == NULL)
+       {
+         if (TREE_CODE (var) == PARM_DECL && single_succ_p (ENTRY_BLOCK_PTR))
+           {
+             gimple_stmt_iterator gsi
+               = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
+             int lim;
+             /* Search a few source bind stmts at the start of first bb to
+                see if a DEBUG_EXPR_DECL can't be reused.  */
+             for (lim = 32;
+                  !gsi_end_p (gsi) && lim > 0;
+                  gsi_next (&gsi), lim--)
+               {
+                 gimple gstmt = gsi_stmt (gsi);
+                 if (!gimple_debug_source_bind_p (gstmt))
+                   break;
+                 if (gimple_debug_source_bind_get_value (gstmt) == var)
+                   {
+                     def = gimple_debug_source_bind_get_var (gstmt);
+                     if (TREE_CODE (def) == DEBUG_EXPR_DECL)
+                       break;
+                     else
+                       def = NULL_TREE;
+                   }
+               }
+             /* If not, add a new source bind stmt.  */
+             if (def == NULL_TREE)
+               {
+                 gimple def_temp;
+                 def = make_node (DEBUG_EXPR_DECL);
+                 def_temp = gimple_build_debug_source_bind (def, var, NULL);
+                 DECL_ARTIFICIAL (def) = 1;
+                 TREE_TYPE (def) = TREE_TYPE (var);
+                 DECL_MODE (def) = DECL_MODE (var);
+                 gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
+                 gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
+               }
+             update = true;
+           }
+       }
+      else
+       def = get_current_def (var);
+      if (def == NULL)
+       {
+         gimple_debug_bind_reset_value (stmt);
+         update_stmt (stmt);
+         return;
+       }
+      SET_USE (use_p, def);
+    }
+  if (update)
+    update_stmt (stmt);
+}
+
 /* SSA Rewriting Step 2.  Rewrite every variable used in each statement in
    the block with its immediate reaching definitions.  Update the current
    definition of a variable when a new real or virtual definition is found.  */
@@ -1306,12 +1383,17 @@ rewrite_stmt (gimple_stmt_iterator si)
 
   /* Step 1.  Rewrite USES in the statement.  */
   if (rewrite_uses_p (stmt))
-    FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
-      {
-       tree var = USE_FROM_PTR (use_p);
-       gcc_assert (DECL_P (var));
-       SET_USE (use_p, get_reaching_def (var));
-      }
+    {
+      if (is_gimple_debug (stmt))
+       rewrite_debug_stmt_uses (stmt);
+      else
+       FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+         {
+           tree var = USE_FROM_PTR (use_p);
+           gcc_assert (DECL_P (var));
+           SET_USE (use_p, get_reaching_def (var));
+         }
+    }
 
   /* Step 2.  Register the statement's DEF operands.  */
   if (register_defs_p (stmt))
index 9d2ea1a05f6e970170213979b0918524463dd57a..921821d5fbde3072e0a14af691a5208f64496d04 100644 (file)
@@ -1,5 +1,5 @@
 /* Loop autoparallelization.
-   Copyright (C) 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Sebastian Pop <pop@cri.ensmp.fr> and
    Zdenek Dvorak <dvorakz@suse.cz>.
@@ -716,8 +716,11 @@ eliminate_local_variables (edge entry, edge exit)
   FOR_EACH_VEC_ELT (basic_block, body, i, bb)
     if (bb != entry_bb && bb != exit_bb)
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-       if (gimple_debug_bind_p (gsi_stmt (gsi)))
-         has_debug_stmt = true;
+       if (is_gimple_debug (gsi_stmt (gsi)))
+         {
+           if (gimple_debug_bind_p (gsi_stmt (gsi)))
+             has_debug_stmt = true;
+         }
        else
          eliminate_local_variables_stmt (entry, &gsi, decl_address);
 
@@ -883,8 +886,8 @@ separate_decls_in_region_stmt (edge entry, edge exit, gimple stmt,
    replacement decls are stored in DECL_COPIES.  */
 
 static bool
-separate_decls_in_region_debug_bind (gimple stmt,
-                                    htab_t name_copies, htab_t decl_copies)
+separate_decls_in_region_debug (gimple stmt, htab_t name_copies,
+                               htab_t decl_copies)
 {
   use_operand_p use;
   ssa_op_iter oi;
@@ -893,7 +896,12 @@ separate_decls_in_region_debug_bind (gimple stmt,
   struct name_to_copy_elt elt;
   void **slot, **dslot;
 
-  var = gimple_debug_bind_get_var (stmt);
+  if (gimple_debug_bind_p (stmt))
+    var = gimple_debug_bind_get_var (stmt);
+  else if (gimple_debug_source_bind_p (stmt))
+    var = gimple_debug_source_bind_get_var (stmt);
+  else
+    return true;
   if (TREE_CODE (var) == DEBUG_EXPR_DECL)
     return true;
   gcc_assert (DECL_P (var) && SSA_VAR_P (var));
@@ -901,7 +909,10 @@ separate_decls_in_region_debug_bind (gimple stmt,
   dslot = htab_find_slot_with_hash (decl_copies, &ielt, ielt.uid, NO_INSERT);
   if (!dslot)
     return true;
-  gimple_debug_bind_set_var (stmt, ((struct int_tree_map *) *dslot)->to);
+  if (gimple_debug_bind_p (stmt))
+    gimple_debug_bind_set_var (stmt, ((struct int_tree_map *) *dslot)->to);
+  else if (gimple_debug_source_bind_p (stmt))
+    gimple_debug_source_bind_set_var (stmt, ((struct int_tree_map *) *dslot)->to);
 
   FOR_EACH_PHI_OR_STMT_USE (use, stmt, oi, SSA_OP_USE)
   {
@@ -1295,11 +1306,10 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
            {
              gimple stmt = gsi_stmt (gsi);
 
-             if (gimple_debug_bind_p (stmt))
+             if (is_gimple_debug (stmt))
                {
-                 if (separate_decls_in_region_debug_bind (stmt,
-                                                          name_copies,
-                                                          decl_copies))
+                 if (separate_decls_in_region_debug (stmt, name_copies,
+                                                     decl_copies))
                    {
                      gsi_remove (&gsi, true);
                      continue;
index 322abb570a42d3b239e14b0b41bd7434f94560ba..b9bb23d62e3c5ab25b069ab29e29f5a59b5f2693 100644 (file)
@@ -1,7 +1,7 @@
 /* Scalar Replacement of Aggregates (SRA) converts some structure
    references into scalar references, exposing them to the scalar
    optimizers.
-   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
    Contributed by Martin Jambor <mjambor@suse.cz>
 
 This file is part of GCC.
@@ -4282,28 +4282,87 @@ static void
 sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
 {
   int i, len;
+  gimple_stmt_iterator *gsip = NULL, gsi;
 
+  if (MAY_HAVE_DEBUG_STMTS && single_succ_p (ENTRY_BLOCK_PTR))
+    {
+      gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
+      gsip = &gsi;
+    }
   len = VEC_length (ipa_parm_adjustment_t, adjustments);
   for (i = 0; i < len; i++)
     {
       struct ipa_parm_adjustment *adj;
       imm_use_iterator ui;
-      gimple stmt;
-      tree name;
+      gimple stmt, def_temp;
+      tree name, vexpr, copy = NULL_TREE;
+      use_operand_p use_p;
 
       adj = VEC_index (ipa_parm_adjustment_t, adjustments, i);
       if (adj->copy_param || !is_gimple_reg (adj->base))
        continue;
       name = gimple_default_def (cfun, adj->base);
-      if (!name)
-       continue;
-      FOR_EACH_IMM_USE_STMT (stmt, ui, name)
+      vexpr = NULL;
+      if (name)
+       FOR_EACH_IMM_USE_STMT (stmt, ui, name)
+         {
+           /* All other users must have been removed by
+              ipa_sra_modify_function_body.  */
+           gcc_assert (is_gimple_debug (stmt));
+           if (vexpr == NULL && gsip != NULL)
+             {
+               gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
+               vexpr = make_node (DEBUG_EXPR_DECL);
+               def_temp = gimple_build_debug_source_bind (vexpr, adj->base,
+                                                          NULL);
+               DECL_ARTIFICIAL (vexpr) = 1;
+               TREE_TYPE (vexpr) = TREE_TYPE (name);
+               DECL_MODE (vexpr) = DECL_MODE (adj->base);
+               gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
+             }
+           if (vexpr)
+             {
+               FOR_EACH_IMM_USE_ON_STMT (use_p, ui)
+                 SET_USE (use_p, vexpr);
+             }
+           else
+             gimple_debug_bind_reset_value (stmt);
+           update_stmt (stmt);
+         }
+      /* Create a VAR_DECL for debug info purposes.  */
+      if (!DECL_IGNORED_P (adj->base))
        {
-         /* All other users must have been removed by
-            ipa_sra_modify_function_body.  */
-         gcc_assert (is_gimple_debug (stmt));
-         gimple_debug_bind_reset_value (stmt);
-         update_stmt (stmt);
+         copy = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
+                            VAR_DECL, DECL_NAME (adj->base),
+                            TREE_TYPE (adj->base));
+         if (DECL_PT_UID_SET_P (adj->base))
+           SET_DECL_PT_UID (copy, DECL_PT_UID (adj->base));
+         TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (adj->base);
+         TREE_READONLY (copy) = TREE_READONLY (adj->base);
+         TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (adj->base);
+         DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (adj->base);
+         DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (adj->base);
+         DECL_IGNORED_P (copy) = DECL_IGNORED_P (adj->base);
+         DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (adj->base);
+         DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
+         SET_DECL_RTL (copy, 0);
+         TREE_USED (copy) = 1;
+         DECL_CONTEXT (copy) = current_function_decl;
+         add_referenced_var (copy);
+         add_local_decl (cfun, copy);
+         DECL_CHAIN (copy) =
+           BLOCK_VARS (DECL_INITIAL (current_function_decl));
+         BLOCK_VARS (DECL_INITIAL (current_function_decl)) = copy;
+       }
+      if (gsip != NULL && copy && target_for_debug_bind (adj->base))
+       {
+         gcc_assert (TREE_CODE (adj->base) == PARM_DECL);
+         if (vexpr)
+           def_temp = gimple_build_debug_bind (copy, vexpr, NULL);
+         else
+           def_temp = gimple_build_debug_source_bind (copy, adj->base,
+                                                      NULL);
+         gsi_insert_before (gsip, def_temp, GSI_SAME_STMT);
        }
     }
 }
index 6b778765e92e9244ca1e4ca503b492c54f6a0cb2..6900ee77e869570aba49b40299a8a82fcf614e31 100644 (file)
@@ -1,5 +1,5 @@
 /* Dead code elimination pass for the GNU compiler.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Ben Elliston <bje@redhat.com>
    and Andrew MacLeod <amacleod@redhat.com>
@@ -316,7 +316,8 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
         easily locate the debug temp bind stmt for a use thereof,
         would could refrain from marking all debug temps here, and
         mark them only if they're used.  */
-      if (gimple_debug_bind_has_value_p (stmt)
+      if (!gimple_debug_bind_p (stmt)
+         || gimple_debug_bind_has_value_p (stmt)
          || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL)
        mark_stmt_necessary (stmt, false);
       return;
index d984ecef331abadcae0213bbb9e4456eb40877f7..28720340bab9223482b941a79dc5bb8ecb4a5c63 100644 (file)
@@ -203,6 +203,9 @@ static GTY ((if_marked ("tree_decl_map_marked_p"), param_is (struct tree_decl_ma
 static GTY ((if_marked ("tree_decl_map_marked_p"), param_is (struct tree_decl_map)))
      htab_t value_expr_for_decl;
 
+static GTY ((if_marked ("tree_vec_map_marked_p"), param_is (struct tree_vec_map)))
+     htab_t debug_args_for_decl;
+
 static GTY ((if_marked ("tree_priority_map_marked_p"),
             param_is (struct tree_priority_map)))
   htab_t init_priority_for_decl;
@@ -6016,6 +6019,49 @@ decl_value_expr_insert (tree from, tree to)
   *(struct tree_decl_map **) loc = h;
 }
 
+/* Lookup a vector of debug arguments for FROM, and return it if we
+   find one.  */
+
+VEC(tree, gc) **
+decl_debug_args_lookup (tree from)
+{
+  struct tree_vec_map *h, in;
+
+  if (!DECL_HAS_DEBUG_ARGS_P (from))
+    return NULL;
+  gcc_checking_assert (debug_args_for_decl != NULL);
+  in.base.from = from;
+  h = (struct tree_vec_map *)
+      htab_find_with_hash (debug_args_for_decl, &in, DECL_UID (from));
+  if (h)
+    return &h->to;
+  return NULL;
+}
+
+/* Insert a mapping FROM->empty vector of debug arguments in the value
+   expression hashtable.  */
+
+VEC(tree, gc) **
+decl_debug_args_insert (tree from)
+{
+  struct tree_vec_map *h;
+  void **loc;
+
+  if (DECL_HAS_DEBUG_ARGS_P (from))
+    return decl_debug_args_lookup (from);
+  if (debug_args_for_decl == NULL)
+    debug_args_for_decl = htab_create_ggc (64, tree_vec_map_hash,
+                                          tree_vec_map_eq, 0);
+  h = ggc_alloc_tree_vec_map ();
+  h->base.from = from;
+  h->to = NULL;
+  loc = htab_find_slot_with_hash (debug_args_for_decl, h, DECL_UID (from),
+                                 INSERT);
+  *(struct tree_vec_map **) loc = h;
+  DECL_HAS_DEBUG_ARGS_P (from) = 1;
+  return &h->to;
+}
+
 /* Hashing of types so that we don't make duplicates.
    The entry point is `type_hash_canon'.  */
 
index 3840fed8c04127f310699b80c10af863952578b8..1d1bb31f579507c64422577fcfe1c248e5f9b8a0 100644 (file)
@@ -1,6 +1,6 @@
 /* Front-end tree definitions for GNU compiler.
    Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -3431,6 +3431,13 @@ struct GTY(())
 #define DECL_DISREGARD_INLINE_LIMITS(NODE) \
   (FUNCTION_DECL_CHECK (NODE)->function_decl.disregard_inline_limits)
 
+extern VEC(tree, gc) **decl_debug_args_lookup (tree);
+extern VEC(tree, gc) **decl_debug_args_insert (tree);
+
+/* Nonzero if a FUNCTION_DECL has DEBUG arguments attached to it.  */
+#define DECL_HAS_DEBUG_ARGS_P(NODE) \
+  (FUNCTION_DECL_CHECK (NODE)->function_decl.has_debug_args_flag)
+
 /* For FUNCTION_DECL, this holds a pointer to a structure ("struct function")
    that describes the status of this function.  */
 #define DECL_STRUCT_FUNCTION(NODE) \
@@ -3496,16 +3503,16 @@ struct GTY(()) tree_function_decl {
   unsigned operator_new_flag : 1;
   unsigned declared_inline_flag : 1;
   unsigned regdecl_flag : 1;
-
   unsigned no_inline_warning_flag : 1;
+
   unsigned no_instrument_function_entry_exit : 1;
   unsigned no_limit_stack : 1;
   unsigned disregard_inline_limits : 1;
   unsigned pure_flag : 1;
   unsigned looping_const_or_pure_flag : 1;
+  unsigned has_debug_args_flag : 1;
 
-
-  /* 3 bits left */
+  /* 2 bits left */
 };
 
 /* The source language of the translation-unit.  */
@@ -5742,6 +5749,17 @@ struct GTY(()) tree_priority_map {
 #define tree_priority_map_hash tree_map_base_hash
 #define tree_priority_map_marked_p tree_map_base_marked_p
 
+/* Map from a decl tree to a tree vector.  */
+
+struct GTY(()) tree_vec_map {
+  struct tree_map_base base;
+  VEC(tree,gc) *to;
+};
+
+#define tree_vec_map_eq tree_map_base_eq
+#define tree_vec_map_hash tree_decl_map_hash
+#define tree_vec_map_marked_p tree_map_base_marked_p
+
 /* In tree-ssa.c */
 
 tree target_for_debug_bind (tree);
index a8574d21c300cbc7a02b8ccfd350b75353e885cc..b3f84a17044e95635a286f815fca90c8121ae101 100644 (file)
@@ -5812,6 +5812,29 @@ prepare_call_arguments (basic_block bb, rtx insn)
          }
       }
 
+  /* Add debug arguments.  */
+  if (fndecl
+      && TREE_CODE (fndecl) == FUNCTION_DECL
+      && DECL_HAS_DEBUG_ARGS_P (fndecl))
+    {
+      VEC(tree, gc) **debug_args = decl_debug_args_lookup (fndecl);
+      if (debug_args)
+       {
+         unsigned int ix;
+         tree param;
+         for (ix = 0; VEC_iterate (tree, *debug_args, ix, param); ix += 2)
+           {
+             rtx item;
+             tree dtemp = VEC_index (tree, *debug_args, ix + 1);
+             enum machine_mode mode = DECL_MODE (dtemp);
+             item = gen_rtx_DEBUG_PARAMETER_REF (mode, param);
+             item = gen_rtx_CONCAT (mode, item, DECL_RTL (dtemp));
+             call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item,
+                                                 call_arguments);
+           }
+       }
+    }
+
   /* Reverse call_arguments chain.  */
   prev = NULL_RTX;
   for (cur = call_arguments; cur; cur = next)
index fa0dfac51f3993d9b06d570e350e03e480e4cf4d..e4a6bcae4f9af05c07417241c8bca2de65af27f2 100644 (file)
@@ -1,3 +1,8 @@
+2011-06-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/47858
+       * dwarf2.h (enum dwarf_location_atom): Add DW_OP_GNU_parameter_ref.
+
 2011-06-13  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * demangle.h (DMGL_RET_POSTFIX): Extend the comment.
index 0b008661f964d672de61eb38dad8003e46718825..b2806ef78c9083abfe3762e86d7a3a5fedaa8b76 100644 (file)
@@ -563,6 +563,8 @@ enum dwarf_location_atom
     DW_OP_GNU_deref_type = 0xf6,
     DW_OP_GNU_convert = 0xf7,
     DW_OP_GNU_reinterpret = 0xf9,
+    /* The GNU parameter ref extension.  */
+    DW_OP_GNU_parameter_ref = 0xfa,
     /* HP extensions.  */
     DW_OP_HP_unknown     = 0xe0, /* Ouch, the same as GNU_push_tls_address.  */
     DW_OP_HP_is_value    = 0xe1,