Jakub,
First, thank you very much for reviewing this set of patches.
I think it's better to start with an answer to your last mail:
On 10/03/2014 11:20 AM, Jakub Jelinek wrote:
What kind of more complex expressions do you need and why?
GNAT can produce array types that make sense only as part of a record
type and whose bounds are equal to members of this record type. Such
ARRAY_TYPE nodes get generated from the kind of example you could see on
the Dwarf-Discuss mailing list:
type Array_Type is array (Integer range <>) of Integer;
type Record_Type (N : Integer) is record
A : Array_Type (1 .. N);
end record;
In this case, the "A" field's type is an ARRAY_TYPE node whose upper
bound is:
COMPONENT_REF (PLACEHOLDER_EXPR (<Record_Type>),
FIELD_DECL("N"))
Upcoming patches will actually extend the need to handle more complex
expressions: Ada arrays can contain dynamically-sized objects (their
size is bounded, though). As a consequence, debuggers need these arrays
to have a DW_AT_byte_stride attribute in order to decode them. The size
expressions that describe the array stride in GCC can contain fairly
complex operations such as unsigned divisions, unsigned comparisons,
bitwise operations, calls to size functions (see
stor-layout.c:self_referencial_size).
On 10/03/2014 11:18 AM, Jakub Jelinek wrote:
+ /* Instead of producing a dedicated DW_TAG_array_type DIE for this type, let
+ the circuitry wrap the main variant with DIEs for qualifiers (for
+ instance: DW_TAG_const_type, ...). */
+ if (type != TYPE_MAIN_VARIANT (type))
+ {
+ gen_type_die (TYPE_MAIN_VARIANT (type), context_die);
+ return;
+ }
I don't like this, can you explain why? I'd say that if you only
want to see TYPE_MAIN_VARIANT here, it should be responsibility of
the callers to ensure that.
Agreed. I have updated the patch to:
1. remove this hunk;
2. in gen_type_die_with_usage, which is the only caller, move the
type_main_variant call on "type" right before the array descriptors
handling.
@@ -19941,7 +19991,8 @@ gen_type_die_with_usage (tree type, dw_die_ref
context_die,
/* If this is an array type with hidden descriptor, handle itfirst. */
if (!TREE_ASM_WRITTEN (type)
&& lang_hooks.types.get_array_descr_info
- && lang_hooks.types.get_array_descr_info (type, &info)
+ && lang_hooks.types.get_array_descr_info (type,
+ init_array_descr_info (&info))
Just memset it to 0 instead?
Sure. I was not sure about whether is was considered good style, but
it's done, now.
+ enum array_descr_ordering ordering;
tree element_type;
tree base_decl;
tree data_location;
tree allocated;
tree associated;
+
Why the extra vertical space?
struct array_descr_dimen
{
It made the separation between "global" and "dimension-local"
information clearer to me. As I suppose you don't like it and as there
is already one indentation level, I removed it.
* dwarf2out.c (gen_type_die_with_usage): Enable the array lang-hook
even when (dwarf_version < 3 && dwarf_strict).
(gen_descr_array_die): Do not output DW_AT_data_locationn,
DW_AT_associated, DW_AT_allocated and DW_AT_byte_stride DWARF
attributes when (dwarf_version < 3 && dwarf_strict).
This patch sounds very wrong. DW_OP_push_object_address is not in DWARF2
either, and that is the basis of all the fields, so there is reallynothing
you can really output correctly for DWARF2. It isn't the default on sane
targets, where GCC defaults to DWARF4 these days, so why bother?
Generating DW_OP_push_object_address in strict DWARF2 mode is indeed a
bug (patch is adjusted). However, if I understand correctly all
fields/attributes don't have to rely on it.
In the case of the first Ada example I quoted above, such an operation
would not be emitted: instead, add_bound_info/add_scalar_info are going
to output a DW_AT_upper_bound attribute that is a reference to another
DIE. This is valid DWARF2 and, I think, justifies enabling the language
hook in this case.
We have several platforms whose default to strict DWARF2. These are
quite used platforms on which some DWARF consumers crash when provided
DIEs and tags they do not handle.
gcc/fortran/
* trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR nodes
instead of VAR_DECL ones in type-related expressions. Remove base_decl
initialization.
Ugh, I must say I don't like PLACEHOLDER_EXPRs at all.
Why so? I know that as far as supported front-ends are concerned,
PLACEHOLDE_EXPR nodes are used only in GNAT, but it seems to me they
describe the best what object the bound/stride/allocated/associated
expressions (self-)reference.
I have attached to this mail the 3 patches that are updated thanks to
your (Jakub and Jason's) comments and run successfuly the GCC testsuite
on x86_64-pc-linux-gnu.
Thanks again for revewing!
--
Pierre-Marie de Rodat
>From 5ae605a24f0df5a8963fa84d0c07c278542977f1 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <dero...@adacore.com>
Date: Wed, 5 Feb 2014 12:00:02 +0100
Subject: [PATCH 1/5] Complete information generated through the array
descriptor language hook
gcc/
* dwarf2out.h (enum array_descr_ordering): New.
(array_descr_dimen): Add a bounds_type structure field.
(struct array_descr_info): Add a field to hold index type information
and another one to hold ordering information.
* dwarf2out.c (gen_type_die_with_usage): Get the main variant before
invoking the array descriptor language hook. Initialize the
array_descr_info structure before calling the lang-hook.
(gen_descr_array_type_die): Use gen_type_die if not processing the
main type variant. Replace Fortran-specific code with generic one
using this new field. Add a GNAT descriptive type, if any. Output
type information for the array bound subrange, if any.
gcc/fortran
* trans-types.c (gfc_get_array_descr_info): Describe all Fortran
arrays with column major ordering.
---
gcc/dwarf2out.c | 52 +++++++++++++++++++++++++++++----------------
gcc/dwarf2out.h | 12 +++++++++++
gcc/fortran/trans-types.c | 1 +
3 files changed, 47 insertions(+), 18 deletions(-)
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 59c05ed..39b859e 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -17401,18 +17401,25 @@ static void
gen_descr_array_type_die (tree type, struct array_descr_info *info,
dw_die_ref context_die)
{
- dw_die_ref scope_die = scope_die_for (type, context_die);
- dw_die_ref array_die;
+ const dw_die_ref scope_die = scope_die_for (type, context_die);
+ const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type);
int dim;
- array_die = new_die (DW_TAG_array_type, scope_die, type);
add_name_attribute (array_die, type_tag (type));
equate_type_number_to_die (type, array_die);
- /* For Fortran multidimensional arrays use DW_ORD_col_major ordering. */
- if (is_fortran ()
- && info->ndimensions >= 2)
- add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+ if (info->ndimensions > 1)
+ switch (info->ordering)
+ {
+ case array_descr_ordering_row_major:
+ add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major);
+ break;
+ case array_descr_ordering_column_major:
+ add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+ break;
+ default:
+ break;
+ }
if (info->data_location)
add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
@@ -17424,11 +17431,17 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
info->base_decl);
+ add_gnat_descriptive_type_attribute (array_die, type, context_die);
+
for (dim = 0; dim < info->ndimensions; dim++)
{
dw_die_ref subrange_die
= new_die (DW_TAG_subrange_type, array_die, NULL);
+ if (info->dimen[dim].bounds_type)
+ add_type_attribute (subrange_die,
+ info->dimen[dim].bounds_type, 0,
+ context_die);
if (info->dimen[dim].lower_bound)
{
/* If it is the default value, omit it. */
@@ -19986,17 +19999,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
return;
}
- /* If this is an array type with hidden descriptor, handle it first. */
- if (!TREE_ASM_WRITTEN (type)
- && lang_hooks.types.get_array_descr_info
- && lang_hooks.types.get_array_descr_info (type, &info)
- && (dwarf_version >= 3 || !dwarf_strict))
- {
- gen_descr_array_type_die (type, &info, context_die);
- TREE_ASM_WRITTEN (type) = 1;
- return;
- }
-
/* We are going to output a DIE to represent the unqualified version
of this type (i.e. without any const or volatile qualifiers) so
get the main variant (i.e. the unqualified version) of this type
@@ -20005,6 +20007,20 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
if (TREE_CODE (type) != VECTOR_TYPE)
type = type_main_variant (type);
+ /* If this is an array type with hidden descriptor, handle it first. */
+ if (!TREE_ASM_WRITTEN (type)
+ && lang_hooks.types.get_array_descr_info
+ && (dwarf_version >= 3 || !dwarf_strict))
+ {
+ memset (&info, 0, sizeof (info));
+ if (lang_hooks.types.get_array_descr_info (type, &info))
+ {
+ gen_descr_array_type_die (type, &info, context_die);
+ TREE_ASM_WRITTEN (type) = 1;
+ return;
+ }
+ }
+
if (TREE_ASM_WRITTEN (type))
return;
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 7843e0a..0cf290c 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -261,9 +261,17 @@ extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *));
extern void dwarf2out_vms_debug_main_pointer (void);
#endif
+enum array_descr_ordering
+{
+ array_descr_ordering_default,
+ array_descr_ordering_row_major,
+ array_descr_ordering_column_major
+};
+
struct array_descr_info
{
int ndimensions;
+ enum array_descr_ordering ordering;
tree element_type;
tree base_decl;
tree data_location;
@@ -271,6 +279,10 @@ struct array_descr_info
tree associated;
struct array_descr_dimen
{
+ /* GCC uses sizetype for array indices, so lower_bound and upper_bound
+ will likely be "sizetype" values. However, bounds may have another
+ type in the original source code. */
+ tree bounds_type;
tree lower_bound;
tree upper_bound;
tree stride;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 6bfe14c..1bfe920 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3036,6 +3036,7 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
memset (info, '\0', sizeof (*info));
info->ndimensions = rank;
+ info->ordering = array_descr_ordering_column_major;
info->element_type = etype;
ptype = build_pointer_type (gfc_array_index_type);
base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
--
1.7.10.4
>From a292821505560a7a27b7446db6ed439360da940b Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <dero...@adacore.com>
Date: Fri, 7 Feb 2014 16:09:21 +0100
Subject: [PATCH 2/5] Enable the array descr language hook for all DWARF
versions
* dwarf2out.c (gen_type_die_with_usage): Enable the array lang-hook
even when (dwarf_version < 3 && dwarf_strict).
(gen_descr_array_die): Do not output DW_AT_data_locationn,
DW_AT_associated, DW_AT_allocated and DW_AT_byte_stride DWARF
attributes when (dwarf_version < 3 && dwarf_strict).
---
gcc/dwarf2out.c | 34 ++++++++++++++++++++--------------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 39b859e..79cd8f5 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -17421,15 +17421,19 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
break;
}
- if (info->data_location)
- add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
- info->base_decl);
- if (info->associated)
- add_descr_info_field (array_die, DW_AT_associated, info->associated,
- info->base_decl);
- if (info->allocated)
- add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
- info->base_decl);
+ if (dwarf_version >= 3 || !dwarf_strict)
+ {
+ if (info->data_location)
+ add_descr_info_field (array_die, DW_AT_data_location,
+ info->data_location,
+ info->base_decl);
+ if (info->associated)
+ add_descr_info_field (array_die, DW_AT_associated, info->associated,
+ info->base_decl);
+ if (info->allocated)
+ add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
+ info->base_decl);
+ }
add_gnat_descriptive_type_attribute (array_die, type, context_die);
@@ -17460,10 +17464,13 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
add_descr_info_field (subrange_die, DW_AT_upper_bound,
info->dimen[dim].upper_bound,
info->base_decl);
- if (info->dimen[dim].stride)
- add_descr_info_field (subrange_die, DW_AT_byte_stride,
- info->dimen[dim].stride,
- info->base_decl);
+ if (dwarf_version >= 3 || !dwarf_strict)
+ {
+ if (info->dimen[dim].stride)
+ add_descr_info_field (subrange_die, DW_AT_byte_stride,
+ info->dimen[dim].stride,
+ info->base_decl);
+ }
}
gen_type_die (info->element_type, context_die);
@@ -20010,7 +20017,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
/* If this is an array type with hidden descriptor, handle it first. */
if (!TREE_ASM_WRITTEN (type)
&& lang_hooks.types.get_array_descr_info
- && (dwarf_version >= 3 || !dwarf_strict))
{
memset (&info, 0, sizeof (info));
if (lang_hooks.types.get_array_descr_info (type, &info))
--
1.7.10.4
>From 7e09d1d93f8edcc556b21e4f39fcb3d3252b4f31 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <dero...@adacore.com>
Date: Mon, 9 Jun 2014 15:13:45 +0200
Subject: [PATCH 5/5] dwarf2out.c: do not short-circuit add_bound_info in
array descr. lang-hook
gcc/
* dwarf2out.h (struct array_descr_info): Remove the base_decl field.
* dwarf2out.c (enum dw_scalar_form): New.
(add_scalar_info): New.
(loc_list_from_tree): Handle PLACEHOLDER_EXPR nodes for type-related
expressions.
(add_bound_info): Use add_scalar_info.
(descr_info_loc): Remove.
(add_descr_info_field): Remove.
(gen_descr_array_type_die): Switch add_descr_info_field calls into
add_scalar_info/add_bound_info ones.
gcc/ada
* gcc-interface/misc.c (gnat_get_array_descr_info): Remove base_decl
initialization.
gcc/fortran/
* trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR
nodes instead of VAR_DECL ones in type-related expressions. Remove
base_decl initialization.
---
gcc/ada/gcc-interface/misc.c | 1 -
gcc/dwarf2out.c | 438 ++++++++++++++++++++----------------------
gcc/dwarf2out.h | 1 -
gcc/fortran/trans-types.c | 7 +-
4 files changed, 208 insertions(+), 239 deletions(-)
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 7449ef9..0661d49 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -658,7 +658,6 @@ gnat_get_array_descr_info (const_tree type, struct array_descr_info *info)
info->ordering = (convention_fortran_p
? array_descr_ordering_column_major
: array_descr_ordering_row_major);
- info->base_decl = NULL_TREE;
info->data_location = NULL_TREE;
info->allocated = NULL_TREE;
info->associated = NULL_TREE;
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c334e9f..bd5fee2 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2981,6 +2981,15 @@ static bool frame_pointer_fb_offset_valid;
static vec<dw_die_ref> base_types;
+/* Flags to represent a set of attribute classes for attributes that represent
+ a scalar value (bounds, pointers, ...). */
+enum dw_scalar_form
+{
+ dw_scalar_form_constant = 0x01,
+ dw_scalar_form_exprloc = 0x02,
+ dw_scalar_form_reference = 0x04
+};
+
/* Forward declarations for functions defined in this file. */
static int is_pseudo_reg (const_rtx);
@@ -3186,6 +3195,7 @@ static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
static void add_name_attribute (dw_die_ref, const char *);
static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
static void add_comp_dir_attribute (dw_die_ref);
+static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int);
static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
static void add_subscript_info (dw_die_ref, tree, bool);
static void add_byte_size_attribute (dw_die_ref, tree);
@@ -14319,11 +14329,24 @@ loc_list_from_tree (tree loc, int want_address)
case PLACEHOLDER_EXPR:
/* This case involves extracting fields from an object to determine the
- 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;
+ position of other fields. It is supposed to appear only as the first
+ operand of COMPONENT_REF nodes. */
+ if (TREE_CODE (TREE_TYPE (loc)) == RECORD_TYPE
+ && want_address >= 1)
+ {
+ if (dwarf_version >= 3 || !dwarf_strict)
+ {
+ ret = new_loc_descr (DW_OP_push_object_address, 0, 0);
+ have_address = 1;
+ break;
+ }
+ else
+ return NULL;
+ }
+ else
+ expansion_failed (loc, NULL_RTX,
+ "PLACEHOLDER_EXPR for a non-structure");
+ break;
case CALL_EXPR:
expansion_failed (loc, NULL_RTX, "CALL_EXPR");
@@ -16432,6 +16455,141 @@ add_comp_dir_attribute (dw_die_ref die)
add_AT_string (die, DW_AT_comp_dir, wd);
}
+/* Given a tree node VALUE describing a scalar attribute ATTR (i.e. a bound, a
+ pointer computation, ...), output a representation for that bound according
+ to the accepted FORMS (see enum dw_scalar_form) and add it to DIE. */
+
+static void
+add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
+ int forms)
+{
+ dw_die_ref ctx, decl_die;
+ dw_loc_list_ref list;
+
+ bool strip_conversions = true;
+
+ while (strip_conversions)
+ switch (TREE_CODE (value))
+ {
+ case ERROR_MARK:
+ case SAVE_EXPR:
+ return;
+
+ CASE_CONVERT:
+ case VIEW_CONVERT_EXPR:
+ value = TREE_OPERAND (value, 0);
+ break;
+
+ default:
+ strip_conversions = false;
+ break;
+ }
+
+ /* If possible and permitted, output the attribute as a constant. */
+ if ((forms & dw_scalar_form_constant) != 0
+ && TREE_CODE (value) == INTEGER_CST)
+ {
+ unsigned int prec = simple_type_size_in_bits (TREE_TYPE (value));
+
+ /* If HOST_WIDE_INT is big enough then represent the bound as
+ a constant value. We need to choose a form based on
+ whether the type is signed or unsigned. We cannot just
+ call add_AT_unsigned if the value itself is positive
+ (add_AT_unsigned might add the unsigned value encoded as
+ DW_FORM_data[1248]). Some DWARF consumers will lookup the
+ bounds type and then sign extend any unsigned values found
+ for signed types. This is needed only for
+ DW_AT_{lower,upper}_bound, since for most other attributes,
+ consumers will treat DW_FORM_data[1248] as unsigned values,
+ regardless of the underlying type. */
+ if (prec <= HOST_BITS_PER_WIDE_INT
+ || tree_fits_uhwi_p (value))
+ {
+ if (TYPE_UNSIGNED (TREE_TYPE (value)))
+ add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value));
+ else
+ add_AT_int (die, attr, TREE_INT_CST_LOW (value));
+ }
+ else
+ /* Otherwise represent the bound as an unsigned value with
+ the precision of its type. The precision and signedness
+ of the type will be necessary to re-interpret it
+ unambiguously. */
+ add_AT_wide (die, attr, value);
+ }
+
+ /* Otherwise, if it's possible and permitted too, output a reference to
+ another DIE. */
+ if ((forms & dw_scalar_form_reference) != 0)
+ {
+ tree decl = NULL_TREE;
+
+ /* Some type attributes reference an outer type. For instance, the upper
+ bound of an array may reference an embedding record (this happens in
+ Ada). */
+ if (TREE_CODE (value) == COMPONENT_REF
+ && TREE_CODE (TREE_OPERAND (value, 0)) == PLACEHOLDER_EXPR
+ && TREE_CODE (TREE_OPERAND (value, 1)) == FIELD_DECL)
+ decl = TREE_OPERAND (value, 1);
+
+ else if (TREE_CODE (value) == VAR_DECL
+ || TREE_CODE (value) == PARM_DECL
+ || TREE_CODE (value) == RESULT_DECL)
+ decl = value;
+
+ if (decl != NULL_TREE)
+ {
+ dw_die_ref decl_die = lookup_decl_die (decl);
+
+ /* ??? Can this happen, or should the variable have been bound
+ first? Probably it can, since I imagine that we try to create
+ the types of parameters in the order in which they exist in
+ the list, and won't have created a forward reference to a
+ later parameter. */
+ if (decl_die != NULL)
+ {
+ add_AT_die_ref (die, attr, decl_die);
+ return;
+ }
+ }
+ }
+
+ /* Last chance: try to create a stack operation procedure to evaluate the
+ value. Do nothing if even that is not possible or permitted. */
+ if ((forms & dw_scalar_form_exprloc) == 0)
+ return;
+
+ list = loc_list_from_tree (value, 2);
+ if (list == NULL || single_element_loc_list_p (list))
+ {
+ /* If this attribute is not a reference nor constant, it is
+ a DWARF expression rather than location description. For that
+ loc_list_from_tree (value, 0) is needed. */
+ dw_loc_list_ref list2 = loc_list_from_tree (value, 0);
+ if (list2 && single_element_loc_list_p (list2))
+ {
+ add_AT_loc (die, attr, list2->expr);
+ return;
+ }
+ }
+
+ /* If that failed to give a single element location list, fall back to
+ outputting this as a reference... still if permitted. */
+ if (list == NULL || (forms & dw_scalar_form_reference) == 0)
+ return;
+
+ if (current_function_decl == 0)
+ ctx = comp_unit_die ();
+ else
+ ctx = lookup_decl_die (current_function_decl);
+
+ decl_die = new_die (DW_TAG_variable, ctx, value);
+ add_AT_flag (decl_die, DW_AT_artificial, 1);
+ add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, ctx);
+ add_AT_location_description (decl_die, DW_AT_location, list);
+ add_AT_die_ref (die, attr, decl_die);
+}
+
/* Return the default for DW_AT_lower_bound, or -1 if there is not any
default. */
@@ -16473,121 +16631,40 @@ lower_bound_default (void)
a representation for that bound. */
static void
-add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
+add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
+ tree bound)
{
- switch (TREE_CODE (bound))
- {
- case ERROR_MARK:
- return;
+ int dflt;
- /* All fixed-bounds are represented by INTEGER_CST nodes. */
- case INTEGER_CST:
+ while (1)
+ switch (TREE_CODE (bound))
{
- unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
- int dflt;
+ /* Strip all conversions. */
+ CASE_CONVERT:
+ case VIEW_CONVERT_EXPR:
+ bound = TREE_OPERAND (bound, 0);
+ break;
- /* Use the default if possible. */
+ /* All fixed-bounds are represented by INTEGER_CST nodes. Lower bounds
+ are even omitted when they are the default. */
+ case INTEGER_CST:
+ /* If the value for this bound is the default one, we can even omit the
+ attribute. */
if (bound_attr == DW_AT_lower_bound
&& tree_fits_shwi_p (bound)
&& (dflt = lower_bound_default ()) != -1
&& tree_to_shwi (bound) == dflt)
- ;
-
- /* If HOST_WIDE_INT is big enough then represent the bound as
- a constant value. We need to choose a form based on
- whether the type is signed or unsigned. We cannot just
- call add_AT_unsigned if the value itself is positive
- (add_AT_unsigned might add the unsigned value encoded as
- DW_FORM_data[1248]). Some DWARF consumers will lookup the
- bounds type and then sign extend any unsigned values found
- for signed types. This is needed only for
- DW_AT_{lower,upper}_bound, since for most other attributes,
- consumers will treat DW_FORM_data[1248] as unsigned values,
- regardless of the underlying type. */
- else if (prec <= HOST_BITS_PER_WIDE_INT
- || tree_fits_uhwi_p (bound))
- {
- if (TYPE_UNSIGNED (TREE_TYPE (bound)))
- add_AT_unsigned (subrange_die, bound_attr,
- TREE_INT_CST_LOW (bound));
- else
- add_AT_int (subrange_die, bound_attr, TREE_INT_CST_LOW (bound));
- }
- else
- /* Otherwise represent the bound as an unsigned value with
- the precision of its type. The precision and signedness
- of the type will be necessary to re-interpret it
- unambiguously. */
- add_AT_wide (subrange_die, bound_attr, bound);
- }
- break;
-
- CASE_CONVERT:
- case VIEW_CONVERT_EXPR:
- add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
- break;
-
- case SAVE_EXPR:
- break;
-
- case VAR_DECL:
- case PARM_DECL:
- case RESULT_DECL:
- {
- dw_die_ref decl_die = lookup_decl_die (bound);
-
- /* ??? Can this happen, or should the variable have been bound
- first? Probably it can, since I imagine that we try to create
- the types of parameters in the order in which they exist in
- the list, and won't have created a forward reference to a
- later parameter. */
- if (decl_die != NULL)
- {
- add_AT_die_ref (subrange_die, bound_attr, decl_die);
- break;
- }
- }
- /* FALLTHRU */
-
- default:
- {
- /* Otherwise try to create a stack operation procedure to
- evaluate the value of the array bound. */
-
- dw_die_ref ctx, decl_die;
- dw_loc_list_ref list;
-
- list = loc_list_from_tree (bound, 2);
- if (list == NULL || single_element_loc_list_p (list))
- {
- /* If DW_AT_*bound is not a reference nor constant, it is
- a DWARF expression rather than location description.
- For that loc_list_from_tree (bound, 0) is needed.
- If that fails to give a single element list,
- fall back to outputting this as a reference anyway. */
- dw_loc_list_ref list2 = loc_list_from_tree (bound, 0);
- if (list2 && single_element_loc_list_p (list2))
- {
- add_AT_loc (subrange_die, bound_attr, list2->expr);
- break;
- }
- }
- if (list == NULL)
- break;
+ return;
- if (current_function_decl == 0)
- ctx = comp_unit_die ();
- else
- ctx = lookup_decl_die (current_function_decl);
+ /* FALLTHRU */
- 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), TYPE_QUAL_CONST, ctx);
- add_AT_location_description (decl_die, DW_AT_location, list);
- add_AT_die_ref (subrange_die, bound_attr, decl_die);
- break;
+ default:
+ add_scalar_info (subrange_die, bound_attr, bound,
+ dw_scalar_form_constant
+ | dw_scalar_form_exprloc
+ | dw_scalar_form_reference);
+ return;
}
- }
}
/* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
@@ -17375,99 +17452,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
add_pubtype (type, array_die);
}
-static dw_loc_descr_ref
-descr_info_loc (tree val, tree base_decl)
-{
- HOST_WIDE_INT size;
- dw_loc_descr_ref loc, loc2;
- enum dwarf_location_atom op;
-
- if (val == base_decl)
- return new_loc_descr (DW_OP_push_object_address, 0, 0);
-
- switch (TREE_CODE (val))
- {
- 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 (tree_fits_shwi_p (val))
- return int_loc_descriptor (tree_to_shwi (val));
- break;
- case INDIRECT_REF:
- size = int_size_in_bytes (TREE_TYPE (val));
- if (size < 0)
- break;
- loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
- if (!loc)
- break;
- if (size == DWARF2_ADDR_SIZE)
- add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0));
- else
- add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0));
- return loc;
- case POINTER_PLUS_EXPR:
- case PLUS_EXPR:
- if (tree_fits_uhwi_p (TREE_OPERAND (val, 1))
- && tree_to_uhwi (TREE_OPERAND (val, 1)) < 16384)
- {
- loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
- if (!loc)
- break;
- loc_descr_plus_const (&loc, tree_to_shwi (TREE_OPERAND (val, 1)));
- }
- else
- {
- op = DW_OP_plus;
- do_binop:
- loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
- if (!loc)
- break;
- loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl);
- if (!loc2)
- break;
- add_loc_descr (&loc, loc2);
- add_loc_descr (&loc2, new_loc_descr (op, 0, 0));
- }
- return loc;
- case MINUS_EXPR:
- op = DW_OP_minus;
- goto do_binop;
- case MULT_EXPR:
- op = DW_OP_mul;
- goto do_binop;
- case EQ_EXPR:
- op = DW_OP_eq;
- goto do_binop;
- case NE_EXPR:
- op = DW_OP_ne;
- goto do_binop;
- default:
- break;
- }
- return NULL;
-}
-
-static void
-add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr,
- tree val, tree base_decl)
-{
- dw_loc_descr_ref loc;
-
- if (tree_fits_shwi_p (val))
- {
- add_AT_unsigned (die, attr, tree_to_shwi (val));
- return;
- }
-
- loc = descr_info_loc (val, base_decl);
- if (!loc)
- return;
-
- add_AT_loc (die, attr, loc);
-}
-
/* This routine generates DIE for array with hidden descriptor, details
are filled into *info by a langhook. */
@@ -17498,15 +17482,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
if (dwarf_version >= 3 || !dwarf_strict)
{
if (info->data_location)
- add_descr_info_field (array_die, DW_AT_data_location,
- info->data_location,
- info->base_decl);
+ add_scalar_info (array_die, DW_AT_data_location, info->data_location,
+ dw_scalar_form_exprloc);
if (info->associated)
- add_descr_info_field (array_die, DW_AT_associated, info->associated,
- info->base_decl);
+ add_scalar_info (array_die, DW_AT_associated, info->associated,
+ dw_scalar_form_constant
+ | dw_scalar_form_exprloc
+ | dw_scalar_form_reference);
if (info->allocated)
- add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
- info->base_decl);
+ add_scalar_info (array_die, DW_AT_allocated, info->allocated,
+ dw_scalar_form_constant
+ | dw_scalar_form_exprloc
+ | dw_scalar_form_reference);
}
add_gnat_descriptive_type_attribute (array_die, type, context_die);
@@ -17521,30 +17508,17 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
info->dimen[dim].bounds_type, 0,
context_die);
if (info->dimen[dim].lower_bound)
- {
- /* If it is the default value, omit it. */
- int dflt;
-
- if (tree_fits_shwi_p (info->dimen[dim].lower_bound)
- && (dflt = lower_bound_default ()) != -1
- && tree_to_shwi (info->dimen[dim].lower_bound) == dflt)
- ;
- else
- add_descr_info_field (subrange_die, DW_AT_lower_bound,
- info->dimen[dim].lower_bound,
- info->base_decl);
- }
+ add_bound_info (subrange_die, DW_AT_lower_bound,
+ info->dimen[dim].lower_bound);
if (info->dimen[dim].upper_bound)
- add_descr_info_field (subrange_die, DW_AT_upper_bound,
- info->dimen[dim].upper_bound,
- info->base_decl);
- if (dwarf_version >= 3 || !dwarf_strict)
- {
- if (info->dimen[dim].stride)
- add_descr_info_field (subrange_die, DW_AT_byte_stride,
- info->dimen[dim].stride,
- info->base_decl);
- }
+ add_bound_info (subrange_die, DW_AT_upper_bound,
+ info->dimen[dim].upper_bound);
+ if ((dwarf_version >= 3 || !dwarf_strict) && info->dimen[dim].stride)
+ add_scalar_info (subrange_die, DW_AT_byte_stride,
+ info->dimen[dim].stride,
+ dw_scalar_form_constant
+ | dw_scalar_form_exprloc
+ | dw_scalar_form_reference);
}
gen_type_die (info->element_type, context_die);
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index a73fdb4..b37ba5c 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -274,7 +274,6 @@ struct array_descr_info
int ndimensions;
enum array_descr_ordering ordering;
tree element_type;
- tree base_decl;
tree data_location;
tree allocated;
tree associated;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 1bfe920..a108e81 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3042,13 +3042,10 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
if (!base_decl)
{
- base_decl = make_node (DEBUG_EXPR_DECL);
- DECL_ARTIFICIAL (base_decl) = 1;
- TREE_TYPE (base_decl) = indirect ? build_pointer_type (ptype) : ptype;
- DECL_MODE (base_decl) = TYPE_MODE (TREE_TYPE (base_decl));
+ base_decl = build0 (PLACEHOLDER_EXPR,
+ indirect ? build_pointer_type (ptype) : ptype);
GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
}
- info->base_decl = base_decl;
if (indirect)
base_decl = build1 (INDIRECT_REF, ptype, base_decl);
--
1.7.10.4