data_section ();
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
- (*targetm.asm_out.globalize_label) (asm_out_file, IDENTIFIER_POINTER (label));
+ targetm.asm_out.globalize_label (asm_out_file, IDENTIFIER_POINTER (label));
ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
}
typedef struct dw_fde_struct GTY(())
{
+ tree decl;
const char *dw_fde_begin;
const char *dw_fde_current_label;
const char *dw_fde_end;
#define FUNC_END_LABEL "LFE"
#endif
+#ifndef FRAME_BEGIN_LABEL
#define FRAME_BEGIN_LABEL "Lframe"
+#endif
#define CIE_AFTER_SIZE_LABEL "LSCIE"
#define CIE_END_LABEL "LECIE"
#define FDE_LABEL "LSFDE"
if (fde_table_in_use == 0)
return;
+ /* If we make FDEs linkonce, we may have to emit an empty label for
+ an FDE that wouldn't otherwise be emitted. We want to avoid
+ having an FDE kept around when the function it refers to is
+ discarded. (Example where this matters: a primary function
+ template in C++ requires EH information, but an explicit
+ specialization doesn't. */
+ if (TARGET_USES_WEAK_UNWIND_INFO
+ && ! flag_asynchronous_unwind_tables
+ && for_eh)
+ for (i = 0; i < fde_table_in_use; i++)
+ if ((fde_table[i].nothrow || fde_table[i].all_throwers_are_sibcalls)
+ && !fde_table[i].uses_eh_lsda
+ && ! DECL_ONE_ONLY (fde_table[i].decl))
+ targetm.asm_out.unwind_label (asm_out_file, fde_table[i].decl,
+ /* empty */ 1);
+
/* If we don't have any functions we'll want to unwind out of, don't
emit any EH unwind information. Note that if exceptions aren't
enabled, we won't have collected nothrow information, and if we
for (i = 0; i < fde_table_in_use; i++)
if (fde_table[i].uses_eh_lsda)
any_eh_needed = any_lsda_needed = true;
+ else if (TARGET_USES_WEAK_UNWIND_INFO
+ && DECL_ONE_ONLY (fde_table[i].decl))
+ any_eh_needed = 1;
else if (! fde_table[i].nothrow
&& ! fde_table[i].all_throwers_are_sibcalls)
any_eh_needed = true;
app_enable ();
if (for_eh)
- (*targetm.asm_out.eh_frame_section) ();
+ targetm.asm_out.eh_frame_section ();
else
named_section_flags (DEBUG_FRAME_SECTION, SECTION_DEBUG);
P Indicates the presence of an encoding + language
personality routine in the CIE augmentation. */
- fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
+ fde_encoding = TARGET_USES_WEAK_UNWIND_INFO
+ ? ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1)
+ : ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
/* Don't emit EH unwind info for leaf functions that don't need it. */
if (for_eh && !flag_asynchronous_unwind_tables && flag_exceptions
&& (fde->nothrow || fde->all_throwers_are_sibcalls)
+ && (! TARGET_USES_WEAK_UNWIND_INFO || ! DECL_ONE_ONLY (fde->decl))
&& !fde->uses_eh_lsda)
continue;
- (*targetm.asm_out.internal_label) (asm_out_file, FDE_LABEL, for_eh + i * 2);
+ targetm.asm_out.unwind_label (asm_out_file, fde->decl, /* empty */ 0);
+ targetm.asm_out.internal_label (asm_out_file, FDE_LABEL, for_eh + i * 2);
ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i * 2);
ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i * 2);
dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
if (for_eh)
{
- dw2_asm_output_encoded_addr_rtx (fde_encoding,
- gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
- "FDE initial location");
+ if (TARGET_USES_WEAK_UNWIND_INFO
+ && DECL_ONE_ONLY (fde->decl))
+ dw2_asm_output_encoded_addr_rtx (fde_encoding,
+ gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (fde->decl))),
+ "FDE initial location");
+ else
+ dw2_asm_output_encoded_addr_rtx (fde_encoding,
+ gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
+ "FDE initial location");
dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
fde->dw_fde_end, fde->dw_fde_begin,
"FDE address range");
/* Add the new FDE at the end of the fde_table. */
fde = &fde_table[fde_table_in_use++];
+ fde->decl = current_function_decl;
fde->dw_fde_begin = xstrdup (label);
fde->dw_fde_current_label = NULL;
fde->dw_fde_end = NULL;
unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_offset"))) val_offset;
dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
- HOST_WIDE_INT GTY ((default (""))) val_int;
+ HOST_WIDE_INT GTY ((default)) val_int;
unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
dw_long_long_const GTY ((tag ("dw_val_class_long_long"))) val_long_long;
dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
/* We make these global, not weak; if the target doesn't support
.linkonce, it doesn't support combining the sections, so debugging
will break. */
- (*targetm.asm_out.globalize_label) (asm_out_file, sym);
+ targetm.asm_out.globalize_label (asm_out_file, sym);
ASM_OUTPUT_LABEL (asm_out_file, sym);
}
static const char *
dwarf2_name (tree decl, int scope)
{
- return (*lang_hooks.decl_printable_name) (decl, scope ? 1 : 0);
+ return lang_hooks.decl_printable_name (decl, scope ? 1 : 0);
}
/* Add a new entry to .debug_pubnames if appropriate. */
|| ! strcmp (type_name, "signed char")
|| ! strcmp (type_name, "unsigned char"))))
{
- if (TREE_UNSIGNED (type))
+ if (TYPE_UNSIGNED (type))
encoding = DW_ATE_unsigned;
else
encoding = DW_ATE_signed;
case CHAR_TYPE:
/* GNU Pascal/Ada CHAR type. Not used in C. */
- if (TREE_UNSIGNED (type))
+ if (TYPE_UNSIGNED (type))
encoding = DW_ATE_unsigned_char;
else
encoding = DW_ATE_signed_char;
{
tree subtype = TREE_TYPE (type);
- if (TREE_CODE (type) == INTEGER_TYPE
- && subtype != NULL_TREE)
+ /* Subrange types are identified by the fact that they are integer
+ types, and that they have a subtype which is either an integer type
+ or an enumeral type. */
+
+ if (TREE_CODE (type) != INTEGER_TYPE
+ || subtype == NULL_TREE)
+ return false;
+
+ if (TREE_CODE (subtype) != INTEGER_TYPE
+ && TREE_CODE (subtype) != ENUMERAL_TYPE)
+ return false;
+
+ if (TREE_CODE (type) == TREE_CODE (subtype)
+ && int_size_in_bytes (type) == int_size_in_bytes (subtype)
+ && TYPE_MIN_VALUE (type) != NULL
+ && TYPE_MIN_VALUE (subtype) != NULL
+ && tree_int_cst_equal (TYPE_MIN_VALUE (type), TYPE_MIN_VALUE (subtype))
+ && TYPE_MAX_VALUE (type) != NULL
+ && TYPE_MAX_VALUE (subtype) != NULL
+ && tree_int_cst_equal (TYPE_MAX_VALUE (type), TYPE_MAX_VALUE (subtype)))
{
- if (TREE_CODE (subtype) == INTEGER_TYPE)
- return true;
- if (TREE_CODE (subtype) == ENUMERAL_TYPE)
- return true;
+ /* The type and its subtype have the same representation. If in
+ addition the two types also have the same name, then the given
+ type is not a subrange type, but rather a plain base type. */
+ /* FIXME: brobecker/2004-03-22:
+ Sizetype INTEGER_CSTs nodes are canonicalized. It should
+ therefore be sufficient to check the TYPE_SIZE node pointers
+ rather than checking the actual size. Unfortunately, we have
+ found some cases, such as in the Ada "integer" type, where
+ this is not the case. Until this problem is solved, we need to
+ keep checking the actual size. */
+ tree type_name = TYPE_NAME (type);
+ tree subtype_name = TYPE_NAME (subtype);
+
+ if (type_name != NULL && TREE_CODE (type_name) == TYPE_DECL)
+ type_name = DECL_NAME (type_name);
+
+ if (subtype_name != NULL && TREE_CODE (subtype_name) == TYPE_DECL)
+ subtype_name = DECL_NAME (subtype_name);
+
+ if (type_name == subtype_name)
+ return false;
}
- return false;
+
+ return true;
}
/* Given a pointer to a tree node for a subrange type, return a pointer
dw_die_ref subrange_die;
tree name = TYPE_NAME (type);
const HOST_WIDE_INT size_in_bytes = int_size_in_bytes (type);
+ tree subtype = TREE_TYPE (type);
if (context_die == NULL)
context_die = comp_unit_die;
- if (TREE_CODE (TREE_TYPE (type)) == ENUMERAL_TYPE)
- subtype_die = gen_enumeration_type_die (TREE_TYPE (type), context_die);
+ if (TREE_CODE (subtype) == ENUMERAL_TYPE)
+ subtype_die = gen_enumeration_type_die (subtype, context_die);
else
- subtype_die = base_type_die (TREE_TYPE (type));
+ subtype_die = base_type_die (subtype);
subrange_die = new_die (DW_TAG_subrange_type, context_die, type);
add_name_attribute (subrange_die, IDENTIFIER_POINTER (name));
}
- if (int_size_in_bytes (TREE_TYPE (type)) != size_in_bytes)
+ if (int_size_in_bytes (subtype) != size_in_bytes)
{
/* The size of the subrange type and its base type do not match,
so we need to generate a size attribute for the subrange type. */
return 0;
reg = reg_number (rtl);
- regs = (*targetm.dwarf_register_span) (rtl);
+ regs = targetm.dwarf_register_span (rtl);
if (hard_regno_nregs[reg][GET_MODE (rtl)] > 1
|| regs)
actually within the array. That's *not* necessarily the same as the
zeroth element of the array. */
- rtl = (*targetm.delegitimize_address) (rtl);
+ rtl = targetm.delegitimize_address (rtl);
switch (GET_CODE (rtl))
{
{
dw_loc_descr_ref ret, ret1;
int indirect_p = 0;
- int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc));
+ int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
enum dwarf_location_atom op;
/* ??? Most of the time we do not take proper care for sign/zero
case ERROR_MARK:
return 0;
- case WITH_RECORD_EXPR:
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
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:
/* We can support this only if we can look through conversions and
find an INDIRECT_EXPR. */
mode = GET_MODE (rtl);
rtl = XEXP (rtl, 0);
- rtl = (*targetm.delegitimize_address) (rtl);
+ rtl = targetm.delegitimize_address (rtl);
indirect_p = 1;
ret = mem_loc_descriptor (rtl, mode, true);
goto do_binop;
case LE_EXPR:
- if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
return 0;
op = DW_OP_le;
goto do_binop;
case GE_EXPR:
- if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
return 0;
op = DW_OP_ge;
goto do_binop;
case LT_EXPR:
- if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
return 0;
op = DW_OP_lt;
goto do_binop;
case GT_EXPR:
- if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
+ if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
return 0;
op = DW_OP_gt;
add_loc_descr (&ret, new_loc_descr (op, 0, 0));
break;
+ case MIN_EXPR:
case MAX_EXPR:
- loc = build (COND_EXPR, TREE_TYPE (loc),
- build (LT_EXPR, integer_type_node,
- TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
- TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
+ {
+ const enum tree_code code =
+ TREE_CODE (loc) == MIN_EXPR ? GT_EXPR : LT_EXPR;
+
+ loc = build (COND_EXPR, TREE_TYPE (loc),
+ build (code, integer_type_node,
+ TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
+ TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
+ }
/* ... fall through ... */
&& TREE_CODE (decl) == VAR_DECL
&& TREE_STATIC (decl))))
{
- rtl = (*targetm.delegitimize_address) (rtl);
+ rtl = targetm.delegitimize_address (rtl);
return rtl;
}
rtl = NULL_RTX;
}
if (rtl)
- rtl = (*targetm.delegitimize_address) (rtl);
+ rtl = targetm.delegitimize_address (rtl);
/* If we don't look past the constant pool, we risk emitting a
reference to a constant pool entry that isn't referenced from
if (type_die->die_parent == NULL)
add_child_die (scope_die_for (type, context_die), type_die);
- for (link = TYPE_FIELDS (type);
+ for (link = TYPE_VALUES (type);
link != NULL; link = TREE_CHAIN (link))
{
dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link);
add_name_attribute (enum_die,
IDENTIFIER_POINTER (TREE_PURPOSE (link)));
- if (host_integerp (value, TREE_UNSIGNED (TREE_TYPE (value))))
+ if (host_integerp (value, TYPE_UNSIGNED (TREE_TYPE (value))))
/* DWARF2 does not provide a way of indicating whether or
not enumeration constants are signed or unsigned. GDB
always assumes the values are signed, so we output all
else if (DECL_SECTION_NAME (current_function_decl))
{
dw_separate_line_info_ref line_info;
- (*targetm.asm_out.internal_label) (asm_out_file, SEPARATE_LINE_CODE_LABEL,
+ targetm.asm_out.internal_label (asm_out_file, SEPARATE_LINE_CODE_LABEL,
separate_line_info_table_in_use);
/* Expand the line info table if necessary. */
{
dw_line_info_ref line_info;
- (*targetm.asm_out.internal_label) (asm_out_file, LINE_CODE_LABEL,
+ targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL,
line_info_table_in_use);
/* Expand the line info table if necessary. */
/* Output a terminator label for the .text section. */
text_section ();
- (*targetm.asm_out.internal_label) (asm_out_file, TEXT_END_LABEL, 0);
+ targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
/* Output the source line correspondence table. We must do this
even if there is no line information. Otherwise, on an empty