diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-09-08 18:36:54 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-09-08 18:36:54 +0000 |
commit | 931e9893f8dc1bedd8ba650153bb6aa104d12b38 (patch) | |
tree | 836174b555f80b032094c6faa9d7b90163ee8351 /gcc | |
parent | 978dc23eff054e366cfc305fd6caa39597fa9032 (diff) | |
download | gcc-931e9893f8dc1bedd8ba650153bb6aa104d12b38.tar.gz |
* 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: svn+ssh://gcc.gnu.org/svn/gcc/trunk@56957 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 27 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 7 | ||||
-rw-r--r-- | gcc/dwarf2.h | 6 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 128 |
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 } |