+ /* See if we possibly have multiple locations for this variable. */
+ loc_list = lookup_decl_loc (decl);
+
+ /* If it truly has multiple locations, the first and last node will
+ differ. */
+ if (loc_list && loc_list->first != loc_list->last)
+ {
+ const char *secname;
+ const char *endname;
+ dw_loc_list_ref list;
+ rtx varloc;
+ struct var_loc_node *node;
+
+ /* We need to figure out what section we should use as the base
+ for the address ranges where a given location is valid.
+ 1. If this particular DECL has a section associated with it,
+ use that.
+ 2. If this function has a section associated with it, use
+ that.
+ 3. Otherwise, use the text section.
+ XXX: If you split a variable across multiple sections, this
+ won't notice. */
+
+ if (DECL_SECTION_NAME (decl))
+ {
+ tree sectree = DECL_SECTION_NAME (decl);
+ secname = TREE_STRING_POINTER (sectree);
+ }
+ else if (current_function_decl
+ && DECL_SECTION_NAME (current_function_decl))
+ {
+ tree sectree = DECL_SECTION_NAME (current_function_decl);
+ secname = TREE_STRING_POINTER (sectree);
+ }
+ else
+ secname = text_section_label;
+
+ /* Now that we know what section we are using for a base,
+ actually construct the list of locations.
+ The first location information is what is passed to the
+ function that creates the location list, and the remaining
+ locations just get added on to that list.
+ Note that we only know the start address for a location
+ (IE location changes), so to build the range, we use
+ the range [current location start, next location start].
+ This means we have to special case the last node, and generate
+ a range of [last location start, end of function label]. */
+
+ node = loc_list->first;
+ varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+ list = new_loc_list (loc_descriptor (varloc, attr != DW_AT_frame_base),
+ node->label, node->next->label, secname, 1);
+ node = node->next;
+
+ for (; node->next; node = node->next)
+ if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
+ {
+ /* The variable has a location between NODE->LABEL and
+ NODE->NEXT->LABEL. */
+ varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+ add_loc_descr_to_loc_list (&list,
+ loc_descriptor (varloc,
+ attr != DW_AT_frame_base),
+ node->label, node->next->label, secname);
+ }
+
+ /* If the variable has a location at the last label
+ it keeps its location until the end of function. */
+ if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
+ {
+ char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
+
+ varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+ if (!current_function_decl)
+ endname = text_end_label;
+ else
+ {
+ ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
+ current_function_funcdef_no);
+ endname = ggc_strdup (label_id);
+ }
+ add_loc_descr_to_loc_list (&list,
+ loc_descriptor (varloc,
+ attr != DW_AT_frame_base),
+ node->label, endname, secname);
+ }
+
+ /* Finally, add the location list to the DIE, and we are done. */
+ add_AT_loc_list (die, attr, list);
+ return;
+ }
+