}
}
+#ifdef DWARF2_DEBUGGING_INFO
/* Add a constant OFFSET to a location list. */
static void
for (d = list_head; d != NULL; d = d->dw_loc_next)
loc_descr_plus_const (&d->expr, offset);
}
+#endif
/* Return the size of a location descriptor. */
static int is_base_type (tree);
static dw_die_ref subrange_type_die (tree, tree, tree, dw_die_ref);
static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
-static dw_die_ref generic_parameter_die (tree, tree, dw_die_ref, int);
+static dw_die_ref generic_parameter_die (tree, tree, bool, dw_die_ref);
+static dw_die_ref template_parameter_pack_die (tree, tree, dw_die_ref);
static int type_is_enum (const_tree);
static unsigned int dbx_reg_number (const_rtx);
static void add_loc_descr_op_piece (dw_loc_descr_ref *, int);
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 bool add_const_value_attribute (dw_die_ref, rtx);
static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
static void insert_float (const_rtx, unsigned char *);
static rtx rtl_for_decl_location (tree);
-static void add_location_or_const_value_attribute (dw_die_ref, tree,
+static bool add_location_or_const_value_attribute (dw_die_ref, tree,
enum dwarf_attribute);
-static void tree_add_const_value_attribute (dw_die_ref, tree);
-static void tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
+static bool tree_add_const_value_attribute (dw_die_ref, tree);
+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_comp_dir_attribute (dw_die_ref);
static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
static void gen_entry_point_die (tree, dw_die_ref);
#endif
static dw_die_ref gen_enumeration_type_die (tree, dw_die_ref);
-static dw_die_ref gen_formal_parameter_die (tree, tree, dw_die_ref);
+static dw_die_ref gen_formal_parameter_die (tree, tree, bool, dw_die_ref);
+static dw_die_ref gen_formal_parameter_pack_die (tree, tree, dw_die_ref, tree*);
static void gen_unspecified_parameters_die (tree, dw_die_ref);
static void gen_formal_types_die (tree, dw_die_ref);
static void gen_subprogram_die (tree, dw_die_ref);
static struct dwarf_file_data * lookup_filename (const char *);
static void retry_incomplete_types (void);
static void gen_type_die_for_member (tree, tree, dw_die_ref);
-static tree make_ith_pack_parameter_name (tree, int);
static void gen_generic_params_dies (tree);
static void splice_child_die (dw_die_ref, dw_die_ref);
static int file_info_cmp (const void *, const void *);
return "DW_TAG_condition";
case DW_TAG_shared_type:
return "DW_TAG_shared_type";
+ case DW_TAG_template_parameter_pack:
+ return "DW_TAG_template_parameter_pack";
+ case DW_TAG_formal_parameter_pack:
+ return "DW_TAG_formal_parameter_pack";
case DW_TAG_MIPS_loop:
return "DW_TAG_MIPS_loop";
case DW_TAG_format_label:
static inline var_loc_list *
lookup_decl_loc (const_tree decl)
{
+ if (!decl_loc_table)
+ return NULL;
return (var_loc_list *)
htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl));
}
case REAL_TYPE:
if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type)))
- encoding = DW_ATE_decimal_float;
+ {
+ if (dwarf_version >= 3 || !dwarf_strict)
+ encoding = DW_ATE_decimal_float;
+ else
+ encoding = DW_ATE_lo_user;
+ }
else
encoding = DW_ATE_float;
break;
case FIXED_POINT_TYPE:
- if (TYPE_UNSIGNED (type))
+ if (!(dwarf_version >= 3 || !dwarf_strict))
+ encoding = DW_ATE_lo_user;
+ else if (TYPE_UNSIGNED (type))
encoding = DW_ATE_unsigned_fixed;
else
encoding = DW_ATE_signed_fixed;
return mod_type_die;
}
-/* Generate a new name for the parameter pack name NAME (an
- IDENTIFIER_NODE) that incorporates its */
-
-static tree
-make_ith_pack_parameter_name (tree name, int i)
-{
- /* Munge the name to include the parameter index. */
-#define NUMBUF_LEN 128
- char numbuf[NUMBUF_LEN];
- char* newname;
- int newname_len;
-
- snprintf (numbuf, NUMBUF_LEN, "%i", i);
- newname_len = IDENTIFIER_LENGTH (name)
- + strlen (numbuf) + 2;
- newname = (char*) alloca (newname_len);
- snprintf (newname, newname_len,
- "%s#%i", IDENTIFIER_POINTER (name), i);
- return get_identifier (newname);
-}
-
/* Generate DIEs for the generic parameters of T.
T must be either a generic type or a generic function.
See http://gcc.gnu.org/wiki/TemplateParmsDwarf for more. */
args = lang_hooks.get_innermost_generic_args (t);
for (i = 0; i < parms_num; i++)
{
- tree parm, arg;
+ tree parm, arg, arg_pack_elems;
parm = TREE_VEC_ELT (parms, i);
arg = TREE_VEC_ELT (args, i);
+ arg_pack_elems = lang_hooks.types.get_argument_pack_elems (arg);
+ gcc_assert (parm && TREE_VALUE (parm) && arg);
+
if (parm && TREE_VALUE (parm) && arg)
{
- tree pack_elems =
- lang_hooks.types.get_argument_pack_elems (arg);
- if (pack_elems)
- {
- /* So ARG is an argument pack and the elements of that pack
- are stored in PACK_ELEMS. */
- int i, len;
-
- len = TREE_VEC_LENGTH (pack_elems);
- for (i = 0; i < len; i++)
- generic_parameter_die (TREE_VALUE (parm),
- TREE_VEC_ELT (pack_elems, i),
- die, i);
- }
- else /* Arg is not an argument pack. */
- generic_parameter_die (TREE_VALUE (parm),
- arg, die,
- -1/* Not a param pack. */);
+ /* If PARM represents a template parameter pack,
+ emit a DW_TAG_template_parameter_pack DIE, followed
+ by DW_TAG_template_*_parameter DIEs for the argument
+ pack elements of ARG. Note that ARG would then be
+ an argument pack. */
+ if (arg_pack_elems)
+ template_parameter_pack_die (TREE_VALUE (parm),
+ arg_pack_elems,
+ die);
+ else
+ generic_parameter_die (TREE_VALUE (parm), arg,
+ true /* Emit DW_AT_name */, die);
}
}
}
the representation of a generic type parameter.
For instance, in the C++ front end, PARM would be a template parameter.
ARG is the argument to PARM.
+ EMIT_NAME_P if tree, the DIE will have DW_AT_name attribute set to the
+ name of the PARM.
PARENT_DIE is the parent DIE which the new created DIE should be added to,
- as a child node.
- PACK_ELEM_INDEX is >= 0 if PARM is a generic parameter pack, and if ARG
- is one of the unpacked elements of the parameter PACK. In that case,
- PACK_ELEM_INDEX is the index of ARG in the parameter pack. */
+ as a child node. */
static dw_die_ref
-generic_parameter_die (tree parm, tree arg, dw_die_ref parent_die,
- int pack_elem_index)
+generic_parameter_die (tree parm, tree arg,
+ bool emit_name_p,
+ dw_die_ref parent_die)
{
dw_die_ref tmpl_die = NULL;
const char *name = NULL;
{
tree tmpl_type;
- if (pack_elem_index >= 0)
+ /* If PARM is a generic parameter pack, it means we are
+ emitting debug info for a template argument pack element.
+ In other terms, ARG is a template argument pack element.
+ In that case, we don't emit any DW_AT_name attribute for
+ the die. */
+ if (emit_name_p)
{
- /* PARM is an element of a parameter pack.
- Generate a name for it. */
- tree identifier = make_ith_pack_parameter_name (DECL_NAME (parm),
- pack_elem_index);
- if (identifier)
- name = IDENTIFIER_POINTER (identifier);
+ name = IDENTIFIER_POINTER (DECL_NAME (parm));
+ gcc_assert (name);
+ add_AT_string (tmpl_die, DW_AT_name, name);
}
- else
- name = IDENTIFIER_POINTER (DECL_NAME (parm));
-
- gcc_assert (name);
- add_AT_string (tmpl_die, DW_AT_name, name);
if (!lang_hooks.decls.generic_generic_parameter_decl_p (parm))
{
return tmpl_die;
}
+/* Generate and return a DW_TAG_template_parameter_pack DIE representing.
+ PARM_PACK must be a template parameter pack. The returned DIE
+ will be child DIE of PARENT_DIE. */
+
+static dw_die_ref
+template_parameter_pack_die (tree parm_pack,
+ tree parm_pack_args,
+ dw_die_ref parent_die)
+{
+ dw_die_ref die;
+ int j;
+
+ gcc_assert (parent_die
+ && parm_pack
+ && DECL_NAME (parm_pack));
+
+ die = new_die (DW_TAG_template_parameter_pack, parent_die, parm_pack);
+ add_AT_string (die, DW_AT_name, IDENTIFIER_POINTER (DECL_NAME (parm_pack)));
+
+ for (j = 0; j < TREE_VEC_LENGTH (parm_pack_args); j++)
+ generic_parameter_die (parm_pack,
+ TREE_VEC_ELT (parm_pack_args, j),
+ false /* Don't emit DW_AT_name */,
+ die);
+ return die;
+}
+
/* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is
an enumerated type. */
#endif
#ifdef DWARF2_DEBUGGING_INFO
+/* Return loc description representing "address" of integer value.
+ This can appear only as toplevel expression. */
+
+static dw_loc_descr_ref
+address_of_int_loc_descriptor (int size, HOST_WIDE_INT i)
+{
+ int litsize;
+ dw_loc_descr_ref loc_result = NULL;
+
+ if (!(dwarf_version >= 4 || !dwarf_strict))
+ return NULL;
+
+ if (i >= 0)
+ {
+ if (i <= 31)
+ litsize = 1;
+ else if (i <= 0xff)
+ litsize = 2;
+ else if (i <= 0xffff)
+ litsize = 3;
+ else if (HOST_BITS_PER_WIDE_INT == 32
+ || i <= 0xffffffff)
+ litsize = 5;
+ else
+ litsize = 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
+ }
+ else
+ {
+ if (i >= -0x80)
+ litsize = 2;
+ else if (i >= -0x8000)
+ litsize = 3;
+ else if (HOST_BITS_PER_WIDE_INT == 32
+ || i >= -0x80000000)
+ litsize = 5;
+ else
+ litsize = 1 + size_of_sleb128 (i);
+ }
+ /* Determine if DW_OP_stack_value or DW_OP_implicit_value
+ is more compact. For DW_OP_stack_value we need:
+ litsize + 1 (DW_OP_stack_value) + 1 (DW_OP_bit_size)
+ + 1 (mode size)
+ and for DW_OP_implicit_value:
+ 1 (DW_OP_implicit_value) + 1 (length) + mode_size. */
+ if ((int) DWARF2_ADDR_SIZE >= size
+ && litsize + 1 + 1 + 1 < 1 + 1 + size)
+ {
+ loc_result = int_loc_descriptor (i);
+ add_loc_descr (&loc_result,
+ new_loc_descr (DW_OP_stack_value, 0, 0));
+ add_loc_descr_op_piece (&loc_result, size);
+ return loc_result;
+ }
+
+ loc_result = new_loc_descr (DW_OP_implicit_value,
+ size, 0);
+ loc_result->dw_loc_oprnd2.val_class = dw_val_class_const;
+ loc_result->dw_loc_oprnd2.v.val_int = i;
+ return loc_result;
+}
/* Return a location descriptor that designates a base+offset location. */
rtl = XEXP (rtl, 0);
if (GET_MODE_SIZE (GET_MODE (rtl)) > DWARF2_ADDR_SIZE)
break;
-
- /* ... fall through ... */
+ mem_loc_result = mem_loc_descriptor (rtl, mode, initialized);
+ break;
case REG:
/* Whenever a register number forms a part of the description of the
break;
}
- symref:
mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl;
case PARITY:
case ASM_OPERANDS:
case UNSPEC:
+ case HIGH:
/* If delegitimize_address couldn't do anything with the UNSPEC, we
can't express it in the debug info. This can happen e.g. with some
TLS UNSPECs. */
break;
case CONST_STRING:
- rtl = get_debug_string_label (XSTR (rtl, 0));
- goto symref;
+ /* These can't easily be tracked, see PR41404. */
+ break;
default:
#ifdef ENABLE_CHECKING
break;
case CONST_INT:
- if (mode != VOIDmode && mode != BLKmode && dwarf_version >= 4)
- {
- HOST_WIDE_INT i = INTVAL (rtl);
- int litsize;
- if (i >= 0)
- {
- if (i <= 31)
- litsize = 1;
- else if (i <= 0xff)
- litsize = 2;
- else if (i <= 0xffff)
- litsize = 3;
- else if (HOST_BITS_PER_WIDE_INT == 32
- || i <= 0xffffffff)
- litsize = 5;
- else
- litsize = 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
- }
- else
- {
- if (i >= -0x80)
- litsize = 2;
- else if (i >= -0x8000)
- litsize = 3;
- else if (HOST_BITS_PER_WIDE_INT == 32
- || i >= -0x80000000)
- litsize = 5;
- else
- litsize = 1 + size_of_sleb128 (i);
- }
- /* Determine if DW_OP_stack_value or DW_OP_implicit_value
- is more compact. For DW_OP_stack_value we need:
- litsize + 1 (DW_OP_stack_value) + 1 (DW_OP_bit_size)
- + 1 (mode size)
- and for DW_OP_implicit_value:
- 1 (DW_OP_implicit_value) + 1 (length) + mode_size. */
- if (DWARF2_ADDR_SIZE >= GET_MODE_SIZE (mode)
- && litsize + 1 + 1 + 1 < 1 + 1 + GET_MODE_SIZE (mode))
- {
- loc_result = int_loc_descriptor (i);
- add_loc_descr (&loc_result,
- new_loc_descr (DW_OP_stack_value, 0, 0));
- add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
- return loc_result;
- }
-
- loc_result = new_loc_descr (DW_OP_implicit_value,
- GET_MODE_SIZE (mode), 0);
- loc_result->dw_loc_oprnd2.val_class = dw_val_class_const;
- loc_result->dw_loc_oprnd2.v.val_int = i;
- }
+ if (mode != VOIDmode && mode != BLKmode)
+ loc_result = address_of_int_loc_descriptor (GET_MODE_SIZE (mode),
+ INTVAL (rtl));
break;
case CONST_DOUBLE:
- if (mode != VOIDmode && dwarf_version >= 4)
+ if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
{
/* Note that a CONST_DOUBLE rtx could represent either an integer
or a floating-point constant. A CONST_DOUBLE is used whenever
break;
case CONST_VECTOR:
- if (mode != VOIDmode && dwarf_version >= 4)
+ if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
{
unsigned int elt_size = GET_MODE_UNIT_SIZE (GET_MODE (rtl));
unsigned int length = CONST_VECTOR_NUNITS (rtl);
break;
case LABEL_REF:
if (mode != VOIDmode && GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE
- && dwarf_version >= 4)
+ && (dwarf_version >= 4 || !dwarf_strict))
{
loc_result = new_loc_descr (DW_OP_implicit_value,
DWARF2_ADDR_SIZE, 0);
default:
if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE (rtl) == mode
&& GET_MODE_SIZE (GET_MODE (rtl)) <= DWARF2_ADDR_SIZE
- && dwarf_version >= 4)
+ && (dwarf_version >= 4 || !dwarf_strict))
{
/* Value expression. */
loc_result = mem_loc_descriptor (rtl, VOIDmode, initialized);
return loc;
}
+/* 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 dwarf representation of location list representing for
LOC_LIST of DECL. */
else
descr = loc_descriptor (varloc, DECL_MODE (decl), initialized);
- if (!current_function_decl)
- endname = text_end_label;
+ if (loc_list && loc_list->first != loc_list->last)
+ list = new_loc_list (descr, node->label, node->next->label, secname, 1);
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);
+ return single_element_loc_list (descr);
node = node->next;
if (!node)
enum var_init_status initialized =
NOTE_VAR_LOCATION_STATUS (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);
+ }
+
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
if (!toplevel || by_reference)
{
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. */
return;
}
+/* LOC is constant expression. Try a luck, look it up in constant
+ pool and return its loc_descr of its address. */
+
+static dw_loc_descr_ref
+cst_pool_loc_descr (tree loc)
+{
+ /* Get an RTL for this, if something has been emitted. */
+ rtx rtl = lookup_constant_def (loc);
+ enum machine_mode mode;
+
+ if (!rtl || !MEM_P (rtl))
+ {
+ gcc_assert (!rtl);
+ return 0;
+ }
+ gcc_assert (GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF);
+
+ /* TODO: We might get more coverage if we was actually delaying expansion
+ of all expressions till end of compilation when constant pools are fully
+ populated. */
+ if (!TREE_ASM_WRITTEN (SYMBOL_REF_DECL (XEXP (rtl, 0))))
+ {
+ expansion_failed (loc, NULL_RTX,
+ "CST value in contant pool but not marked.");
+ return 0;
+ }
+ mode = GET_MODE (rtl);
+ rtl = XEXP (rtl, 0);
+ return mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
+}
+
+/* Return dw_loc_list representing address of addr_expr LOC
+ by looking for innder INDIRECT_REF expression and turing it
+ into simple arithmetics. */
+
+static dw_loc_list_ref
+loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
+{
+ tree obj, offset;
+ HOST_WIDE_INT bitsize, bitpos, bytepos;
+ enum machine_mode mode;
+ int volatilep;
+ int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
+ dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
+
+ obj = get_inner_reference (TREE_OPERAND (loc, 0),
+ &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &volatilep, false);
+ STRIP_NOPS (obj);
+ if (bitpos % BITS_PER_UNIT)
+ {
+ expansion_failed (loc, NULL_RTX, "bitfield access");
+ return 0;
+ }
+ if (!INDIRECT_REF_P (obj))
+ {
+ expansion_failed (obj,
+ NULL_RTX, "no indirect ref in inner refrence");
+ return 0;
+ }
+ if (!offset && !bitpos)
+ list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1);
+ else if (toplev
+ && int_size_in_bytes (TREE_TYPE (loc)) <= DWARF2_ADDR_SIZE
+ && (dwarf_version >= 4 || !dwarf_strict))
+ {
+ list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0);
+ if (!list_ret)
+ return 0;
+ if (offset)
+ {
+ /* 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);
+ add_loc_descr_to_each (list_ret,
+ new_loc_descr (DW_OP_stack_value, 0, 0));
+ add_loc_descr_to_each (list_ret,
+ new_loc_descr (DW_OP_piece,
+ int_size_in_bytes (TREE_TYPE
+ (loc)),
+ 0));
+ }
+ return list_ret;
+}
+
+
/* Generate Dwarf location list representing LOC.
If WANT_ADDRESS is false, expression computing LOC will be computed
If WANT_ADDRESS is 1, expression computing address of LOC will be returned
return 0;
case ADDR_EXPR:
- /* If we already want an address, there's nothing we can do. */
+ /* If we already want an address, see if there is INDIRECT_REF inside
+ e.g. for &this->field. */
if (want_address)
{
- expansion_failed (loc, NULL_RTX, "need address of ADDR_EXPR");
- return 0;
+ list_ret = loc_list_for_address_of_addr_expr_of_indirect_ref
+ (loc, want_address == 2);
+ if (list_ret)
+ have_address = 1;
+ else if (decl_address_ip_invariant_p (TREE_OPERAND (loc, 0))
+ && (ret = cst_pool_loc_descr (loc)))
+ have_address = 1;
}
-
- /* Otherwise, process the argument and look for the address. */
- return loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
+ /* Otherwise, process the argument and look for the address. */
+ if (!list_ret && !ret)
+ list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
+ else
+ {
+ if (want_address)
+ expansion_failed (loc, NULL_RTX, "need address of ADDR_EXPR");
+ return NULL;
+ }
+ break;
case VAR_DECL:
if (DECL_THREAD_LOCAL_P (loc))
}
else
{
- if (!targetm.emutls.debug_form_tls_address)
+ if (!targetm.emutls.debug_form_tls_address
+ || !(dwarf_version >= 3 || !dwarf_strict))
return 0;
loc = emutls_decl (loc);
first_op = DW_OP_addr;
case PARM_DECL:
if (DECL_HAS_VALUE_EXPR_P (loc))
return loc_list_from_tree (DECL_VALUE_EXPR (loc),
- want_address);
+ want_address);
/* FALLTHRU */
case RESULT_DECL:
break;
case INDIRECT_REF:
+ case ALIGN_INDIRECT_REF:
+ case MISALIGNED_INDIRECT_REF:
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
have_address = 1;
break;
case BIT_FIELD_REF:
case ARRAY_REF:
case ARRAY_RANGE_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
{
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
gcc_assert (obj != loc);
- list_ret = loc_list_from_tree (obj, 1);
+ list_ret = loc_list_from_tree (obj,
+ want_address == 2
+ && !bitpos && !offset ? 2 : 1);
+ /* TODO: We can extract value of the small expression via shifting even
+ for nonzero bitpos. */
if (list_ret == 0)
return 0;
if (bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
}
case INTEGER_CST:
- if (host_integerp (loc, 0))
+ if ((want_address || !host_integerp (loc, 0))
+ && (ret = cst_pool_loc_descr (loc)))
+ have_address = 1;
+ else if (want_address == 2
+ && host_integerp (loc, 0)
+ && (ret = address_of_int_loc_descriptor
+ (int_size_in_bytes (TREE_TYPE (loc)),
+ tree_low_cst (loc, 0))))
+ have_address = 1;
+ else if (host_integerp (loc, 0))
ret = int_loc_descriptor (tree_low_cst (loc, 0));
else
{
break;
case CONSTRUCTOR:
- {
- /* Get an RTL for this, if something has been emitted. */
- rtx rtl = lookup_constant_def (loc);
- enum machine_mode mode;
-
- if (!rtl || !MEM_P (rtl))
- return 0;
- mode = GET_MODE (rtl);
- rtl = XEXP (rtl, 0);
- ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
+ case REAL_CST:
+ case STRING_CST:
+ case COMPLEX_CST:
+ if ((ret = cst_pool_loc_descr (loc)))
have_address = 1;
- break;
- }
+ else
+ /* We can construct small constants here using int_loc_descriptor. */
+ expansion_failed (loc, NULL_RTX,
+ "constructor or constant not in constant pool");
+ break;
case TRUTH_AND_EXPR:
case TRUTH_ANDIF_EXPR:
if (!ret && !list_ret)
return 0;
+ if (want_address == 2 && !have_address
+ && (dwarf_version >= 4 || !dwarf_strict))
+ {
+ if (int_size_in_bytes (TREE_TYPE (loc)) > DWARF2_ADDR_SIZE)
+ {
+ expansion_failed (loc, NULL_RTX,
+ "DWARF address size mismatch");
+ return 0;
+ }
+ add_loc_descr_to_each (list_ret,
+ new_loc_descr (DW_OP_stack_value, 0, 0));
+ add_loc_descr_to_each (list_ret,
+ new_loc_descr (DW_OP_piece,
+ int_size_in_bytes (TREE_TYPE
+ (loc)),
+ 0));
+ have_address = 1;
+ }
/* Show if we can't fill the request for an address. */
if (want_address && !have_address)
{
to an inlined function. They can also arise in C++ where declared
constants do not necessarily get memory "homes". */
-static void
+static bool
add_const_value_attribute (dw_die_ref die, rtx rtl)
{
switch (GET_CODE (rtl))
else
add_AT_unsigned (die, DW_AT_const_value, (unsigned HOST_WIDE_INT) val);
}
- break;
+ return true;
case CONST_DOUBLE:
/* Note that a CONST_DOUBLE rtx could represent either an integer or a
else
add_AT_long_long (die, DW_AT_const_value, rtl);
}
- break;
+ return true;
case CONST_VECTOR:
{
add_AT_vec (die, DW_AT_const_value, length, elt_size, array);
}
- break;
+ return true;
case CONST_STRING:
add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0));
- break;
+ return true;
case CONST:
if (CONSTANT_P (XEXP (rtl, 0)))
{
add_const_value_attribute (die, XEXP (rtl, 0));
- return;
+ return true;
}
/* FALLTHROUGH */
case SYMBOL_REF:
if (GET_CODE (rtl) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE)
- break;
+ return false;
case LABEL_REF:
add_AT_addr (die, DW_AT_const_value, rtl);
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
- break;
+ return true;
case PLUS:
/* In cases where an inlined instance of an inline function is passed
*value* which the artificial local variable always has during its
lifetime. We currently have no way to represent such quasi-constant
values in Dwarf, so for now we just punt and generate nothing. */
- break;
+ return false;
default:
/* No other kinds of rtx should be possible here. */
gcc_unreachable ();
}
-
+ return false;
}
/* Determine whether the evaluation of EXPR references any variables
pointer. This can happen for example if an actual argument in an inlined
function call evaluates to a compile-time constant address. */
-static void
+static bool
add_location_or_const_value_attribute (dw_die_ref die, tree decl,
enum dwarf_attribute attr)
{
rtx rtl;
- dw_loc_descr_ref descr;
- dw_loc_list_ref descr_list;
+ dw_loc_list_ref list;
var_loc_list *loc_list;
- struct var_loc_node *node;
+
if (TREE_CODE (decl) == ERROR_MARK)
- return;
+ return false;
gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL);
- /* 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 *endname, *secname;
- dw_loc_list_ref list;
- rtx varloc;
- enum var_init_status initialized;
-
- /* 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;
-
- descr = loc_by_reference (loc_descriptor (varloc, DECL_MODE (decl),
- initialized), decl);
- list = new_loc_list (descr, 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. */
- 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, 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];
- enum var_init_status initialized =
- NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
-
- 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);
- }
- descr = loc_by_reference (loc_descriptor (varloc,
- DECL_MODE (decl),
- initialized),
- decl);
- add_loc_descr_to_loc_list (&list, descr,
- node->label, endname, secname);
- }
-
- /* Finally, add the location list to the DIE, and we are done. */
- add_AT_loc_list (die, attr, list);
- return;
- }
-
/* Try to get some constant RTL for this decl, and use that as the value of
the location. */
rtl = rtl_for_decl_location (decl);
- if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING))
- {
- add_const_value_attribute (die, rtl);
- return;
- }
+ if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
+ && add_const_value_attribute (die, rtl))
+ return true;
- /* If we have tried to generate the location otherwise, and it
- didn't work out (we wouldn't be here if we did), and we have a one entry
- location list, try generating a location from that. */
- if (loc_list && loc_list->first)
+ /* See if we have single element location list that is equivalent to
+ a constant value. That way we are better to use add_const_value_attribute
+ rather than expanding constant value equivalent. */
+ loc_list = lookup_decl_loc (decl);
+ if (loc_list && loc_list->first && loc_list->first == loc_list->last)
{
enum var_init_status status;
+ struct var_loc_node *node;
+
node = loc_list->first;
status = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
rtl = NOTE_VAR_LOCATION (node->var_loc_note);
if (GET_CODE (rtl) == VAR_LOCATION
&& GET_CODE (XEXP (rtl, 1)) != PARALLEL)
rtl = XEXP (XEXP (rtl, 1), 0);
- if (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
- {
- add_const_value_attribute (die, rtl);
- return;
- }
- descr = loc_descriptor (NOTE_VAR_LOCATION (node->var_loc_note),
- DECL_MODE (decl), status);
- if (descr)
- {
- descr = loc_by_reference (descr, decl);
- add_AT_location_description (die, attr, single_element_loc_list (descr));
- return;
- }
+ if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
+ && add_const_value_attribute (die, rtl))
+ return true;
}
-
- /* We couldn't get any rtl, so try directly generating the location
- description from the tree. */
- descr_list = loc_list_from_tree (decl, 2);
- if (descr_list)
+ list = loc_list_from_tree (decl, 2);
+ if (list)
{
- descr = loc_by_reference (descr, decl);
- add_AT_location_description (die, attr, descr_list);
- return;
+ add_AT_location_description (die, attr, list);
+ return true;
}
/* None of that worked, so it must not really have a location;
try adding a constant value attribute from the DECL_INITIAL. */
- tree_add_const_value_attribute_for_decl (die, decl);
+ return tree_add_const_value_attribute_for_decl (die, decl);
}
/* Add VARIABLE and DIE into deferred locations list. */
/* Attach a DW_AT_const_value attribute to DIE. The value of the
attribute is the const value T. */
-static void
+static bool
tree_add_const_value_attribute (dw_die_ref die, tree t)
{
tree init;
rtx rtl;
if (!t || !TREE_TYPE (t) || TREE_TYPE (t) == error_mark_node)
- return;
+ return false;
init = t;
gcc_assert (!DECL_P (init));
rtl = rtl_for_decl_init (init, type);
if (rtl)
- add_const_value_attribute (die, rtl);
+ {
+ add_const_value_attribute (die, rtl);
+ return true;
+ }
/* If the host and target are sane, try harder. */
else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
&& initializer_constant_valid_p (init, type))
unsigned char *array = GGC_CNEWVEC (unsigned char, size);
if (native_encode_initializer (init, array, size))
- add_AT_vec (die, DW_AT_const_value, size, 1, array);
+ {
+ add_AT_vec (die, DW_AT_const_value, size, 1, array);
+ return true;
+ }
}
}
+ return false;
}
/* Attach a DW_AT_const_value attribute to VAR_DIE. The value of the
variable with static storage duration
(so it can't be a PARM_DECL or a RESULT_DECL). */
-static void
+static bool
tree_add_const_value_attribute_for_decl (dw_die_ref var_die, tree decl)
{
if (!decl
|| (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != CONST_DECL))
- return;
+ return false;
if (TREE_READONLY (decl)
&& ! TREE_THIS_VOLATILE (decl)
&& DECL_INITIAL (decl))
/* OK */;
else
- return;
+ return false;
- tree_add_const_value_attribute (var_die, DECL_INITIAL (decl));
+ return tree_add_const_value_attribute (var_die, DECL_INITIAL (decl));
}
/* Convert the CFI instructions for the current function into a
return DW_TAG_class_type;
case RECORD_IS_INTERFACE:
- return DW_TAG_interface_type;
+ if (dwarf_version >= 3 || !dwarf_strict)
+ return DW_TAG_interface_type;
+ return DW_TAG_structure_type;
default:
gcc_unreachable ();
DIE to represent a formal parameter object (or some inlining thereof). If
it's the latter, then this function is only being called to output a
DW_TAG_formal_parameter DIE to stand as a placeholder for some formal
- argument type of some subprogram type. */
+ argument type of some subprogram type.
+ If EMIT_NAME_P is true, name and source coordinate attributes
+ are emitted. */
static dw_die_ref
-gen_formal_parameter_die (tree node, tree origin, dw_die_ref context_die)
+gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
+ dw_die_ref context_die)
{
tree node_or_origin = node ? node : origin;
dw_die_ref parm_die
else
{
tree type = TREE_TYPE (node);
- add_name_and_src_coords_attributes (parm_die, node);
+ if (emit_name_p)
+ add_name_and_src_coords_attributes (parm_die, node);
if (decl_by_reference_p (node))
add_type_attribute (parm_die, TREE_TYPE (type), 0, 0,
context_die);
return parm_die;
}
+/* Generate and return a DW_TAG_formal_parameter_pack. Also generate
+ children DW_TAG_formal_parameter DIEs representing the arguments of the
+ parameter pack.
+
+ PARM_PACK must be a function parameter pack.
+ PACK_ARG is the first argument of the parameter pack. Its TREE_CHAIN
+ must point to the subsequent arguments of the function PACK_ARG belongs to.
+ SUBR_DIE is the DIE of the function PACK_ARG belongs to.
+ If NEXT_ARG is non NULL, *NEXT_ARG is set to the function argument
+ following the last one for which a DIE was generated. */
+
+static dw_die_ref
+gen_formal_parameter_pack_die (tree parm_pack,
+ tree pack_arg,
+ dw_die_ref subr_die,
+ tree *next_arg)
+{
+ tree arg;
+ dw_die_ref parm_pack_die;
+
+ gcc_assert (parm_pack
+ && lang_hooks.function_parameter_pack_p (parm_pack)
+ && DECL_NAME (parm_pack)
+ && subr_die);
+
+ parm_pack_die = new_die (DW_TAG_formal_parameter_pack, subr_die, parm_pack);
+ add_AT_string (parm_pack_die, DW_AT_name,
+ IDENTIFIER_POINTER (DECL_NAME (parm_pack)));
+
+ for (arg = pack_arg; arg; arg = TREE_CHAIN (arg))
+ {
+ if (! lang_hooks.decls.function_parm_expanded_from_pack_p (arg,
+ parm_pack))
+ break;
+ gen_formal_parameter_die (arg, NULL,
+ false /* Don't emit name attribute. */,
+ parm_pack_die);
+ }
+ if (next_arg)
+ *next_arg = arg;
+ return parm_pack_die;
+}
+
/* Generate a special type of DIE used as a stand-in for a trailing ellipsis
at the end of an (ANSI prototyped) formal parameters list. */
break;
/* Output a (nameless) DIE to represent the formal parameter itself. */
- parm_die = gen_formal_parameter_die (formal_type, NULL, context_die);
+ parm_die = gen_formal_parameter_die (formal_type, NULL,
+ true /* Emit name attribute. */,
+ context_die);
if ((TREE_CODE (function_or_method_type) == METHOD_TYPE
&& link == first_parm_type)
|| (arg && DECL_ARTIFICIAL (arg)))
tree save_fn;
tree context;
int was_abstract = DECL_ABSTRACT (decl);
+ htab_t old_decl_loc_table;
/* Make sure we have the actual abstract inline, not a clone. */
decl = DECL_ORIGIN (decl);
- htab_empty (decl_loc_table);
old_die = lookup_decl_die (decl);
if (old_die && get_AT (old_die, DW_AT_inline))
/* We've already generated the abstract instance. */
return;
+ /* We can be called while recursively when seeing block defining inlined subroutine
+ DIE. Be sure to not clobber the outer location table nor use it or we would
+ get locations in abstract instantces. */
+ old_decl_loc_table = decl_loc_table;
+ decl_loc_table = NULL;
+
/* Be sure we've emitted the in-class declaration DIE (if any) first, so
we don't get confused by DECL_ABSTRACT. */
if (debug_info_level > DINFO_LEVEL_TERSE)
set_decl_abstract_flags (decl, 0);
current_function_decl = save_fn;
+ decl_loc_table = old_decl_loc_table;
pop_cfun ();
}
/* If this is an explicit function declaration then generate
a DW_AT_explicit attribute. */
- if (lang_hooks.decls.function_decl_explicit_p (decl))
+ if (lang_hooks.decls.function_decl_explicit_p (decl)
+ && (dwarf_version >= 3 || !dwarf_strict))
add_AT_flag (subr_die, DW_AT_explicit, 1);
/* The first time we see a member function, it is in the context of
else
{
/* Generate DIEs to represent all known formal parameters. */
- tree arg_decls = DECL_ARGUMENTS (decl);
- tree parm;
-
- /* When generating DIEs, generate the unspecified_parameters DIE
- instead if we come across the arg "__builtin_va_alist" */
- for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
- if (TREE_CODE (parm) == PARM_DECL)
- {
- if (DECL_NAME (parm)
- && !strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)),
- "__builtin_va_alist"))
- gen_unspecified_parameters_die (parm, subr_die);
- else
+ tree parm = DECL_ARGUMENTS (decl);
+ tree generic_decl = lang_hooks.decls.get_generic_function_decl (decl);
+ tree generic_decl_parm = generic_decl
+ ? DECL_ARGUMENTS (generic_decl)
+ : NULL;
+
+ /* Now we want to walk the list of parameters of the function and
+ emit their relevant DIEs.
+
+ We consider the case of DECL being an instance of a generic function
+ as well as it being a normal function.
+
+ If DECL is an instance of a generic function we walk the
+ parameters of the generic function declaration _and_ the parameters of
+ DECL itself. This is useful because we want to emit specific DIEs for
+ function parameter packs and those are declared as part of the
+ generic function declaration. In that particular case,
+ the parameter pack yields a DW_TAG_formal_parameter_pack DIE.
+ That DIE has children DIEs representing the set of arguments
+ of the pack. Note that the set of pack arguments can be empty.
+ In that case, the DW_TAG_formal_parameter_pack DIE will not have any
+ children DIE.
+
+ Otherwise, we just consider the parameters of DECL. */
+ while (generic_decl_parm || parm)
+ {
+ if (generic_decl_parm
+ && lang_hooks.function_parameter_pack_p (generic_decl_parm))
+ gen_formal_parameter_pack_die (generic_decl_parm,
+ parm, subr_die,
+ &parm);
+ else if (parm)
+ {
gen_decl_die (parm, NULL, subr_die);
- }
+ parm = TREE_CHAIN (parm);
+ }
+
+ if (generic_decl_parm)
+ generic_decl_parm = TREE_CHAIN (generic_decl_parm);
+ }
/* Decide whether we need an unspecified_parameters DIE at the end.
There are 2 more cases to do this for: 1) the ansi ... declaration -
{
expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (stmt));
- add_AT_file (die, DW_AT_call_file, lookup_filename (s.file));
- add_AT_unsigned (die, DW_AT_call_line, s.line);
+ if (dwarf_version >= 3 || !dwarf_strict)
+ {
+ add_AT_file (die, DW_AT_call_file, lookup_filename (s.file));
+ add_AT_unsigned (die, DW_AT_call_line, s.line);
+ }
}
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
- if (BLOCK_FRAGMENT_CHAIN (stmt))
+ if (BLOCK_FRAGMENT_CHAIN (stmt)
+ && (dwarf_version >= 3 || !dwarf_strict))
{
tree chain;
add_AT_string (die, DW_AT_producer, producer);
+ language = DW_LANG_C89;
if (strcmp (language_string, "GNU C++") == 0)
language = DW_LANG_C_plus_plus;
- else if (strcmp (language_string, "GNU Ada") == 0)
- language = DW_LANG_Ada95;
else if (strcmp (language_string, "GNU F77") == 0)
language = DW_LANG_Fortran77;
- else if (strcmp (language_string, "GNU Fortran") == 0)
- language = DW_LANG_Fortran95;
else if (strcmp (language_string, "GNU Pascal") == 0)
language = DW_LANG_Pascal83;
- else if (strcmp (language_string, "GNU Java") == 0)
- language = DW_LANG_Java;
- else if (strcmp (language_string, "GNU Objective-C") == 0)
- language = DW_LANG_ObjC;
- else if (strcmp (language_string, "GNU Objective-C++") == 0)
- language = DW_LANG_ObjC_plus_plus;
- else
- language = DW_LANG_C89;
+ else if (dwarf_version >= 3 || !dwarf_strict)
+ {
+ if (strcmp (language_string, "GNU Ada") == 0)
+ language = DW_LANG_Ada95;
+ else if (strcmp (language_string, "GNU Fortran") == 0)
+ language = DW_LANG_Fortran95;
+ else if (strcmp (language_string, "GNU Java") == 0)
+ language = DW_LANG_Java;
+ else if (strcmp (language_string, "GNU Objective-C") == 0)
+ language = DW_LANG_ObjC;
+ else if (strcmp (language_string, "GNU Objective-C++") == 0)
+ language = DW_LANG_ObjC_plus_plus;
+ }
add_AT_unsigned (die, DW_AT_language, language);
return 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
- && lang_hooks.types.get_array_descr_info (type, &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;
break;
case NAMESPACE_DECL:
- dwarf2out_decl (decl);
+ if (dwarf_version >= 3 || !dwarf_strict)
+ dwarf2out_decl (decl);
+ else
+ /* DWARF2 has neither DW_TAG_module, nor DW_TAG_namespace. */
+ decl_die = comp_unit_die;
break;
default:
if (!origin)
origin = decl_ultimate_origin (decl);
if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL)
- gen_formal_parameter_die (decl, origin, context_die);
+ gen_formal_parameter_die (decl, origin,
+ true /* Emit name attribute. */,
+ context_die);
else
gen_variable_die (decl, origin, context_die);
break;
gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
else
gen_type_die (TREE_TYPE (decl_or_origin), context_die);
- gen_formal_parameter_die (decl, origin, context_die);
+ gen_formal_parameter_die (decl, origin,
+ true /* Emit name attribute. */,
+ context_die);
break;
case NAMESPACE_DECL:
case IMPORTED_DECL:
- gen_namespace_die (decl, context_die);
+ if (dwarf_version >= 3 || !dwarf_strict)
+ gen_namespace_die (decl, context_die);
break;
default:
}
if (TREE_CODE (decl) == NAMESPACE_DECL)
- imported_die = new_die (DW_TAG_imported_module,
- lexical_block_die,
- lexical_block);
+ {
+ if (dwarf_version >= 3 || !dwarf_strict)
+ imported_die = new_die (DW_TAG_imported_module,
+ lexical_block_die,
+ lexical_block);
+ else
+ return;
+ }
else
imported_die = new_die (DW_TAG_imported_declaration,
lexical_block_die,
&& TYPE_P (context)
&& !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE))
return;
+
+ if (!(dwarf_version >= 3 || !dwarf_strict))
+ return;
+
scope_die = get_context_die (context);
if (child)
/* We can only use the low/high_pc attributes if all of the code was
in .text. */
- if (!have_multiple_function_sections)
+ if (!have_multiple_function_sections
+ || !(dwarf_version >= 3 || !dwarf_strict))
{
add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label);
add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);