This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: dwarf2out tree expression expansion improvements
On Wed, 16 Sep 2009, Jan Hubicka wrote:
> Hi,
> this is updated patch. I kept the dumping but added function for it so
> it less obstructates the source code. I can remove it if it seems
> better, but I think it is useful. If it is accepted, I will add same
> dumping into RTL expasion.
>
> The patch also adds dump file for final where part of messages depart.
> The output looks like following:
>
> Failed to expand as dwarf: _rtx
> Reason: DECL has no RTL
>
> Failed to expand as dwarf: tem
> Reason: DECL has no RTL
>
> Failed to expand as dwarf: orig_code
> Reason: DECL has no RTL
>
> Failed to expand as dwarf: mask
> (reg/v:DI 246 [ mask ])
> Reason: failed to produce loc descriptor for rtl
>
> Failed to expand as dwarf: is_mode
> Reason: DECL has no RTL
>
> Failed to expand as dwarf: inner_mode
> Reason: DECL has no RTL
>
> Failed to expand as dwarf: orig_pos
> Reason: DECL has no RTL
>
> Failed to expand as dwarf: offset
> (reg/v:DI 117 [ offset ])
> Reason: failed to produce loc descriptor for rtl
>
> (this is excerpt from combine.c compilation. With inline tracking or
> variable bound arrays we expand more exotic expressions too and thus
> get more interesting set of failure reasons)
>
> Other part of dwarf processing happens at the end of compilation unit
> that has no dump file, perhaps we can just open the .final dump there
> too? It is technically IPA pass, I can also add pass called
> end_of_compilation to the end of queue.
>
> I am bootstrapping/regtesting x86_64-linux now after some last minute
> changes, but since it was all in debug output, it should be fine. OK if
> it passes?
I'm happy with the changes. If Jakub thinks the whole plan is sound
the patch is ok. You might want to consider inlining the
dump_file && (dump_flags & TDF_DETAILS) check though.
Thanks,
Richard.
> Honza
>
> * dwarf2out.c: Include tree-pass.h and gimple.h
> (loc_list_plus_const): New function.
> (loc_descriptor_from_tree_1): Rename to ...
> (loc_descriptor_from_tree): ... remove original.
> (loc_list_from_tree): New function.
> (add_AT_location_description): Accept location list.
> (tls_mem_loc_descriptor): Update call of loc_descriptor_from_tree.
> (mem_loc_descriptor): Handle CONCAT and VAR_LOCATION.
> (secname_for_decl): Move up.
> (hidden_reference_p): New function; break out from ...
> (loc_by_refernece): ... here; move up.
> (dw_loc_list): New function.
> (single_element_loc_list): New function.
> (single_element_loc_list_p): New function.
> (add_loc_descr_to_each): New function.
> (add_loc_list): New function.
> (loc_descr_from_tree): Make wraper of loc_list_from_tree.
> (loc_list_from_tree): Reroganized from loc_descr_from_tree;
> add diagnostics why expansion failed.
> (add_location_or_const_value_attribute): Support location lists.
> (add_bound_info): Likewise.
> (descr_info_loc): Update call of loc_descriptor_from_tree.
> (gen_variable_die): Work on location lists.
> * final.c (pass_final): Add dump file.
> * Makefile.in (dwarf2out.o): Add new dependencies.
>
> Index: final.c
> ===================================================================
> *** final.c (revision 151743)
> --- final.c (working copy)
> *************** struct rtl_opt_pass pass_final =
> *** 4304,4310 ****
> {
> {
> RTL_PASS,
> ! NULL, /* name */
> NULL, /* gate */
> rest_of_handle_final, /* execute */
> NULL, /* sub */
> --- 4304,4310 ----
> {
> {
> RTL_PASS,
> ! "final", /* name */
> NULL, /* gate */
> rest_of_handle_final, /* execute */
> NULL, /* sub */
> Index: dwarf2out.c
> ===================================================================
> *** dwarf2out.c (revision 151743)
> --- dwarf2out.c (working copy)
> *************** along with GCC; see the file COPYING3.
> *** 89,94 ****
> --- 89,96 ----
> #include "hashtab.h"
> #include "cgraph.h"
> #include "input.h"
> + #include "gimple.h"
> + #include "tree-pass.h"
>
> #ifdef DWARF2_DEBUGGING_INFO
> static void dwarf2out_source_line (unsigned int, const char *, int, bool);
> *************** loc_descr_plus_const (dw_loc_descr_ref *
> *** 4655,4660 ****
> --- 4657,4672 ----
> }
> }
>
> + /* Add a constant OFFSET to a location list. */
> +
> + static void
> + loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset)
> + {
> + dw_loc_list_ref d;
> + for (d = list_head; d != NULL; d = d->dw_loc_next)
> + loc_descr_plus_const (&d->expr, offset);
> + }
> +
> /* Return the size of a location descriptor. */
>
> static unsigned long
> *************** static dw_loc_descr_ref concat_loc_descr
> *** 5938,5945 ****
> enum var_init_status);
> static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
> enum var_init_status);
> ! static dw_loc_descr_ref loc_descriptor_from_tree_1 (tree, int);
> ! static dw_loc_descr_ref loc_descriptor_from_tree (tree);
> static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
> static tree field_type (const_tree);
> static unsigned int simple_type_align_in_bits (const_tree);
> --- 5950,5957 ----
> enum var_init_status);
> static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
> enum var_init_status);
> ! static dw_loc_list_ref loc_list_from_tree (tree, int);
> ! static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
> static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
> static tree field_type (const_tree);
> static unsigned int simple_type_align_in_bits (const_tree);
> *************** static unsigned int simple_decl_align_in
> *** 5947,5953 ****
> static unsigned HOST_WIDE_INT simple_type_size_in_bits (const_tree);
> static HOST_WIDE_INT field_byte_offset (const_tree);
> static void add_AT_location_description (dw_die_ref, enum dwarf_attribute,
> ! dw_loc_descr_ref);
> static void add_data_member_location_attribute (dw_die_ref, tree);
> static void add_const_value_attribute (dw_die_ref, rtx);
> static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
> --- 5959,5965 ----
> static unsigned HOST_WIDE_INT simple_type_size_in_bits (const_tree);
> static HOST_WIDE_INT field_byte_offset (const_tree);
> static void add_AT_location_description (dw_die_ref, enum dwarf_attribute,
> ! dw_loc_list_ref);
> static void add_data_member_location_attribute (dw_die_ref, tree);
> static void add_const_value_attribute (dw_die_ref, rtx);
> static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
> *************** tls_mem_loc_descriptor (rtx mem)
> *** 11006,11012 ****
> || !DECL_THREAD_LOCAL_P (base))
> return NULL;
>
> ! loc_result = loc_descriptor_from_tree_1 (MEM_EXPR (mem), 2);
> if (loc_result == NULL)
> return NULL;
>
> --- 11018,11024 ----
> || !DECL_THREAD_LOCAL_P (base))
> return NULL;
>
> ! loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 2);
> if (loc_result == NULL)
> return NULL;
>
> *************** tls_mem_loc_descriptor (rtx mem)
> *** 11016,11021 ****
> --- 11028,11053 ----
> return loc_result;
> }
>
> + /* Output debug info about reason why we failed to expand expression as dwarf
> + expression. */
> +
> + static void
> + expansion_failed (tree expr, rtx rtl, char const *reason)
> + {
> + if (dump_file && (dump_flags & TDF_DETAILS))
> + {
> + fprintf (dump_file, "Failed to expand as dwarf: ");
> + if (expr)
> + print_generic_expr (dump_file, expr, dump_flags);
> + if (rtl)
> + {
> + fprintf (dump_file, "\n");
> + print_rtl (dump_file, rtl);
> + }
> + fprintf (dump_file, "\nReason: %s\n", reason);
> + }
> + }
> +
> /* The following routine converts the RTL for a variable or parameter
> (resident in memory) into an equivalent Dwarf representation of a
> mechanism for getting the address of that same variable onto the top of a
> *************** mem_loc_descriptor (rtx rtl, enum machin
> *** 11163,11169 ****
> FIXME: might try to use DW_OP_const_value here, though
> DW_OP_piece complicates it. */
> if (!marked)
> ! return 0;
> }
>
> if (GET_CODE (rtl) == SYMBOL_REF
> --- 11195,11205 ----
> FIXME: might try to use DW_OP_const_value here, though
> DW_OP_piece complicates it. */
> if (!marked)
> ! {
> ! expansion_failed (NULL_TREE, rtl,
> ! "Constant was removed from constant pool.\n");
> ! return 0;
> ! }
> }
>
> if (GET_CODE (rtl) == SYMBOL_REF
> *************** mem_loc_descriptor (rtx rtl, enum machin
> *** 11193,11198 ****
> --- 11229,11250 ----
> VEC_safe_push (rtx, gc, used_rtx_array, rtl);
> break;
>
> + case CONCAT:
> + {
> + rtx x0 = XEXP (rtl, 0);
> + rtx x1 = XEXP (rtl, 1);
> + dw_loc_descr_ref x0_ref = mem_loc_descriptor (x0, GET_MODE (x0), VAR_INIT_STATUS_INITIALIZED);
> + dw_loc_descr_ref x1_ref = mem_loc_descriptor (x1, GET_MODE (x1), VAR_INIT_STATUS_INITIALIZED);
> + if (x0_ref == 0 || x1_ref == 0)
> + return 0;
> + mem_loc_result = x0_ref;
> + add_loc_descr_op_piece (&mem_loc_result, GET_MODE_SIZE (GET_MODE (x0)));
> +
> + add_loc_descr (&mem_loc_result, x1_ref);
> + add_loc_descr_op_piece (&mem_loc_result, GET_MODE_SIZE (GET_MODE (x1)));
> + }
> + break;
> +
> case PRE_MODIFY:
> /* Extract the PLUS expression nested inside and fall into
> PLUS code below. */
> *************** mem_loc_descriptor (rtx rtl, enum machin
> *** 11327,11332 ****
> --- 11379,11397 ----
> VAR_INIT_STATUS_INITIALIZED);
> break;
>
> + case VAR_LOCATION:
> + if (GET_CODE (XEXP (rtl, 1)) != PARALLEL)
> + {
> + mem_loc_result = mem_loc_descriptor (XEXP (XEXP (rtl, 1), 0), mode, initialized);
> + break;
> + }
> + /* TODO: We can handle this case via OP_piece of dwarf stack machine operatoins.
> + It should not be common case however. */
> + expansion_failed (NULL_TREE, rtl,
> + "Multipart value can not be used in value expression.\n");
> + return 0;
> + break;
> +
> case EQ:
> op = DW_OP_eq;
> goto do_scompare;
> *************** loc_descriptor (rtx rtl, enum machine_mo
> *** 11972,11987 ****
> return loc_result;
> }
>
> ! /* Similar, but generate the descriptor from trees instead of rtl. This comes
> ! up particularly with variable length arrays. WANT_ADDRESS is 2 if this is
> ! a top-level invocation of loc_descriptor_from_tree; is 1 if this is not a
> ! top-level invocation, and we require the address of LOC; is 0 if we require
> ! the value of LOC. */
>
> static dw_loc_descr_ref
> ! loc_descriptor_from_tree_1 (tree loc, int want_address)
> {
> ! dw_loc_descr_ref ret, ret1;
> int have_address = 0;
> enum dwarf_location_atom op;
>
> --- 12037,12318 ----
> return loc_result;
> }
>
> ! /* We need to figure out what section we should use as the base for the
> ! address ranges where a given location is valid.
> ! 1. If this particular DECL has a section associated with it, use that.
> ! 2. If this function has a section associated with it, use that.
> ! 3. Otherwise, use the text section.
> ! XXX: If you split a variable across multiple sections, we won't notice. */
> !
> ! static const char *
> ! secname_for_decl (const_tree decl)
> ! {
> ! const char *secname;
> !
> ! if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
> ! {
> ! tree sectree = DECL_SECTION_NAME (decl);
> ! secname = TREE_STRING_POINTER (sectree);
> ! }
> ! else if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
> ! {
> ! tree sectree = DECL_SECTION_NAME (current_function_decl);
> ! secname = TREE_STRING_POINTER (sectree);
> ! }
> ! else if (cfun && in_cold_section_p)
> ! secname = crtl->subsections.cold_section_label;
> ! else
> ! secname = text_section_label;
> !
> ! return secname;
> ! }
> !
> ! static bool
> ! hidden_reference_p (tree decl)
> ! {
> ! return ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL
> ! || (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl)))
> ! && DECL_BY_REFERENCE (decl));
> ! }
> !
> ! /* Dereference a location expression LOC if DECL is passed by invisible
> ! reference. */
>
> static dw_loc_descr_ref
> ! loc_by_reference (dw_loc_descr_ref loc, tree decl)
> ! {
> ! HOST_WIDE_INT size;
> ! enum dwarf_location_atom op;
> !
> ! if (loc == NULL)
> ! return NULL;
> !
> ! if (!hidden_reference_p (decl))
> ! return loc;
> !
> ! /* If loc is DW_OP_reg{0...31,x}, don't add DW_OP_deref, instead
> ! change it into corresponding DW_OP_breg{0...31,x} 0. Then the
> ! location expression is considered to be address of a memory location,
> ! rather than the register itself. */
> ! if (((loc->dw_loc_opc >= DW_OP_reg0 && loc->dw_loc_opc <= DW_OP_reg31)
> ! || loc->dw_loc_opc == DW_OP_regx)
> ! && (loc->dw_loc_next == NULL
> ! || (loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_uninit
> ! && loc->dw_loc_next->dw_loc_next == NULL)))
> ! {
> ! if (loc->dw_loc_opc == DW_OP_regx)
> ! {
> ! loc->dw_loc_opc = DW_OP_bregx;
> ! loc->dw_loc_oprnd2.v.val_int = 0;
> ! }
> ! else
> ! {
> ! loc->dw_loc_opc
> ! = (enum dwarf_location_atom)
> ! (loc->dw_loc_opc + (DW_OP_breg0 - DW_OP_reg0));
> ! loc->dw_loc_oprnd1.v.val_int = 0;
> ! }
> ! return loc;
> ! }
> !
> ! size = int_size_in_bytes (TREE_TYPE (decl));
> ! if (size > DWARF2_ADDR_SIZE || size == -1)
> ! return 0;
> ! else if (size == DWARF2_ADDR_SIZE)
> ! op = DW_OP_deref;
> ! else
> ! op = DW_OP_deref_size;
> ! add_loc_descr (&loc, new_loc_descr (op, size, 0));
> ! return loc;
> ! }
> !
> ! /* Return dwarf representation of location list representing for
> ! LOC_LIST of DECL. */
> !
> ! static dw_loc_list_ref
> ! dw_loc_list (var_loc_list * loc_list, tree decl, bool toplevel)
> ! {
> ! const char *endname, *secname;
> ! dw_loc_list_ref list;
> ! rtx varloc;
> ! enum var_init_status initialized;
> ! struct var_loc_node *node;
> ! dw_loc_descr_ref descr;
> ! char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
> !
> ! bool by_reference = hidden_reference_p (decl);
> !
> ! /* Now that we know what section we are using for a base,
> ! actually construct the list of locations.
> ! The first location information is what is passed to the
> ! function that creates the location list, and the remaining
> ! locations just get added on to that list.
> ! Note that we only know the start address for a location
> ! (IE location changes), so to build the range, we use
> ! the range [current location start, next location start].
> ! This means we have to special case the last node, and generate
> ! a range of [last location start, end of function label]. */
> !
> ! node = loc_list->first;
> ! varloc = NOTE_VAR_LOCATION (node->var_loc_note);
> ! secname = secname_for_decl (decl);
> !
> ! if (NOTE_VAR_LOCATION_LOC (node->var_loc_note))
> ! initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
> ! else
> ! initialized = VAR_INIT_STATUS_INITIALIZED;
> !
> ! if (!toplevel || by_reference)
> ! descr = loc_by_reference (mem_loc_descriptor (varloc,
> ! TYPE_MODE (TREE_TYPE (decl)),
> ! initialized),
> ! decl);
> ! else
> ! descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
> ! initialized), decl);
> !
> ! if (!current_function_decl)
> ! endname = text_end_label;
> ! else
> ! {
> ! ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
> ! current_function_funcdef_no);
> ! endname = ggc_strdup (label_id);
> ! }
> ! list = new_loc_list (descr, node->label, node->next ? node->next->label : endname, secname, 1);
> ! node = node->next;
> !
> ! if (!node)
> ! return NULL;
> !
> ! for (; node->next; node = node->next)
> ! if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
> ! {
> ! /* The variable has a location between NODE->LABEL and
> ! NODE->NEXT->LABEL. */
> ! enum var_init_status initialized =
> ! NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
> ! varloc = NOTE_VAR_LOCATION (node->var_loc_note);
> ! if (!toplevel || by_reference)
> ! descr = mem_loc_descriptor (varloc, TYPE_MODE (TREE_TYPE (decl)), initialized);
> ! else
> ! descr = loc_descriptor (varloc, DECL_MODE (decl), initialized);
> ! descr = loc_by_reference (descr, decl);
> ! add_loc_descr_to_loc_list (&list, descr,
> ! node->label, node->next->label, secname);
> ! }
> !
> ! /* If the variable has a location at the last label
> ! it keeps its location until the end of function. */
> ! if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
> ! {
> ! enum var_init_status initialized =
> ! NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
> !
> ! varloc = NOTE_VAR_LOCATION (node->var_loc_note);
> ! descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
> ! initialized), decl);
> ! add_loc_descr_to_loc_list (&list, descr, node->label, endname, secname);
> ! }
> ! return list;
> ! }
> !
> ! /* Return single element location list containing loc descr REF. */
> !
> ! static dw_loc_list_ref
> ! single_element_loc_list (dw_loc_descr_ref ref)
> ! {
> ! return new_loc_list (ref, NULL, NULL, NULL, 0);
> ! }
> !
> ! /* Return if the loc_list has only single element and thus can be represented
> ! as location description. */
> !
> ! static bool
> ! single_element_loc_list_p (dw_loc_list_ref list)
> ! {
> ! return (!list->dw_loc_next && !list->begin && !list->end);
> ! }
> !
> ! /* To each location in list LIST add loc descr REF. */
> !
> ! static void
> ! add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
> {
> ! dw_loc_descr_ref copy;
> ! add_loc_descr (&list->expr, ref);
> ! list = list->dw_loc_next;
> ! while (list)
> ! {
> ! copy = GGC_CNEW (dw_loc_descr_node);
> ! memcpy (copy, ref, sizeof (dw_loc_descr_node));
> ! add_loc_descr (&list->expr, copy);
> ! while (copy->dw_loc_next)
> ! {
> ! dw_loc_descr_ref new_copy = GGC_CNEW (dw_loc_descr_node);
> ! memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
> ! copy->dw_loc_next = new_copy;
> ! copy = new_copy;
> ! }
> ! list = list->dw_loc_next;
> ! }
> ! }
> !
> ! /* Given two lists RET and LIST
> ! produce location list that is result of adding expression in LIST
> ! to expression in RET on each possition in program.
> ! Might be destructive on both RET and LIST.
> !
> ! TODO: We handle only simple cases of RET or LIST having at most one
> ! element. General case would inolve sorting the lists in program order
> ! and merging them that will need some additional work.
> ! Adding that will improve quality of debug info especially for SRA-ed
> ! structures. */
> !
> ! static void
> ! add_loc_list (dw_loc_list_ref *ret, dw_loc_list_ref list)
> ! {
> ! if (!list)
> ! return;
> ! if (!*ret)
> ! {
> ! *ret = list;
> ! return;
> ! }
> ! if (!list->dw_loc_next)
> ! {
> ! add_loc_descr_to_each (*ret, list->expr);
> ! return;
> ! }
> ! if (!(*ret)->dw_loc_next)
> ! {
> ! add_loc_descr_to_each (list, (*ret)->expr);
> ! *ret = list;
> ! return;
> ! }
> ! expansion_failed (NULL_TREE, NULL_RTX,
> ! "Don't know how to merge two non-trivial"
> ! " location lists.\n");
> ! *ret = NULL;
> ! return;
> ! }
> !
> ! /* Generate Dwarf location list representing LOC.
> ! If WANT_ADDRESS is 0, expression computing LOC will be computed
> ! If WANT_ADDRESS is 1, expression computing address of LOC will be returned
> ! if WANT_ADDRESS is 2, expression computing address useable in location
> ! will be returned (i.e. DW_OP_reg can be used
> ! to refer to register values)
> ! TODO: Dwarf4 adds types to the stack machine that ought to be used here
> ! DW_OP_stack_value will help in cases where we fail to find address of the
> ! expression.
> ! */
> !
> ! static dw_loc_list_ref
> ! loc_list_from_tree (tree loc, int want_address)
> ! {
> ! dw_loc_descr_ref ret = NULL, ret1 = NULL;
> ! dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
> int have_address = 0;
> enum dwarf_location_atom op;
>
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 11992,11997 ****
> --- 12323,12329 ----
> switch (TREE_CODE (loc))
> {
> case ERROR_MARK:
> + expansion_failed (loc, NULL_RTX, "ERROR_MARK");
> return 0;
>
> case PLACEHOLDER_EXPR:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 11999,12023 ****
> position of other fields. We don't try to encode this here. The
> only user of this is Ada, which encodes the needed information using
> the names of types. */
> return 0;
>
> case CALL_EXPR:
> return 0;
>
> case PREINCREMENT_EXPR:
> case PREDECREMENT_EXPR:
> case POSTINCREMENT_EXPR:
> case POSTDECREMENT_EXPR:
> /* There are no opcodes for these operations. */
> return 0;
>
> case ADDR_EXPR:
> /* If we already want an address, there's nothing we can do. */
> if (want_address)
> ! return 0;
>
> /* Otherwise, process the argument and look for the address. */
> ! return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 1);
>
> case VAR_DECL:
> if (DECL_THREAD_LOCAL_P (loc))
> --- 12331,12362 ----
> position of other fields. We don't try to encode this here. The
> only user of this is Ada, which encodes the needed information using
> the names of types. */
> + expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR");
> return 0;
>
> case CALL_EXPR:
> + expansion_failed (loc, NULL_RTX, "CALL_EXPR");
> + /* There are no opcodes for these operations. */
> return 0;
>
> case PREINCREMENT_EXPR:
> case PREDECREMENT_EXPR:
> case POSTINCREMENT_EXPR:
> case POSTDECREMENT_EXPR:
> + expansion_failed (loc, NULL_RTX, "PRE/POST INDCREMENT/DECREMENT");
> /* There are no opcodes for these operations. */
> return 0;
>
> case ADDR_EXPR:
> /* If we already want an address, there's nothing we can do. */
> if (want_address)
> ! {
> ! expansion_failed (loc, NULL_RTX, "need address of ADDR_EXPR");
> ! return 0;
> ! }
>
> /* Otherwise, process the argument and look for the address. */
> ! return loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
>
> case VAR_DECL:
> if (DECL_THREAD_LOCAL_P (loc))
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12077,12093 ****
>
> case PARM_DECL:
> if (DECL_HAS_VALUE_EXPR_P (loc))
> ! return loc_descriptor_from_tree_1 (DECL_VALUE_EXPR (loc),
> ! want_address);
> /* FALLTHRU */
>
> case RESULT_DECL:
> case FUNCTION_DECL:
> {
> rtx rtl = rtl_for_decl_location (loc);
>
> ! if (rtl == NULL_RTX)
> ! return 0;
> else if (CONST_INT_P (rtl))
> {
> HOST_WIDE_INT val = INTVAL (rtl);
> --- 12416,12439 ----
>
> case PARM_DECL:
> if (DECL_HAS_VALUE_EXPR_P (loc))
> ! return loc_list_from_tree (DECL_VALUE_EXPR (loc),
> ! want_address);
> /* FALLTHRU */
>
> case RESULT_DECL:
> case FUNCTION_DECL:
> {
> rtx rtl = rtl_for_decl_location (loc);
> + var_loc_list *loc_list = lookup_decl_loc (loc);
>
> ! if (loc_list && loc_list->first
> ! && (list_ret = dw_loc_list (loc_list, loc, want_address == 2)))
> ! have_address = 1;
> ! else if (rtl == NULL_RTX)
> ! {
> ! expansion_failed (loc, NULL_RTX, "DECL has no RTL");
> ! return 0;
> ! }
> else if (CONST_INT_P (rtl))
> {
> HOST_WIDE_INT val = INTVAL (rtl);
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12096,12102 ****
> ret = int_loc_descriptor (val);
> }
> else if (GET_CODE (rtl) == CONST_STRING)
> ! return 0;
> else if (CONSTANT_P (rtl))
> {
> ret = new_loc_descr (DW_OP_addr, 0, 0);
> --- 12442,12451 ----
> ret = int_loc_descriptor (val);
> }
> else if (GET_CODE (rtl) == CONST_STRING)
> ! {
> ! expansion_failed (loc, NULL_RTX, "CONST_STRING");
> ! return 0;
> ! }
> else if (CONSTANT_P (rtl))
> {
> ret = new_loc_descr (DW_OP_addr, 0, 0);
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12109,12141 ****
>
> /* Certain constructs can only be represented at top-level. */
> if (want_address == 2)
> - return loc_descriptor (rtl, VOIDmode,
> - VAR_INIT_STATUS_INITIALIZED);
> -
> - mode = GET_MODE (rtl);
> - if (MEM_P (rtl))
> {
> ! rtl = XEXP (rtl, 0);
> have_address = 1;
> }
> ! ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
> }
> }
> break;
>
> case INDIRECT_REF:
> ! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
> have_address = 1;
> break;
>
> case COMPOUND_EXPR:
> ! return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), want_address);
>
> CASE_CONVERT:
> case VIEW_CONVERT_EXPR:
> case SAVE_EXPR:
> case MODIFY_EXPR:
> ! return loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), want_address);
>
> case COMPONENT_REF:
> case BIT_FIELD_REF:
> --- 12458,12498 ----
>
> /* Certain constructs can only be represented at top-level. */
> if (want_address == 2)
> {
> ! ret = loc_descriptor (rtl, VOIDmode,
> ! VAR_INIT_STATUS_INITIALIZED);
> have_address = 1;
> }
> ! if (!ret)
> ! {
> ! mode = GET_MODE (rtl);
> ! if (MEM_P (rtl))
> ! {
> ! rtl = XEXP (rtl, 0);
> ! have_address = 1;
> ! }
> ! ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
> ! }
> ! if (!ret)
> ! expansion_failed (loc, rtl,
> ! "failed to produce loc descriptor for rtl");
> }
> }
> break;
>
> case INDIRECT_REF:
> ! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
> have_address = 1;
> break;
>
> case COMPOUND_EXPR:
> ! return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address);
>
> CASE_CONVERT:
> case VIEW_CONVERT_EXPR:
> case SAVE_EXPR:
> case MODIFY_EXPR:
> ! return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address);
>
> case COMPONENT_REF:
> case BIT_FIELD_REF:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12151,12176 ****
> obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
> &unsignedp, &volatilep, false);
>
> ! if (obj == loc)
> ! return 0;
>
> ! ret = loc_descriptor_from_tree_1 (obj, 1);
> ! if (ret == 0
> ! || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
> return 0;
>
> if (offset != NULL_TREE)
> {
> /* Variable offset. */
> ! ret1 = loc_descriptor_from_tree_1 (offset, 0);
> ! if (ret1 == 0)
> return 0;
> ! add_loc_descr (&ret, ret1);
> ! add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
> }
>
> bytepos = bitpos / BITS_PER_UNIT;
> ! loc_descr_plus_const (&ret, bytepos);
>
> have_address = 1;
> break;
> --- 12508,12542 ----
> obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
> &unsignedp, &volatilep, false);
>
> ! gcc_assert (obj != loc);
>
> ! list_ret = loc_list_from_tree (obj, 1);
> ! if (list_ret == 0)
> return 0;
> + if (bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
> + {
> + expansion_failed (loc, NULL_RTX,
> + "bitfield access");
> + return 0;
> + }
>
> if (offset != NULL_TREE)
> {
> /* Variable offset. */
> ! list_ret1 = loc_list_from_tree (offset, 0);
> ! if (list_ret1 == 0)
> return 0;
> ! add_loc_list (&list_ret, list_ret1);
> ! if (!list_ret)
> ! return 0;
> ! add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_plus, 0, 0));
> }
>
> bytepos = bitpos / BITS_PER_UNIT;
> ! if (bytepos > 0)
> ! add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
> ! else if (bytepos < 0)
> ! loc_list_plus_const (list_ret, bytepos);
>
> have_address = 1;
> break;
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12180,12186 ****
> if (host_integerp (loc, 0))
> ret = int_loc_descriptor (tree_low_cst (loc, 0));
> else
> ! return 0;
> break;
>
> case CONSTRUCTOR:
> --- 12546,12556 ----
> if (host_integerp (loc, 0))
> ret = int_loc_descriptor (tree_low_cst (loc, 0));
> else
> ! {
> ! expansion_failed (loc, NULL_RTX,
> ! "Integer operand is not host integer");
> ! return 0;
> ! }
> break;
>
> case CONSTRUCTOR:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12250,12260 ****
> if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
> && host_integerp (TREE_OPERAND (loc, 1), 0))
> {
> ! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
> ! if (ret == 0)
> return 0;
>
> ! loc_descr_plus_const (&ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
> break;
> }
>
> --- 12620,12630 ----
> if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
> && host_integerp (TREE_OPERAND (loc, 1), 0))
> {
> ! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
> ! if (list_ret == 0)
> return 0;
>
> ! loc_list_plus_const (list_ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
> break;
> }
>
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12298,12310 ****
> goto do_binop;
>
> do_binop:
> ! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
> ! ret1 = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
> ! if (ret == 0 || ret1 == 0)
> return 0;
>
> ! add_loc_descr (&ret, ret1);
> ! add_loc_descr (&ret, new_loc_descr (op, 0, 0));
> break;
>
> case TRUTH_NOT_EXPR:
> --- 12668,12682 ----
> goto do_binop;
>
> do_binop:
> ! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
> ! list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
> ! if (list_ret == 0 || list_ret1 == 0)
> return 0;
>
> ! add_loc_list (&list_ret, list_ret1);
> ! if (list_ret == 0)
> ! return 0;
> ! add_loc_descr_to_each (list_ret, new_loc_descr (op, 0, 0));
> break;
>
> case TRUTH_NOT_EXPR:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12321,12331 ****
> goto do_unop;
>
> do_unop:
> ! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
> ! if (ret == 0)
> return 0;
>
> ! add_loc_descr (&ret, new_loc_descr (op, 0, 0));
> break;
>
> case MIN_EXPR:
> --- 12693,12703 ----
> goto do_unop;
>
> do_unop:
> ! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
> ! if (list_ret == 0)
> return 0;
>
> ! add_loc_descr_to_each (list_ret, new_loc_descr (op, 0, 0));
> break;
>
> case MIN_EXPR:
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12345,12373 ****
> case COND_EXPR:
> {
> dw_loc_descr_ref lhs
> ! = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 1), 0);
> ! dw_loc_descr_ref rhs
> ! = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 2), 0);
> dw_loc_descr_ref bra_node, jump_node, tmp;
>
> ! ret = loc_descriptor_from_tree_1 (TREE_OPERAND (loc, 0), 0);
> ! if (ret == 0 || lhs == 0 || rhs == 0)
> return 0;
>
> bra_node = new_loc_descr (DW_OP_bra, 0, 0);
> ! add_loc_descr (&ret, bra_node);
>
> ! add_loc_descr (&ret, rhs);
> jump_node = new_loc_descr (DW_OP_skip, 0, 0);
> ! add_loc_descr (&ret, jump_node);
>
> ! add_loc_descr (&ret, lhs);
> bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
> bra_node->dw_loc_oprnd1.v.val_loc = lhs;
>
> /* ??? Need a node to point the skip at. Use a nop. */
> tmp = new_loc_descr (DW_OP_nop, 0, 0);
> ! add_loc_descr (&ret, tmp);
> jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
> jump_node->dw_loc_oprnd1.v.val_loc = tmp;
> }
> --- 12717,12745 ----
> case COND_EXPR:
> {
> dw_loc_descr_ref lhs
> ! = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
> ! dw_loc_list_ref rhs
> ! = loc_list_from_tree (TREE_OPERAND (loc, 2), 0);
> dw_loc_descr_ref bra_node, jump_node, tmp;
>
> ! list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
> ! if (list_ret == 0 || lhs == 0 || rhs == 0)
> return 0;
>
> bra_node = new_loc_descr (DW_OP_bra, 0, 0);
> ! add_loc_descr_to_each (list_ret, bra_node);
>
> ! add_loc_list (&list_ret, rhs);
> jump_node = new_loc_descr (DW_OP_skip, 0, 0);
> ! add_loc_descr_to_each (list_ret, jump_node);
>
> ! add_loc_descr_to_each (list_ret, lhs);
> bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
> bra_node->dw_loc_oprnd1.v.val_loc = lhs;
>
> /* ??? Need a node to point the skip at. Use a nop. */
> tmp = new_loc_descr (DW_OP_nop, 0, 0);
> ! add_loc_descr_to_each (list_ret, tmp);
> jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
> jump_node->dw_loc_oprnd1.v.val_loc = tmp;
> }
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12381,12387 ****
> up, for instance, with the C STMT_EXPR. */
> if ((unsigned int) TREE_CODE (loc)
> >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
> ! return 0;
>
> #ifdef ENABLE_CHECKING
> /* Otherwise this is a generic code; we should just lists all of
> --- 12753,12763 ----
> up, for instance, with the C STMT_EXPR. */
> if ((unsigned int) TREE_CODE (loc)
> >= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
> ! {
> ! expansion_failed (loc, NULL_RTX,
> ! "language specific tree node");
> ! return 0;
> ! }
>
> #ifdef ENABLE_CHECKING
> /* Otherwise this is a generic code; we should just lists all of
> *************** loc_descriptor_from_tree_1 (tree loc, in
> *** 12394,12425 ****
> #endif
> }
>
> /* Show if we can't fill the request for an address. */
> if (want_address && !have_address)
> ! return 0;
>
> /* If we've got an address and don't want one, dereference. */
> ! if (!want_address && have_address && ret)
> {
> HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
>
> if (size > DWARF2_ADDR_SIZE || size == -1)
> ! return 0;
> else if (size == DWARF2_ADDR_SIZE)
> op = DW_OP_deref;
> else
> op = DW_OP_deref_size;
>
> ! add_loc_descr (&ret, new_loc_descr (op, size, 0));
> }
>
> ! return ret;
> }
>
> ! static inline dw_loc_descr_ref
> ! loc_descriptor_from_tree (tree loc)
> {
> ! return loc_descriptor_from_tree_1 (loc, 2);
> }
>
> /* Given a value, round it up to the lowest multiple of `boundary'
> --- 12770,12829 ----
> #endif
> }
>
> + if (!ret && !list_ret)
> + return 0;
> +
> /* Show if we can't fill the request for an address. */
> if (want_address && !have_address)
> ! {
> ! expansion_failed (loc, NULL_RTX,
> ! "Want address and only have value");
> ! return 0;
> ! }
> !
> ! gcc_assert (!ret || !list_ret);
>
> /* If we've got an address and don't want one, dereference. */
> ! if (!want_address && have_address)
> {
> HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
>
> if (size > DWARF2_ADDR_SIZE || size == -1)
> ! {
> ! expansion_failed (loc, NULL_RTX,
> ! "DWARF address size mismatch");
> ! return 0;
> ! }
> else if (size == DWARF2_ADDR_SIZE)
> op = DW_OP_deref;
> else
> op = DW_OP_deref_size;
>
> ! if (ret)
> ! add_loc_descr (&ret, new_loc_descr (op, size, 0));
> ! else
> ! add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0));
> }
> + if (ret)
> + list_ret = single_element_loc_list (ret);
>
> ! return list_ret;
> }
>
> ! /* Same as above but return only single location expression. */
> ! static dw_loc_descr_ref
> ! loc_descriptor_from_tree (tree loc, int want_address)
> {
> ! dw_loc_list_ref ret = loc_list_from_tree (loc, want_address);
> ! if (!ret)
> ! return NULL;
> ! if (ret->dw_loc_next)
> ! {
> ! expansion_failed (loc, NULL_RTX,
> ! "Location list where only loc descriptor needed");
> ! return NULL;
> ! }
> ! return ret->expr;
> }
>
> /* Given a value, round it up to the lowest multiple of `boundary'
> *************** field_byte_offset (const_tree decl)
> *** 12626,12635 ****
>
> static inline void
> add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind,
> ! dw_loc_descr_ref descr)
> {
> ! if (descr != 0)
> ! add_AT_loc (die, attr_kind, descr);
> }
>
> /* Attach the specialized form of location attribute used for data members of
> --- 13030,13043 ----
>
> static inline void
> add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind,
> ! dw_loc_list_ref descr)
> {
> ! if (descr == 0)
> ! return;
> ! if (single_element_loc_list_p (descr))
> ! add_AT_loc (die, attr_kind, descr->expr);
> ! else
> ! add_AT_loc_list (die, attr_kind, descr);
> }
>
> /* Attach the specialized form of location attribute used for data members of
> *************** rtl_for_decl_location (tree decl)
> *** 13267,13302 ****
> return rtl;
> }
>
> - /* We need to figure out what section we should use as the base for the
> - address ranges where a given location is valid.
> - 1. If this particular DECL has a section associated with it, use that.
> - 2. If this function has a section associated with it, use that.
> - 3. Otherwise, use the text section.
> - XXX: If you split a variable across multiple sections, we won't notice. */
> -
> - static const char *
> - secname_for_decl (const_tree decl)
> - {
> - const char *secname;
> -
> - if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
> - {
> - tree sectree = DECL_SECTION_NAME (decl);
> - secname = TREE_STRING_POINTER (sectree);
> - }
> - else if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
> - {
> - tree sectree = DECL_SECTION_NAME (current_function_decl);
> - secname = TREE_STRING_POINTER (sectree);
> - }
> - else if (cfun && in_cold_section_p)
> - secname = crtl->subsections.cold_section_label;
> - else
> - secname = text_section_label;
> -
> - return secname;
> - }
> -
> /* Check whether decl is a Fortran COMMON symbol. If not, NULL_TREE is
> returned. If so, the decl for the COMMON block is returned, and the
> value is the offset into the common block for the symbol. */
> --- 13675,13680 ----
> *************** fortran_common (tree decl, HOST_WIDE_INT
> *** 13347,13406 ****
> return cvar;
> }
>
> - /* Dereference a location expression LOC if DECL is passed by invisible
> - reference. */
> -
> - static dw_loc_descr_ref
> - loc_by_reference (dw_loc_descr_ref loc, tree decl)
> - {
> - HOST_WIDE_INT size;
> - enum dwarf_location_atom op;
> -
> - if (loc == NULL)
> - return NULL;
> -
> - if ((TREE_CODE (decl) != PARM_DECL
> - && TREE_CODE (decl) != RESULT_DECL
> - && TREE_CODE (decl) != VAR_DECL)
> - || !DECL_BY_REFERENCE (decl))
> - return loc;
> -
> - /* If loc is DW_OP_reg{0...31,x}, don't add DW_OP_deref, instead
> - change it into corresponding DW_OP_breg{0...31,x} 0. Then the
> - location expression is considered to be address of a memory location,
> - rather than the register itself. */
> - if (((loc->dw_loc_opc >= DW_OP_reg0 && loc->dw_loc_opc <= DW_OP_reg31)
> - || loc->dw_loc_opc == DW_OP_regx)
> - && (loc->dw_loc_next == NULL
> - || (loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_uninit
> - && loc->dw_loc_next->dw_loc_next == NULL)))
> - {
> - if (loc->dw_loc_opc == DW_OP_regx)
> - {
> - loc->dw_loc_opc = DW_OP_bregx;
> - loc->dw_loc_oprnd2.v.val_int = 0;
> - }
> - else
> - {
> - loc->dw_loc_opc
> - = (enum dwarf_location_atom)
> - (loc->dw_loc_opc + (DW_OP_breg0 - DW_OP_reg0));
> - loc->dw_loc_oprnd1.v.val_int = 0;
> - }
> - return loc;
> - }
> -
> - size = int_size_in_bytes (TREE_TYPE (decl));
> - if (size > DWARF2_ADDR_SIZE || size == -1)
> - return 0;
> - else if (size == DWARF2_ADDR_SIZE)
> - op = DW_OP_deref;
> - else
> - op = DW_OP_deref_size;
> - add_loc_descr (&loc, new_loc_descr (op, size, 0));
> - return loc;
> - }
> -
> /* Generate *either* a DW_AT_location attribute or else a DW_AT_const_value
> data attribute for a variable or a parameter. We generate the
> DW_AT_const_value attribute only in those cases where the given variable
> --- 13725,13730 ----
> *************** add_location_or_const_value_attribute (d
> *** 13418,13423 ****
> --- 13742,13748 ----
> {
> rtx rtl;
> dw_loc_descr_ref descr;
> + dw_loc_list_ref descr_list;
> var_loc_list *loc_list;
> struct var_loc_node *node;
> if (TREE_CODE (decl) == ERROR_MARK)
> *************** add_location_or_const_value_attribute (d
> *** 13539,13556 ****
> if (descr)
> {
> descr = loc_by_reference (descr, decl);
> ! add_AT_location_description (die, attr, descr);
> return;
> }
> }
>
> /* We couldn't get any rtl, so try directly generating the location
> description from the tree. */
> ! descr = loc_descriptor_from_tree (decl);
> ! if (descr)
> {
> descr = loc_by_reference (descr, decl);
> ! add_AT_location_description (die, attr, descr);
> return;
> }
> /* None of that worked, so it must not really have a location;
> --- 13864,13881 ----
> if (descr)
> {
> descr = loc_by_reference (descr, decl);
> ! add_AT_location_description (die, attr, single_element_loc_list (descr));
> return;
> }
> }
>
> /* We couldn't get any rtl, so try directly generating the location
> description from the tree. */
> ! descr_list = loc_list_from_tree (decl, hidden_reference_p (decl) ? 0 : 2);
> ! if (descr_list)
> {
> descr = loc_by_reference (descr, decl);
> ! add_AT_location_description (die, attr, descr_list);
> return;
> }
> /* None of that worked, so it must not really have a location;
> *************** add_bound_info (dw_die_ref subrange_die,
> *** 13967,13973 ****
> case RESULT_DECL:
> {
> dw_die_ref decl_die = lookup_decl_die (bound);
> ! dw_loc_descr_ref loc;
>
> /* ??? Can this happen, or should the variable have been bound
> first? Probably it can, since I imagine that we try to create
> --- 14292,14298 ----
> case RESULT_DECL:
> {
> dw_die_ref decl_die = lookup_decl_die (bound);
> ! dw_loc_list_ref loc;
>
> /* ??? Can this happen, or should the variable have been bound
> first? Probably it can, since I imagine that we try to create
> *************** add_bound_info (dw_die_ref subrange_die,
> *** 13978,13984 ****
> add_AT_die_ref (subrange_die, bound_attr, decl_die);
> else
> {
> ! loc = loc_descriptor_from_tree_1 (bound, 0);
> add_AT_location_description (subrange_die, bound_attr, loc);
> }
> break;
> --- 14303,14309 ----
> add_AT_die_ref (subrange_die, bound_attr, decl_die);
> else
> {
> ! loc = loc_list_from_tree (bound, 0);
> add_AT_location_description (subrange_die, bound_attr, loc);
> }
> break;
> *************** add_bound_info (dw_die_ref subrange_die,
> *** 13990,13999 ****
> evaluate the value of the array bound. */
>
> dw_die_ref ctx, decl_die;
> ! dw_loc_descr_ref loc;
>
> ! loc = loc_descriptor_from_tree (bound);
> ! if (loc == NULL)
> break;
>
> if (current_function_decl == 0)
> --- 14315,14324 ----
> evaluate the value of the array bound. */
>
> dw_die_ref ctx, decl_die;
> ! dw_loc_list_ref list;
>
> ! list = loc_list_from_tree (bound, 2);
> ! if (list == NULL)
> break;
>
> if (current_function_decl == 0)
> *************** add_bound_info (dw_die_ref subrange_die,
> *** 14004,14010 ****
> decl_die = new_die (DW_TAG_variable, ctx, bound);
> add_AT_flag (decl_die, DW_AT_artificial, 1);
> add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
> ! add_AT_loc (decl_die, DW_AT_location, loc);
>
> add_AT_die_ref (subrange_die, bound_attr, decl_die);
> break;
> --- 14329,14338 ----
> decl_die = new_die (DW_TAG_variable, ctx, bound);
> add_AT_flag (decl_die, DW_AT_artificial, 1);
> add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
> ! if (list->dw_loc_next)
> ! add_AT_loc_list (decl_die, DW_AT_location, list);
> ! else
> ! add_AT_loc (decl_die, DW_AT_location, list->expr);
>
> add_AT_die_ref (subrange_die, bound_attr, decl_die);
> break;
> *************** gen_array_type_die (tree type, dw_die_re
> *** 14610,14621 ****
> && DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
> {
> tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> ! dw_loc_descr_ref loc = loc_descriptor_from_tree (szdecl);
>
> size = int_size_in_bytes (TREE_TYPE (szdecl));
> if (loc && size > 0)
> {
> ! add_AT_loc (array_die, DW_AT_string_length, loc);
> if (size != DWARF2_ADDR_SIZE)
> add_AT_unsigned (array_die, DW_AT_byte_size, size);
> }
> --- 14938,14949 ----
> && DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
> {
> tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
> ! dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2);
>
> size = int_size_in_bytes (TREE_TYPE (szdecl));
> if (loc && size > 0)
> {
> ! add_AT_location_description (array_die, DW_AT_string_length, loc);
> if (size != DWARF2_ADDR_SIZE)
> add_AT_unsigned (array_die, DW_AT_byte_size, size);
> }
> *************** descr_info_loc (tree val, tree base_decl
> *** 14709,14715 ****
> CASE_CONVERT:
> return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
> case VAR_DECL:
> ! return loc_descriptor_from_tree_1 (val, 0);
> case INTEGER_CST:
> if (host_integerp (val, 0))
> return int_loc_descriptor (tree_low_cst (val, 0));
> --- 15037,15043 ----
> CASE_CONVERT:
> return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
> case VAR_DECL:
> ! return loc_descriptor_from_tree (val, 0);
> case INTEGER_CST:
> if (host_integerp (val, 0))
> return int_loc_descriptor (tree_low_cst (val, 0));
> *************** gen_subprogram_die (tree decl, dw_die_re
> *** 15467,15473 ****
>
> if (cfun->static_chain_decl)
> add_AT_location_description (subr_die, DW_AT_static_link,
> ! loc_descriptor_from_tree (cfun->static_chain_decl));
> }
>
> /* Generate child dies for template paramaters. */
> --- 15795,15801 ----
>
> if (cfun->static_chain_decl)
> add_AT_location_description (subr_die, DW_AT_static_link,
> ! loc_list_from_tree (cfun->static_chain_decl, 2));
> }
>
> /* Generate child dies for template paramaters. */
> *************** gen_variable_die (tree decl, tree origin
> *** 15637,15643 ****
> {
> tree field;
> dw_die_ref com_die;
> ! dw_loc_descr_ref loc;
> die_node com_die_arg;
>
> var_die = lookup_decl_die (decl_or_origin);
> --- 15965,15971 ----
> {
> tree field;
> dw_die_ref com_die;
> ! dw_loc_list_ref loc;
> die_node com_die_arg;
>
> var_die = lookup_decl_die (decl_or_origin);
> *************** gen_variable_die (tree decl, tree origin
> *** 15645,15666 ****
> {
> if (get_AT (var_die, DW_AT_location) == NULL)
> {
> ! loc = loc_descriptor_from_tree (com_decl);
> if (loc)
> {
> if (off)
> {
> /* Optimize the common case. */
> ! if (loc->dw_loc_opc == DW_OP_addr
> ! && loc->dw_loc_next == NULL
> ! && GET_CODE (loc->dw_loc_oprnd1.v.val_addr)
> == SYMBOL_REF)
> ! loc->dw_loc_oprnd1.v.val_addr
> ! = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
> else
> ! loc_descr_plus_const (&loc, off);
> }
> ! add_AT_loc (var_die, DW_AT_location, loc);
> remove_AT (var_die, DW_AT_declaration);
> }
> }
> --- 15973,15995 ----
> {
> if (get_AT (var_die, DW_AT_location) == NULL)
> {
> ! loc = loc_list_from_tree (com_decl, off ? 1 : 2);
> if (loc)
> {
> if (off)
> {
> /* Optimize the common case. */
> ! if (single_element_loc_list_p (loc)
> ! && loc->expr->dw_loc_opc == DW_OP_addr
> ! && loc->expr->dw_loc_next == NULL
> ! && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr)
> == SYMBOL_REF)
> ! loc->expr->dw_loc_oprnd1.v.val_addr
> ! = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
> else
> ! loc_list_plus_const (loc, off);
> }
> ! add_AT_location_description (var_die, DW_AT_location, loc);
> remove_AT (var_die, DW_AT_declaration);
> }
> }
> *************** gen_variable_die (tree decl, tree origin
> *** 15676,15682 ****
> com_die_arg.decl_id = DECL_UID (com_decl);
> com_die_arg.die_parent = context_die;
> com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
> ! loc = loc_descriptor_from_tree (com_decl);
> if (com_die == NULL)
> {
> const char *cnam
> --- 16005,16011 ----
> com_die_arg.decl_id = DECL_UID (com_decl);
> com_die_arg.die_parent = context_die;
> com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
> ! loc = loc_list_from_tree (com_decl, 2);
> if (com_die == NULL)
> {
> const char *cnam
> *************** gen_variable_die (tree decl, tree origin
> *** 15687,15696 ****
> add_name_and_src_coords_attributes (com_die, com_decl);
> if (loc)
> {
> ! add_AT_loc (com_die, DW_AT_location, loc);
> /* Avoid sharing the same loc descriptor between
> DW_TAG_common_block and DW_TAG_variable. */
> ! loc = loc_descriptor_from_tree (com_decl);
> }
> else if (DECL_EXTERNAL (decl))
> add_AT_flag (com_die, DW_AT_declaration, 1);
> --- 16016,16025 ----
> add_name_and_src_coords_attributes (com_die, com_decl);
> if (loc)
> {
> ! add_AT_location_description (com_die, DW_AT_location, loc);
> /* Avoid sharing the same loc descriptor between
> DW_TAG_common_block and DW_TAG_variable. */
> ! loc = loc_list_from_tree (com_decl, 2);
> }
> else if (DECL_EXTERNAL (decl))
> add_AT_flag (com_die, DW_AT_declaration, 1);
> *************** gen_variable_die (tree decl, tree origin
> *** 15701,15708 ****
> }
> else if (get_AT (com_die, DW_AT_location) == NULL && loc)
> {
> ! add_AT_loc (com_die, DW_AT_location, loc);
> ! loc = loc_descriptor_from_tree (com_decl);
> remove_AT (com_die, DW_AT_declaration);
> }
> var_die = new_die (DW_TAG_variable, com_die, decl);
> --- 16030,16037 ----
> }
> else if (get_AT (com_die, DW_AT_location) == NULL && loc)
> {
> ! add_AT_location_description (com_die, DW_AT_location, loc);
> ! loc = loc_list_from_tree (com_decl, 2);
> remove_AT (com_die, DW_AT_declaration);
> }
> var_die = new_die (DW_TAG_variable, com_die, decl);
> *************** gen_variable_die (tree decl, tree origin
> *** 15715,15729 ****
> if (off)
> {
> /* Optimize the common case. */
> ! if (loc->dw_loc_opc == DW_OP_addr
> ! && loc->dw_loc_next == NULL
> ! && GET_CODE (loc->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
> ! loc->dw_loc_oprnd1.v.val_addr
> ! = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
> else
> ! loc_descr_plus_const (&loc, off);
> }
> ! add_AT_loc (var_die, DW_AT_location, loc);
> }
> else if (DECL_EXTERNAL (decl))
> add_AT_flag (var_die, DW_AT_declaration, 1);
> --- 16044,16059 ----
> if (off)
> {
> /* Optimize the common case. */
> ! if (single_element_loc_list_p (loc)
> ! && loc->expr->dw_loc_opc == DW_OP_addr
> ! && loc->expr->dw_loc_next == NULL
> ! && GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
> ! loc->expr->dw_loc_oprnd1.v.val_addr
> ! = plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
> else
> ! loc_list_plus_const (loc, off);
> }
> ! add_AT_location_description (var_die, DW_AT_location, loc);
> }
> else if (DECL_EXTERNAL (decl))
> add_AT_flag (var_die, DW_AT_declaration, 1);
> *************** gen_variable_die (tree decl, tree origin
> *** 15786,15795 ****
> tree type = TREE_TYPE (decl);
>
> add_name_and_src_coords_attributes (var_die, decl);
> ! if ((TREE_CODE (decl) == PARM_DECL
> ! || TREE_CODE (decl) == RESULT_DECL
> ! || TREE_CODE (decl) == VAR_DECL)
> ! && DECL_BY_REFERENCE (decl))
> add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
> else
> add_type_attribute (var_die, type, TREE_READONLY (decl),
> --- 16116,16122 ----
> tree type = TREE_TYPE (decl);
>
> add_name_and_src_coords_attributes (var_die, decl);
> ! if (hidden_reference_p (decl))
> add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
> else
> add_type_attribute (var_die, type, TREE_READONLY (decl),
> Index: Makefile.in
> ===================================================================
> *** Makefile.in (revision 151743)
> --- Makefile.in (working copy)
> *************** dwarf2out.o : dwarf2out.c $(CONFIG_H) $(
> *** 2731,2737 ****
> output.h $(DIAGNOSTIC_H) $(REAL_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
> libfuncs.h $(TOPLEV_H) dwarf2out.h reload.h $(GGC_H) $(EXCEPT_H) dwarf2asm.h \
> $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) \
> ! $(MD5_H) $(INPUT_H) $(FUNCTION_H) $(VARRAY_H)
> dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
> $(FLAGS_H) $(RTL_H) $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) \
> gt-dwarf2asm.h $(DWARF2_H) $(SPLAY_TREE_H) $(TARGET_H)
> --- 2731,2737 ----
> output.h $(DIAGNOSTIC_H) $(REAL_H) hard-reg-set.h $(REGS_H) $(EXPR_H) \
> libfuncs.h $(TOPLEV_H) dwarf2out.h reload.h $(GGC_H) $(EXCEPT_H) dwarf2asm.h \
> $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) \
> ! $(MD5_H) $(INPUT_H) $(FUNCTION_H) $(VARRAY_H) $(GIMPLE_H) $(TREE_PASS_H)
> dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
> $(FLAGS_H) $(RTL_H) $(TREE_H) output.h dwarf2asm.h $(TM_P_H) $(GGC_H) \
> gt-dwarf2asm.h $(DWARF2_H) $(SPLAY_TREE_H) $(TARGET_H)
>
>
--
Richard Guenther <rguenther@suse.de>
Novell / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 - GF: Markus Rex