aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/dwarf2out.c203
1 files changed, 124 insertions, 79 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index b99598e..fbda47e 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -15176,7 +15176,7 @@ scompare_loc_descriptor_narrow (enum dwarf_location_atom op, rtx rtl,
return compare_loc_descriptor (op, op0, op1);
}
-/* Return location descriptor for unsigned comparison OP RTL. */
+/* Return location descriptor for signed comparison OP RTL. */
static dw_loc_descr_ref
scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
@@ -17994,6 +17994,8 @@ struct loc_descr_context
bool placeholder_arg;
/* True if PLACEHOLDER_EXPR has been seen. */
bool placeholder_seen;
+ /* True if strict preservation of signedness has been requested. */
+ bool strict_signedness;
};
/* DWARF procedures generation
@@ -18062,7 +18064,7 @@ new_dwarf_proc_die (dw_loc_descr_ref location, tree fndecl,
/* Return whether TYPE is a supported type as a DWARF procedure argument
type or return type (we handle only scalar types and pointer types that
- aren't wider than the DWARF expression evaluation stack. */
+ aren't wider than the DWARF expression evaluation stack). */
static bool
is_handled_procedure_type (tree type)
@@ -18204,6 +18206,12 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
case DW_OP_bit_piece:
case DW_OP_implicit_value:
case DW_OP_stack_value:
+ case DW_OP_deref_type:
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
+ case DW_OP_GNU_deref_type:
+ case DW_OP_GNU_convert:
+ case DW_OP_GNU_reinterpret:
break;
case DW_OP_addr:
@@ -18335,9 +18343,6 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
case DW_OP_entry_value:
case DW_OP_const_type:
case DW_OP_regval_type:
- case DW_OP_deref_type:
- case DW_OP_convert:
- case DW_OP_reinterpret:
case DW_OP_form_tls_address:
case DW_OP_GNU_push_tls_address:
case DW_OP_GNU_uninit:
@@ -18346,9 +18351,6 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
case DW_OP_GNU_entry_value:
case DW_OP_GNU_const_type:
case DW_OP_GNU_regval_type:
- case DW_OP_GNU_deref_type:
- case DW_OP_GNU_convert:
- case DW_OP_GNU_reinterpret:
case DW_OP_GNU_parameter_ref:
/* loc_list_from_tree will probably not output these operations for
size functions, so assume they will not appear here. */
@@ -18397,8 +18399,8 @@ resolve_args_picking (dw_loc_descr_ref loc, unsigned initial_frame_offset,
this operation. */
hash_map<dw_loc_descr_ref, unsigned> frame_offsets;
- return resolve_args_picking_1 (loc, initial_frame_offset, dpi,
- frame_offsets);
+ return
+ resolve_args_picking_1 (loc, initial_frame_offset, dpi, frame_offsets);
}
/* Try to generate a DWARF procedure that computes the same result as FNDECL.
@@ -18407,8 +18409,15 @@ resolve_args_picking (dw_loc_descr_ref loc, unsigned initial_frame_offset,
static dw_die_ref
function_to_dwarf_procedure (tree fndecl)
{
- struct loc_descr_context ctx;
struct dwarf_procedure_info dpi;
+ struct loc_descr_context ctx = {
+ NULL_TREE, /* context_type */
+ NULL_TREE, /* base_decl */
+ &dpi, /* dpi */
+ false, /* placeholder_arg */
+ false, /* placeholder_seen */
+ true /* strict_signedness */
+ };
dw_die_ref dwarf_proc_die;
tree tree_body = DECL_SAVED_TREE (fndecl);
dw_loc_descr_ref loc_body, epilogue;
@@ -18453,11 +18462,6 @@ function_to_dwarf_procedure (tree fndecl)
cause an infinite recursion if its call graph has a cycle. This is very
unlikely for size functions, however, so don't bother with such things at
the moment. */
- ctx.context_type = NULL_TREE;
- ctx.base_decl = NULL_TREE;
- ctx.dpi = &dpi;
- ctx.placeholder_arg = false;
- ctx.placeholder_seen = false;
dpi.fndecl = fndecl;
dpi.args_count = list_length (DECL_ARGUMENTS (fndecl));
loc_body = loc_descriptor_from_tree (tree_body, 0, &ctx);
@@ -18586,47 +18590,48 @@ loc_list_from_tree_1 (tree loc, int want_address,
case CALL_EXPR:
{
- const int nargs = call_expr_nargs (loc);
tree callee = get_callee_fndecl (loc);
- int i;
dw_die_ref dwarf_proc;
- if (callee == NULL_TREE)
- goto call_expansion_failed;
-
- /* We handle only functions that return an integer. */
- if (!is_handled_procedure_type (TREE_TYPE (TREE_TYPE (callee))))
- goto call_expansion_failed;
-
- dwarf_proc = function_to_dwarf_procedure (callee);
- if (dwarf_proc == NULL)
- goto call_expansion_failed;
-
- /* Evaluate arguments right-to-left so that the first argument will
- be the top-most one on the stack. */
- for (i = nargs - 1; i >= 0; --i)
+ if (callee
+ && is_handled_procedure_type (TREE_TYPE (TREE_TYPE (callee)))
+ && (dwarf_proc = function_to_dwarf_procedure (callee)))
{
- dw_loc_descr_ref loc_descr
- = loc_descriptor_from_tree (CALL_EXPR_ARG (loc, i), 0,
- context);
+ /* DWARF procedures are used for size functions, which are built
+ when size expressions contain conditional constructs, so we
+ request strict preservation of signedness for comparisons. */
+ bool old_strict_signedness;
+ if (context)
+ {
+ old_strict_signedness = context->strict_signedness;
+ context->strict_signedness = true;
+ }
- if (loc_descr == NULL)
- goto call_expansion_failed;
+ /* Evaluate arguments right-to-left so that the first argument
+ will be the top-most one on the stack. */
+ for (int i = call_expr_nargs (loc) - 1; i >= 0; --i)
+ {
+ tree arg = CALL_EXPR_ARG (loc, i);
+ ret1 = loc_descriptor_from_tree (arg, 0, context);
+ if (!ret1)
+ {
+ expansion_failed (arg, NULL_RTX, "CALL_EXPR argument");
+ return NULL;
+ }
+ add_loc_descr (&ret, ret1);
+ }
- add_loc_descr (&ret, loc_descr);
+ ret1 = new_loc_descr (DW_OP_call4, 0, 0);
+ ret1->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+ ret1->dw_loc_oprnd1.v.val_die_ref.die = dwarf_proc;
+ ret1->dw_loc_oprnd1.v.val_die_ref.external = 0;
+ add_loc_descr (&ret, ret1);
+ if (context)
+ context->strict_signedness = old_strict_signedness;
}
-
- ret1 = new_loc_descr (DW_OP_call4, 0, 0);
- ret1->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
- ret1->dw_loc_oprnd1.v.val_die_ref.die = dwarf_proc;
- ret1->dw_loc_oprnd1.v.val_die_ref.external = 0;
- add_loc_descr (&ret, ret1);
+ else
+ expansion_failed (loc, NULL_RTX, "CALL_EXPR target");
break;
-
- call_expansion_failed:
- expansion_failed (loc, NULL_RTX, "CALL_EXPR");
- /* There are no opcodes for these operations. */
- return 0;
}
case PREINCREMENT_EXPR:
@@ -19286,7 +19291,14 @@ loc_list_from_tree_1 (tree loc, int want_address,
= loc_list_from_tree_1 (TREE_OPERAND (loc, 2), 0, context);
dw_loc_descr_ref bra_node, jump_node, tmp;
- list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context);
+ /* DW_OP_bra is branch-on-nonzero so avoid doing useless work. */
+ if (TREE_CODE (TREE_OPERAND (loc, 0)) == NE_EXPR
+ && integer_zerop (TREE_OPERAND (TREE_OPERAND (loc, 0), 1)))
+ list_ret
+ = loc_list_from_tree_1 (TREE_OPERAND (TREE_OPERAND (loc, 0), 0),
+ 0, context);
+ else
+ list_ret = loc_list_from_tree_1 (TREE_OPERAND (loc, 0), 0, context);
if (list_ret == 0 || lhs == 0 || rhs == 0)
return 0;
@@ -19366,23 +19378,50 @@ loc_list_from_tree_1 (tree loc, int want_address,
if (!want_address && have_address)
{
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (loc));
+ scalar_int_mode int_mode;
+ dw_die_ref type_die;
+ dw_loc_descr_ref deref;
+ /* If the size is greater than DWARF2_ADDR_SIZE, bail out. */
if (size > DWARF2_ADDR_SIZE || size == -1)
{
expansion_failed (loc, NULL_RTX,
"DWARF address size mismatch");
return 0;
}
+
+ /* If it is equal to DWARF2_ADDR_SIZE, extension does not matter. */
else if (size == DWARF2_ADDR_SIZE)
- op = DW_OP_deref;
+ deref = new_loc_descr (DW_OP_deref, size, 0);
+
+ /* If it is lower than DWARF2_ADDR_SIZE, DW_OP_deref_size will zero-
+ extend the value, which is really OK for unsigned types only. */
+ else if (!(context && context->strict_signedness)
+ || TYPE_UNSIGNED (TREE_TYPE (loc))
+ || (dwarf_strict && dwarf_version < 5)
+ || !is_a <scalar_int_mode> (mode, &int_mode)
+ || !(type_die = base_type_for_mode (mode, false)))
+ deref = new_loc_descr (DW_OP_deref_size, size, 0);
+
+ /* Use DW_OP_deref_type for signed integral types if possible, but
+ convert back to the generic type to avoid type mismatches later. */
else
- op = DW_OP_deref_size;
+ {
+ deref = new_loc_descr (dwarf_OP (DW_OP_deref_type), size, 0);
+ deref->dw_loc_oprnd2.val_class = dw_val_class_die_ref;
+ deref->dw_loc_oprnd2.v.val_die_ref.die = type_die;
+ deref->dw_loc_oprnd2.v.val_die_ref.external = 0;
+ add_loc_descr (&deref,
+ new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0));
+ }
if (ret)
- add_loc_descr (&ret, new_loc_descr (op, size, 0));
+ add_loc_descr (&ret, deref);
else
- add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0));
+ add_loc_descr_to_each (list_ret, deref);
}
+
if (ret)
list_ret = new_loc_list (ret, NULL, 0, NULL, 0, NULL);
@@ -19473,25 +19512,22 @@ round_up_to_align (const offset_int &t, unsigned int align)
static dw_loc_descr_ref
type_byte_size (const_tree type, HOST_WIDE_INT *cst_size)
{
- tree tree_size;
- struct loc_descr_context ctx;
-
/* Return a constant integer in priority, if possible. */
*cst_size = int_size_in_bytes (type);
if (*cst_size != -1)
return NULL;
- ctx.context_type = const_cast<tree> (type);
- ctx.base_decl = NULL_TREE;
- ctx.dpi = NULL;
- ctx.placeholder_arg = false;
- ctx.placeholder_seen = false;
+ struct loc_descr_context ctx = {
+ const_cast<tree> (type), /* context_type */
+ NULL_TREE, /* base_decl */
+ NULL, /* dpi */
+ false, /* placeholder_arg */
+ false, /* placeholder_seen */
+ false /* strict_signedness */
+ };
- type = TYPE_MAIN_VARIANT (type);
- tree_size = TYPE_SIZE_UNIT (type);
- return ((tree_size != NULL_TREE)
- ? loc_descriptor_from_tree (tree_size, 0, &ctx)
- : NULL);
+ tree tree_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type));
+ return tree_size ? loc_descriptor_from_tree (tree_size, 0, &ctx) : NULL;
}
/* Helper structure for RECORD_TYPE processing. */
@@ -19668,12 +19704,14 @@ field_byte_offset (const_tree decl, struct vlr_context *ctx,
*cst_offset = wi::to_offset (tree_result).to_shwi ();
return NULL;
}
+
struct loc_descr_context loc_ctx = {
ctx->struct_type, /* context_type */
NULL_TREE, /* base_decl */
NULL, /* dpi */
false, /* placeholder_arg */
- false /* placeholder_seen */
+ false, /* placeholder_seen */
+ false /* strict_signedness */
};
loc_result = loc_list_from_tree (tree_result, 0, &loc_ctx);
@@ -22308,8 +22346,14 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
{
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);
- struct loc_descr_context context = { type, info->base_decl, NULL,
- false, false };
+ struct loc_descr_context context = {
+ type, /* context_type */
+ info->base_decl, /* base_decl */
+ NULL, /* dpi */
+ false, /* placeholder_arg */
+ false, /* placeholder_seen */
+ false /* strict_signedness */
+ };
enum dwarf_tag subrange_tag = DW_TAG_subrange_type;
int dim;
@@ -25292,13 +25336,6 @@ gen_variant_part (tree variant_part_decl, struct vlr_context *vlr_ctx,
{
const tree variant_part_type = TREE_TYPE (variant_part_decl);
tree variant_part_offset = vlr_ctx->variant_part_offset;
- struct loc_descr_context ctx = {
- vlr_ctx->struct_type, /* context_type */
- NULL_TREE, /* base_decl */
- NULL, /* dpi */
- false, /* placeholder_arg */
- false /* placeholder_seen */
- };
/* The FIELD_DECL node in STRUCT_TYPE that acts as the discriminant, or
NULL_TREE if there is no such field. */
@@ -25329,11 +25366,19 @@ gen_variant_part (tree variant_part_decl, struct vlr_context *vlr_ctx,
}
/* If the offset for this variant part is more complex than a constant,
- create a DWARF procedure for it so that we will not have to generate DWARF
- expressions for it for each member. */
+ create a DWARF procedure for it so that we will not have to generate
+ DWARF expressions for it for each member. */
if (TREE_CODE (variant_part_offset) != INTEGER_CST
&& (dwarf_version >= 3 || !dwarf_strict))
{
+ struct loc_descr_context ctx = {
+ vlr_ctx->struct_type, /* context_type */
+ NULL_TREE, /* base_decl */
+ NULL, /* dpi */
+ false, /* placeholder_arg */
+ false, /* placeholder_seen */
+ false /* strict_signedness */
+ };
const tree dwarf_proc_fndecl
= build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, NULL_TREE,
build_function_type (TREE_TYPE (variant_part_offset),