]>
Commit | Line | Data |
---|---|---|
5384b728 | 1 | 2002-08-21 Richard Henderson <rth@redhat.com> |
2 | ||
3 | * config/i386/i386-protos.h (i386_output_dwarf_dtprel): Add | |
4 | prototype. | |
5 | * config/i386/i386.c (i386_output_dwarf_dtprel): New. | |
6 | * config/i386/i386.h (ASM_OUTPUT_DWARF_DTPREL): Define. | |
7 | * dwarf2.h (DW_OP_GNU_push_tls_address): Add. | |
8 | (DW_OP_lo_user): Define to 0xe0. | |
9 | * dwarf2out.c (INTERNAL_DW_OP_tls_addr): Define. | |
10 | (dwarf_stack_op_name, sizeof_loc_descr): Handle a few more OPs. | |
11 | (output_loc_operands): Handle INTERNAL_DW_OP_tls_addr. | |
12 | (loc_descriptor_from_tree): Handle DECL_THREAD_LOCAL variables. | |
13 | (add_AT_location_description): Pass descr instead of rtl. | |
14 | (add_location_or_const_value_attribute, add_bound_info, | |
15 | gen_subprogram_die): Adjust its callers. | |
16 | (rtl_for_decl_location): Avoid constant pool references. | |
17 | ||
18 | --- gcc/config/i386/i386-protos.h 20 Aug 2002 17:20:36 -0000 1.1.1.1 | |
19 | +++ gcc/config/i386/i386-protos.h 20 Aug 2002 22:35:02 -0000 | |
20 | @@ -113,6 +113,7 @@ extern const char *output_fix_trunc PARA | |
21 | extern const char *output_fp_compare PARAMS ((rtx, rtx*, int, int)); | |
22 | ||
23 | extern void i386_dwarf_output_addr_const PARAMS ((FILE*, rtx)); | |
24 | +extern void i386_output_dwarf_dtprel PARAMS ((FILE*, int, rtx)); | |
25 | extern rtx i386_simplify_dwarf_addr PARAMS ((rtx)); | |
26 | ||
27 | extern void ix86_expand_clear PARAMS ((rtx)); | |
28 | --- gcc/config/i386/i386.c 20 Aug 2002 17:20:36 -0000 1.1.1.1 | |
29 | +++ gcc/config/i386/i386.c 20 Aug 2002 22:35:02 -0000 | |
30 | @@ -5921,6 +5921,33 @@ i386_dwarf_output_addr_const (file, x) | |
31 | fputc ('\n', file); | |
32 | } | |
33 | ||
34 | +/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL. | |
35 | + We need to emit DTP-relative relocations. */ | |
36 | + | |
37 | +void | |
38 | +i386_output_dwarf_dtprel (file, size, x) | |
39 | + FILE *file; | |
40 | + int size; | |
41 | + rtx x; | |
42 | +{ | |
43 | + switch (size) | |
44 | + { | |
45 | + case 4: | |
46 | + fputs (ASM_LONG, file); | |
47 | + break; | |
48 | + case 8: | |
49 | +#ifdef ASM_QUAD | |
50 | + fputs (ASM_QUAD, file); | |
51 | + break; | |
52 | +#endif | |
53 | + default: | |
54 | + abort (); | |
55 | + } | |
56 | + | |
57 | + output_addr_const (file, x); | |
58 | + fputs ("@DTPOFF", file); | |
59 | +} | |
60 | + | |
61 | /* In the name of slightly smaller debug output, and to cater to | |
62 | general assembler losage, recognize PIC+GOTOFF and turn it back | |
63 | into a direct symbol reference. */ | |
64 | --- gcc/config/i386/i386.h 20 Aug 2002 17:20:36 -0000 1.1.1.1 | |
65 | +++ gcc/config/i386/i386.h 20 Aug 2002 22:35:02 -0000 | |
66 | @@ -2899,6 +2899,13 @@ extern int const svr4_dbx_register_map[F | |
67 | #define ASM_SIMPLIFY_DWARF_ADDR(X) \ | |
68 | i386_simplify_dwarf_addr (X) | |
69 | ||
70 | +/* Emit a dtp-relative reference to a TLS variable. */ | |
71 | + | |
72 | +#ifdef HAVE_AS_TLS | |
73 | +#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \ | |
74 | + i386_output_dwarf_dtprel (FILE, SIZE, X) | |
75 | +#endif | |
76 | + | |
77 | /* Switch to init or fini section via SECTION_OP, emit a call to FUNC, | |
78 | and switch back. For x86 we do this only to save a few bytes that | |
79 | would otherwise be unused in the text section. */ | |
80 | --- gcc/dwarf2.h 20 Aug 2002 17:20:19 -0000 1.1.1.1 | |
81 | +++ gcc/dwarf2.h 20 Aug 2002 22:35:02 -0000 | |
82 | @@ -399,10 +399,12 @@ enum dwarf_location_atom | |
83 | DW_OP_push_object_address = 0x97, | |
84 | DW_OP_call2 = 0x98, | |
85 | DW_OP_call4 = 0x99, | |
86 | - DW_OP_calli = 0x9a | |
87 | + DW_OP_call_ref = 0x9a, | |
88 | + /* GNU extensions. */ | |
89 | + DW_OP_GNU_push_tls_address = 0xe0 | |
90 | }; | |
91 | ||
92 | -#define DW_OP_lo_user 0x80 /* Implementation-defined range start. */ | |
93 | +#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */ | |
94 | #define DW_OP_hi_user 0xff /* Implementation-defined range end. */ | |
95 | ||
96 | /* Type encodings. */ | |
97 | --- gcc/dwarf2out.c 20 Aug 2002 17:20:19 -0000 1.1.1.1 | |
98 | +++ gcc/dwarf2out.c 20 Aug 2002 22:40:42 -0000 | |
99 | @@ -2169,6 +2169,11 @@ dwarf2out_frame_finish () | |
100 | /* And now, the subset of the debugging information support code necessary | |
101 | for emitting location expressions. */ | |
102 | ||
103 | +/* We need some way to distinguish DW_OP_addr with a direct symbol | |
104 | + relocation from DW_OP_addr with a dtp-relative symbol relocation. */ | |
105 | +#define INTERNAL_DW_OP_tls_addr (0x100 + DW_OP_addr) | |
106 | + | |
107 | + | |
108 | typedef struct dw_val_struct *dw_val_ref; | |
109 | typedef struct die_struct *dw_die_ref; | |
110 | typedef struct dw_loc_descr_struct *dw_loc_descr_ref; | |
111 | @@ -2294,6 +2299,7 @@ dwarf_stack_op_name (op) | |
112 | switch (op) | |
113 | { | |
114 | case DW_OP_addr: | |
115 | + case INTERNAL_DW_OP_tls_addr: | |
116 | return "DW_OP_addr"; | |
117 | case DW_OP_deref: | |
118 | return "DW_OP_deref"; | |
119 | @@ -2583,6 +2589,16 @@ dwarf_stack_op_name (op) | |
120 | return "DW_OP_xderef_size"; | |
121 | case DW_OP_nop: | |
122 | return "DW_OP_nop"; | |
123 | + case DW_OP_push_object_address: | |
124 | + return "DW_OP_push_object_address"; | |
125 | + case DW_OP_call2: | |
126 | + return "DW_OP_call2"; | |
127 | + case DW_OP_call4: | |
128 | + return "DW_OP_call4"; | |
129 | + case DW_OP_call_ref: | |
130 | + return "DW_OP_call_ref"; | |
131 | + case DW_OP_GNU_push_tls_address: | |
132 | + return "DW_OP_GNU_push_tls_address"; | |
133 | default: | |
134 | return "OP_<unknown>"; | |
135 | } | |
136 | @@ -2640,6 +2656,7 @@ size_of_loc_descr (loc) | |
137 | switch (loc->dw_loc_opc) | |
138 | { | |
139 | case DW_OP_addr: | |
140 | + case INTERNAL_DW_OP_tls_addr: | |
141 | size += DWARF2_ADDR_SIZE; | |
142 | break; | |
143 | case DW_OP_const1u: | |
144 | @@ -2725,6 +2742,15 @@ size_of_loc_descr (loc) | |
145 | case DW_OP_xderef_size: | |
146 | size += 1; | |
147 | break; | |
148 | + case DW_OP_call2: | |
149 | + size += 2; | |
150 | + break; | |
151 | + case DW_OP_call4: | |
152 | + size += 4; | |
153 | + break; | |
154 | + case DW_OP_call_ref: | |
155 | + size += DWARF2_ADDR_SIZE; | |
156 | + break; | |
157 | default: | |
158 | break; | |
159 | } | |
160 | @@ -2874,6 +2900,17 @@ output_loc_operands (loc) | |
161 | case DW_OP_xderef_size: | |
162 | dw2_asm_output_data (1, val1->v.val_int, NULL); | |
163 | break; | |
164 | + | |
165 | + case INTERNAL_DW_OP_tls_addr: | |
166 | +#ifdef ASM_OUTPUT_DWARF_DTPREL | |
167 | + ASM_OUTPUT_DWARF_DTPREL (asm_out_file, DWARF2_ADDR_SIZE, | |
168 | + val1->v.val_addr); | |
169 | + fputc ('\n', asm_out_file); | |
170 | +#else | |
171 | + abort (); | |
172 | +#endif | |
173 | + break; | |
174 | + | |
175 | default: | |
176 | /* Other codes have no operands. */ | |
177 | break; | |
178 | @@ -3598,7 +3635,8 @@ static unsigned int simple_field_decl_al | |
179 | static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree)); | |
180 | static HOST_WIDE_INT field_byte_offset PARAMS ((tree)); | |
181 | static void add_AT_location_description PARAMS ((dw_die_ref, | |
182 | - enum dwarf_attribute, rtx)); | |
183 | + enum dwarf_attribute, | |
184 | + dw_loc_descr_ref)); | |
185 | static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree)); | |
186 | static void add_const_value_attribute PARAMS ((dw_die_ref, rtx)); | |
187 | static rtx rtl_for_decl_location PARAMS ((tree)); | |
188 | @@ -8031,6 +8069,41 @@ loc_descriptor_from_tree (loc, addressp) | |
189 | : 0); | |
190 | ||
191 | case VAR_DECL: | |
192 | + if (DECL_THREAD_LOCAL (loc)) | |
193 | + { | |
194 | + rtx rtl; | |
195 | + | |
196 | +#ifndef ASM_OUTPUT_DWARF_DTPREL | |
197 | + /* If this is not defined, we have no way to emit the data. */ | |
198 | + return 0; | |
199 | +#endif | |
200 | + /* The way DW_OP_GNU_push_tls_address is specified, we can only | |
201 | + look up addresses of objects in the current module. */ | |
202 | + if (DECL_P (loc) && TREE_PUBLIC (loc) && !MODULE_LOCAL_P (loc)) | |
203 | + return 0; | |
204 | + | |
205 | + rtl = rtl_for_decl_location (loc); | |
206 | + if (rtl == NULL_RTX) | |
207 | + return 0; | |
208 | + | |
209 | + if (GET_CODE (rtl) != MEM) | |
210 | + return 0; | |
211 | + rtl = XEXP (rtl, 0); | |
212 | + if (! CONSTANT_P (rtl)) | |
213 | + return 0; | |
214 | + | |
215 | + ret = new_loc_descr (INTERNAL_DW_OP_tls_addr, 0, 0); | |
216 | + ret->dw_loc_oprnd1.val_class = dw_val_class_addr; | |
217 | + ret->dw_loc_oprnd1.v.val_addr = rtl; | |
218 | + | |
219 | + ret1 = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0); | |
220 | + add_loc_descr (&ret, ret1); | |
221 | + | |
222 | + indirect_p = 1; | |
223 | + break; | |
224 | + } | |
225 | + /* FALLTHRU */ | |
226 | + | |
227 | case PARM_DECL: | |
228 | { | |
229 | rtx rtl = rtl_for_decl_location (loc); | |
230 | @@ -8531,14 +8604,12 @@ field_byte_offset (decl) | |
231 | whole parameters. Note that the location attributes for struct fields are | |
232 | generated by the routine `data_member_location_attribute' below. */ | |
233 | ||
234 | -static void | |
235 | -add_AT_location_description (die, attr_kind, rtl) | |
236 | +static inline void | |
237 | +add_AT_location_description (die, attr_kind, descr) | |
238 | dw_die_ref die; | |
239 | enum dwarf_attribute attr_kind; | |
240 | - rtx rtl; | |
241 | + dw_loc_descr_ref descr; | |
242 | { | |
243 | - dw_loc_descr_ref descr = loc_descriptor (rtl); | |
244 | - | |
245 | if (descr != 0) | |
246 | add_AT_loc (die, attr_kind, descr); | |
247 | } | |
248 | @@ -8963,6 +9034,13 @@ rtl_for_decl_location (decl) | |
249 | if (rtl) | |
250 | rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); | |
251 | #endif | |
252 | + | |
253 | + /* If we don't look past the constant pool, we risk emitting a | |
254 | + reference to a constant pool entry that isn't referenced from | |
255 | + code, and thus is not emitted. */ | |
256 | + if (rtl) | |
257 | + rtl = avoid_constant_pool_reference (rtl); | |
258 | + | |
259 | return rtl; | |
260 | } | |
261 | ||
262 | @@ -8983,6 +9061,7 @@ add_location_or_const_value_attribute (d | |
263 | tree decl; | |
264 | { | |
265 | rtx rtl; | |
266 | + dw_loc_descr_ref descr; | |
267 | ||
268 | if (TREE_CODE (decl) == ERROR_MARK) | |
269 | return; | |
270 | @@ -8993,16 +9072,11 @@ add_location_or_const_value_attribute (d | |
271 | if (rtl == NULL_RTX) | |
272 | return; | |
273 | ||
274 | - /* If we don't look past the constant pool, we risk emitting a | |
275 | - reference to a constant pool entry that isn't referenced from | |
276 | - code, and thus is not emitted. */ | |
277 | - rtl = avoid_constant_pool_reference (rtl); | |
278 | - | |
279 | switch (GET_CODE (rtl)) | |
280 | { | |
281 | case ADDRESSOF: | |
282 | - /* The address of a variable that was optimized away; don't emit | |
283 | - anything. */ | |
284 | + /* The address of a variable that was optimized away; | |
285 | + don't emit anything. */ | |
286 | break; | |
287 | ||
288 | case CONST_INT: | |
289 | @@ -9017,12 +9091,24 @@ add_location_or_const_value_attribute (d | |
290 | break; | |
291 | ||
292 | case MEM: | |
293 | - case REG: | |
294 | - case SUBREG: | |
295 | - case CONCAT: | |
296 | - add_AT_location_description (die, DW_AT_location, rtl); | |
297 | + if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) | |
298 | + { | |
299 | + /* Need loc_descriptor_from_tree since that's where we know | |
300 | + how to handle TLS variables. Want the object's address | |
301 | + since the top-level DW_AT_location assumes such. See | |
302 | + the confusion in loc_descriptor for reference. */ | |
303 | + descr = loc_descriptor_from_tree (decl, 1); | |
304 | + } | |
305 | + else | |
306 | + { | |
307 | + case REG: | |
308 | + case SUBREG: | |
309 | + case CONCAT: | |
310 | + descr = loc_descriptor (rtl); | |
311 | + } | |
312 | + add_AT_location_description (die, DW_AT_location, descr); | |
313 | break; | |
314 | - | |
315 | + | |
316 | default: | |
317 | abort (); | |
318 | } | |
319 | @@ -9154,7 +9240,8 @@ add_bound_info (subrange_die, bound_attr | |
320 | ||
321 | add_AT_flag (decl_die, DW_AT_artificial, 1); | |
322 | add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); | |
323 | - add_AT_location_description (decl_die, DW_AT_location, loc); | |
324 | + add_AT_location_description (decl_die, DW_AT_location, | |
325 | + loc_descriptor (loc)); | |
326 | add_AT_die_ref (subrange_die, bound_attr, decl_die); | |
327 | } | |
328 | ||
329 | @@ -10359,7 +10446,7 @@ gen_subprogram_die (decl, context_die) | |
330 | is not part of the state saved/restored for inline functions. */ | |
331 | if (current_function_needs_context) | |
332 | add_AT_location_description (subr_die, DW_AT_static_link, | |
333 | - lookup_static_chain (decl)); | |
334 | + loc_descriptor (lookup_static_chain (decl))); | |
335 | #endif | |
336 | } | |
337 |