aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-09-08 18:36:54 +0000
committerRichard Henderson <rth@redhat.com>2002-09-08 18:36:54 +0000
commitef49202bb20d4b968005c497c47567fd96bd3f84 (patch)
tree836174b555f80b032094c6faa9d7b90163ee8351
parentd6d6d300ab87ea4fa103e3ca802a73eca5a6de3e (diff)
* 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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@56957 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c27
-rw-r--r--gcc/config/i386/i386.h7
-rw-r--r--gcc/dwarf2.h6
-rw-r--r--gcc/dwarf2out.c128
6 files changed, 166 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 43f4844e1f5..9a2754e3c5e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index a81e0f537b2..bec35aebeee 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -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));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a000bae754c..1d0d1601820 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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. */
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 1c75c20591f..d04c60569a6 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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. */
diff --git a/gcc/dwarf2.h b/gcc/dwarf2.h
index a84eb2cabd1..a7f5f0f8d68 100644
--- a/gcc/dwarf2.h
+++ b/gcc/dwarf2.h
@@ -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. */
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index e8f02e62f5f..5757d247d71 100644
--- a/gcc/dwarf2out.c
+++ b/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
}