dwarf2.h (DW_OP_call_ref): Rename from DW_OP_calli.
* dwarf2.h (DW_OP_call_ref): Rename from DW_OP_calli. (DW_OP_GNU_push_tls_address): New. (DW_OP_lo_user): Fix. * dwarf2out.c (INTERNAL_DW_OP_tls_addr): New. (dwarf_stack_op_name): Handle it, plus other dwarf3 opcodes. (size_of_loc_descr): Likewise. (output_loc_operands): Handle INTERNAL_DW_OP_tls_addr. (add_AT_location_description): Take a dw_loc_descr_ref not an rtx. (loc_descriptor_from_tree): Handle TLS variables. (rtl_for_decl_location): Do avoid_constant_pool_reference here ... (add_location_or_const_value_attribute): ... not here. Defer to loc_descriptor_from_tree for TLS variables. * config/i386/i386.h (ASM_OUTPUT_DWARF_DTPREL): New. * config/i386/i386.c (i386_output_dwarf_dtprel): New. * config/i386/i386-protos.h: Update. From-SVN: r56957
This commit is contained in:
parent
7df988780b
commit
b920346356
@ -1,3 +1,22 @@
|
||||
2002-09-08 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* dwarf2.h (DW_OP_call_ref): Rename from DW_OP_calli.
|
||||
(DW_OP_GNU_push_tls_address): New.
|
||||
(DW_OP_lo_user): Fix.
|
||||
* dwarf2out.c (INTERNAL_DW_OP_tls_addr): New.
|
||||
(dwarf_stack_op_name): Handle it, plus other dwarf3 opcodes.
|
||||
(size_of_loc_descr): Likewise.
|
||||
(output_loc_operands): Handle INTERNAL_DW_OP_tls_addr.
|
||||
(add_AT_location_description): Take a dw_loc_descr_ref not an rtx.
|
||||
(loc_descriptor_from_tree): Handle TLS variables.
|
||||
(rtl_for_decl_location): Do avoid_constant_pool_reference here ...
|
||||
(add_location_or_const_value_attribute): ... not here. Defer
|
||||
to loc_descriptor_from_tree for TLS variables.
|
||||
|
||||
* config/i386/i386.h (ASM_OUTPUT_DWARF_DTPREL): New.
|
||||
* config/i386/i386.c (i386_output_dwarf_dtprel): New.
|
||||
* config/i386/i386-protos.h: Update.
|
||||
|
||||
2002-09-08 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR optimization/6405
|
||||
|
@ -110,6 +110,7 @@ extern const char *output_fix_trunc PARAMS ((rtx, rtx*));
|
||||
extern const char *output_fp_compare PARAMS ((rtx, rtx*, int, int));
|
||||
|
||||
extern void i386_dwarf_output_addr_const PARAMS ((FILE*, rtx));
|
||||
extern void i386_output_dwarf_dtprel PARAMS ((FILE*, int, rtx));
|
||||
extern rtx i386_simplify_dwarf_addr PARAMS ((rtx));
|
||||
|
||||
extern void ix86_expand_clear PARAMS ((rtx));
|
||||
|
@ -5956,6 +5956,33 @@ i386_dwarf_output_addr_const (file, x)
|
||||
fputc ('\n', file);
|
||||
}
|
||||
|
||||
/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
|
||||
We need to emit DTP-relative relocations. */
|
||||
|
||||
void
|
||||
i386_output_dwarf_dtprel (file, size, x)
|
||||
FILE *file;
|
||||
int size;
|
||||
rtx x;
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 4:
|
||||
fputs (ASM_LONG, file);
|
||||
break;
|
||||
case 8:
|
||||
#ifdef ASM_QUAD
|
||||
fputs (ASM_QUAD, file);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
output_addr_const (file, x);
|
||||
fputs ("@DTPOFF", file);
|
||||
}
|
||||
|
||||
/* In the name of slightly smaller debug output, and to cater to
|
||||
general assembler losage, recognize PIC+GOTOFF and turn it back
|
||||
into a direct symbol reference. */
|
||||
|
@ -3021,6 +3021,13 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
|
||||
#define ASM_SIMPLIFY_DWARF_ADDR(X) \
|
||||
i386_simplify_dwarf_addr (X)
|
||||
|
||||
/* Emit a dtp-relative reference to a TLS variable. */
|
||||
|
||||
#ifdef HAVE_AS_TLS
|
||||
#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
|
||||
i386_output_dwarf_dtprel (FILE, SIZE, X)
|
||||
#endif
|
||||
|
||||
/* Switch to init or fini section via SECTION_OP, emit a call to FUNC,
|
||||
and switch back. For x86 we do this only to save a few bytes that
|
||||
would otherwise be unused in the text section. */
|
||||
|
@ -399,10 +399,12 @@ enum dwarf_location_atom
|
||||
DW_OP_push_object_address = 0x97,
|
||||
DW_OP_call2 = 0x98,
|
||||
DW_OP_call4 = 0x99,
|
||||
DW_OP_calli = 0x9a
|
||||
DW_OP_call_ref = 0x9a,
|
||||
/* GNU extensions. */
|
||||
DW_OP_GNU_push_tls_address = 0xe0
|
||||
};
|
||||
|
||||
#define DW_OP_lo_user 0x80 /* Implementation-defined range start. */
|
||||
#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */
|
||||
#define DW_OP_hi_user 0xff /* Implementation-defined range end. */
|
||||
|
||||
/* Type encodings. */
|
||||
|
128
gcc/dwarf2out.c
128
gcc/dwarf2out.c
@ -2182,6 +2182,11 @@ dwarf2out_frame_finish ()
|
||||
/* And now, the subset of the debugging information support code necessary
|
||||
for emitting location expressions. */
|
||||
|
||||
/* We need some way to distinguish DW_OP_addr with a direct symbol
|
||||
relocation from DW_OP_addr with a dtp-relative symbol relocation. */
|
||||
#define INTERNAL_DW_OP_tls_addr (0x100 + DW_OP_addr)
|
||||
|
||||
|
||||
typedef struct dw_val_struct *dw_val_ref;
|
||||
typedef struct die_struct *dw_die_ref;
|
||||
typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
|
||||
@ -2307,6 +2312,7 @@ dwarf_stack_op_name (op)
|
||||
switch (op)
|
||||
{
|
||||
case DW_OP_addr:
|
||||
case INTERNAL_DW_OP_tls_addr:
|
||||
return "DW_OP_addr";
|
||||
case DW_OP_deref:
|
||||
return "DW_OP_deref";
|
||||
@ -2596,6 +2602,16 @@ dwarf_stack_op_name (op)
|
||||
return "DW_OP_xderef_size";
|
||||
case DW_OP_nop:
|
||||
return "DW_OP_nop";
|
||||
case DW_OP_push_object_address:
|
||||
return "DW_OP_push_object_address";
|
||||
case DW_OP_call2:
|
||||
return "DW_OP_call2";
|
||||
case DW_OP_call4:
|
||||
return "DW_OP_call4";
|
||||
case DW_OP_call_ref:
|
||||
return "DW_OP_call_ref";
|
||||
case DW_OP_GNU_push_tls_address:
|
||||
return "DW_OP_GNU_push_tls_address";
|
||||
default:
|
||||
return "OP_<unknown>";
|
||||
}
|
||||
@ -2653,6 +2669,7 @@ size_of_loc_descr (loc)
|
||||
switch (loc->dw_loc_opc)
|
||||
{
|
||||
case DW_OP_addr:
|
||||
case INTERNAL_DW_OP_tls_addr:
|
||||
size += DWARF2_ADDR_SIZE;
|
||||
break;
|
||||
case DW_OP_const1u:
|
||||
@ -2738,6 +2755,15 @@ size_of_loc_descr (loc)
|
||||
case DW_OP_xderef_size:
|
||||
size += 1;
|
||||
break;
|
||||
case DW_OP_call2:
|
||||
size += 2;
|
||||
break;
|
||||
case DW_OP_call4:
|
||||
size += 4;
|
||||
break;
|
||||
case DW_OP_call_ref:
|
||||
size += DWARF2_ADDR_SIZE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2887,6 +2913,17 @@ output_loc_operands (loc)
|
||||
case DW_OP_xderef_size:
|
||||
dw2_asm_output_data (1, val1->v.val_int, NULL);
|
||||
break;
|
||||
|
||||
case INTERNAL_DW_OP_tls_addr:
|
||||
#ifdef ASM_OUTPUT_DWARF_DTPREL
|
||||
ASM_OUTPUT_DWARF_DTPREL (asm_out_file, DWARF2_ADDR_SIZE,
|
||||
val1->v.val_addr);
|
||||
fputc ('\n', asm_out_file);
|
||||
#else
|
||||
abort ();
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other codes have no operands. */
|
||||
break;
|
||||
@ -3590,7 +3627,8 @@ static unsigned int simple_decl_align_in_bits PARAMS ((tree));
|
||||
static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree));
|
||||
static HOST_WIDE_INT field_byte_offset PARAMS ((tree));
|
||||
static void add_AT_location_description PARAMS ((dw_die_ref,
|
||||
enum dwarf_attribute, rtx));
|
||||
enum dwarf_attribute,
|
||||
dw_loc_descr_ref));
|
||||
static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
|
||||
static void add_const_value_attribute PARAMS ((dw_die_ref, rtx));
|
||||
static rtx rtl_for_decl_location PARAMS ((tree));
|
||||
@ -8015,6 +8053,42 @@ loc_descriptor_from_tree (loc, addressp)
|
||||
: 0);
|
||||
|
||||
case VAR_DECL:
|
||||
if (DECL_THREAD_LOCAL (loc))
|
||||
{
|
||||
rtx rtl;
|
||||
|
||||
#ifndef ASM_OUTPUT_DWARF_DTPREL
|
||||
/* If this is not defined, we have no way to emit the data. */
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* The way DW_OP_GNU_push_tls_address is specified, we can only
|
||||
look up addresses of objects in the current module. */
|
||||
if (! (*targetm.binds_local_p) (loc))
|
||||
return 0;
|
||||
|
||||
rtl = rtl_for_decl_location (loc);
|
||||
if (rtl == NULL_RTX)
|
||||
return 0;
|
||||
|
||||
if (GET_CODE (rtl) != MEM)
|
||||
return 0;
|
||||
rtl = XEXP (rtl, 0);
|
||||
if (! CONSTANT_P (rtl))
|
||||
return 0;
|
||||
|
||||
ret = new_loc_descr (INTERNAL_DW_OP_tls_addr, 0, 0);
|
||||
ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
|
||||
ret->dw_loc_oprnd1.v.val_addr = rtl;
|
||||
|
||||
ret1 = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
|
||||
add_loc_descr (&ret, ret1);
|
||||
|
||||
indirect_p = 1;
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case PARM_DECL:
|
||||
{
|
||||
rtx rtl = rtl_for_decl_location (loc);
|
||||
@ -8497,14 +8571,12 @@ field_byte_offset (decl)
|
||||
whole parameters. Note that the location attributes for struct fields are
|
||||
generated by the routine `data_member_location_attribute' below. */
|
||||
|
||||
static void
|
||||
add_AT_location_description (die, attr_kind, rtl)
|
||||
static inline void
|
||||
add_AT_location_description (die, attr_kind, descr)
|
||||
dw_die_ref die;
|
||||
enum dwarf_attribute attr_kind;
|
||||
rtx rtl;
|
||||
dw_loc_descr_ref descr;
|
||||
{
|
||||
dw_loc_descr_ref descr = loc_descriptor (rtl);
|
||||
|
||||
if (descr != 0)
|
||||
add_AT_loc (die, attr_kind, descr);
|
||||
}
|
||||
@ -8929,6 +9001,13 @@ rtl_for_decl_location (decl)
|
||||
if (rtl)
|
||||
rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
|
||||
#endif
|
||||
|
||||
/* If we don't look past the constant pool, we risk emitting a
|
||||
reference to a constant pool entry that isn't referenced from
|
||||
code, and thus is not emitted. */
|
||||
if (rtl)
|
||||
rtl = avoid_constant_pool_reference (rtl);
|
||||
|
||||
return rtl;
|
||||
}
|
||||
|
||||
@ -8949,6 +9028,7 @@ add_location_or_const_value_attribute (die, decl)
|
||||
tree decl;
|
||||
{
|
||||
rtx rtl;
|
||||
dw_loc_descr_ref descr;
|
||||
|
||||
if (TREE_CODE (decl) == ERROR_MARK)
|
||||
return;
|
||||
@ -8959,16 +9039,11 @@ add_location_or_const_value_attribute (die, decl)
|
||||
if (rtl == NULL_RTX)
|
||||
return;
|
||||
|
||||
/* If we don't look past the constant pool, we risk emitting a
|
||||
reference to a constant pool entry that isn't referenced from
|
||||
code, and thus is not emitted. */
|
||||
rtl = avoid_constant_pool_reference (rtl);
|
||||
|
||||
switch (GET_CODE (rtl))
|
||||
{
|
||||
case ADDRESSOF:
|
||||
/* The address of a variable that was optimized away; don't emit
|
||||
anything. */
|
||||
/* The address of a variable that was optimized away;
|
||||
don't emit anything. */
|
||||
break;
|
||||
|
||||
case CONST_INT:
|
||||
@ -8983,12 +9058,24 @@ add_location_or_const_value_attribute (die, decl)
|
||||
break;
|
||||
|
||||
case MEM:
|
||||
case REG:
|
||||
case SUBREG:
|
||||
case CONCAT:
|
||||
add_AT_location_description (die, DW_AT_location, rtl);
|
||||
if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
|
||||
{
|
||||
/* Need loc_descriptor_from_tree since that's where we know
|
||||
how to handle TLS variables. Want the object's address
|
||||
since the top-level DW_AT_location assumes such. See
|
||||
the confusion in loc_descriptor for reference. */
|
||||
descr = loc_descriptor_from_tree (decl, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
case REG:
|
||||
case SUBREG:
|
||||
case CONCAT:
|
||||
descr = loc_descriptor (rtl);
|
||||
}
|
||||
add_AT_location_description (die, DW_AT_location, descr);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
@ -9120,7 +9207,8 @@ add_bound_info (subrange_die, bound_attr, bound)
|
||||
|
||||
add_AT_flag (decl_die, DW_AT_artificial, 1);
|
||||
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
|
||||
add_AT_location_description (decl_die, DW_AT_location, loc);
|
||||
add_AT_location_description (decl_die, DW_AT_location,
|
||||
loc_descriptor (loc));
|
||||
add_AT_die_ref (subrange_die, bound_attr, decl_die);
|
||||
}
|
||||
|
||||
@ -10325,7 +10413,7 @@ gen_subprogram_die (decl, context_die)
|
||||
is not part of the state saved/restored for inline functions. */
|
||||
if (current_function_needs_context)
|
||||
add_AT_location_description (subr_die, DW_AT_static_link,
|
||||
lookup_static_chain (decl));
|
||||
loc_descriptor (lookup_static_chain (decl)));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user