3adb7e5dcf6278b3a49ff1078c83178583408874
[gcc.git] / gcc / dwarf2asm.c
1 /* Dwarf2 assembler output helper routines.
2 Copyright (C) 2001 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21
22 #include "config.h"
23 #include "system.h"
24 #include "flags.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "output.h"
28 #include "dwarf2asm.h"
29 #include "dwarf2.h"
30 #include "splay-tree.h"
31 #include "ggc.h"
32 #include "tm_p.h"
33
34
35 /* How to start an assembler comment. */
36 #ifndef ASM_COMMENT_START
37 #define ASM_COMMENT_START ";#"
38 #endif
39
40 /* We don't have unaligned support, let's hope the normal output works for
41 .debug_frame. But we know it won't work for .debug_info. */
42 #if !defined(UNALIGNED_INT_ASM_OP) && defined(DWARF2_DEBUGGING_INFO)
43 #error DWARF2_DEBUGGING_INFO requires UNALIGNED_INT_ASM_OP.
44 #endif
45
46 \f
47 /* Despite the fact that assemble_integer handles unaligned data,
48 continue emitting things by hand when possible, since that makes
49 the assembler commentary come out prettier. */
50 #ifdef UNALIGNED_INT_ASM_OP
51 static const char * unaligned_integer_asm_op PARAMS ((int));
52
53 static inline const char *
54 unaligned_integer_asm_op (size)
55 int size;
56 {
57 const char *op = NULL;
58 switch (size)
59 {
60 case 1:
61 op = ASM_BYTE_OP;
62 break;
63 case 2:
64 op = UNALIGNED_SHORT_ASM_OP;
65 break;
66 case 4:
67 op = UNALIGNED_INT_ASM_OP;
68 break;
69 case 8:
70 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
71 op = UNALIGNED_DOUBLE_INT_ASM_OP;
72 break;
73 #endif
74 default:
75 abort ();
76 }
77
78 if (! op)
79 abort ();
80
81 return op;
82 }
83 #endif /* UNALIGNED_INT_ASM_OP */
84
85 /* Output an immediate constant in a given size. */
86
87 void
88 dw2_asm_output_data VPARAMS ((int size, unsigned HOST_WIDE_INT value,
89 const char *comment, ...))
90 {
91 VA_OPEN (ap, comment);
92 VA_FIXEDARG (ap, int, size);
93 VA_FIXEDARG (ap, unsigned HOST_WIDE_INT, value);
94 VA_FIXEDARG (ap, const char *, comment);
95
96 if (size * 8 < HOST_BITS_PER_WIDE_INT)
97 value &= ~(~(unsigned HOST_WIDE_INT)0 << (size * 8));
98
99 #ifdef UNALIGNED_INT_ASM_OP
100 fputs (unaligned_integer_asm_op (size), asm_out_file);
101 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
102 #else
103 assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
104 #endif
105
106 if (flag_debug_asm && comment)
107 {
108 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
109 vfprintf (asm_out_file, comment, ap);
110 }
111 fputc ('\n', asm_out_file);
112
113 VA_CLOSE (ap);
114 }
115
116 /* Output the difference between two symbols in a given size. */
117 /* ??? There appear to be assemblers that do not like such
118 subtraction, but do support ASM_SET_OP. It's unfortunately
119 impossible to do here, since the ASM_SET_OP for the difference
120 symbol must appear after both symbols are defined. */
121
122 void
123 dw2_asm_output_delta VPARAMS ((int size, const char *lab1, const char *lab2,
124 const char *comment, ...))
125 {
126 VA_OPEN (ap, comment);
127 VA_FIXEDARG (ap, int, size);
128 VA_FIXEDARG (ap, const char *, lab1);
129 VA_FIXEDARG (ap, const char *, lab2);
130 VA_FIXEDARG (ap, const char *, comment);
131
132 #ifdef UNALIGNED_INT_ASM_OP
133 fputs (unaligned_integer_asm_op (size), asm_out_file);
134 assemble_name (asm_out_file, lab1);
135 fputc ('-', asm_out_file);
136 assemble_name (asm_out_file, lab2);
137 #else
138 assemble_integer (gen_rtx_MINUS (Pmode, gen_rtx_SYMBOL_REF (Pmode, lab1),
139 gen_rtx_SYMBOL_REF (Pmode, lab2)),
140 size, BITS_PER_UNIT, 1);
141 #endif
142
143 if (flag_debug_asm && comment)
144 {
145 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
146 vfprintf (asm_out_file, comment, ap);
147 }
148 fputc ('\n', asm_out_file);
149
150 VA_CLOSE (ap);
151 }
152
153 /* Output a section-relative reference to a label. In general this
154 can only be done for debugging symbols. E.g. on most targets with
155 the GNU linker, this is accomplished with a direct reference and
156 the knowledge that the debugging section will be placed at VMA 0.
157 Some targets have special relocations for this that we must use. */
158
159 void
160 dw2_asm_output_offset VPARAMS ((int size, const char *label,
161 const char *comment, ...))
162 {
163 VA_OPEN (ap, comment);
164 VA_FIXEDARG (ap, int, size);
165 VA_FIXEDARG (ap, const char *, label);
166 VA_FIXEDARG (ap, const char *, comment);
167
168 #ifdef ASM_OUTPUT_DWARF_OFFSET
169 ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label);
170 #else
171 #ifdef UNALIGNED_INT_ASM_OP
172 fputs (unaligned_integer_asm_op (size), asm_out_file);
173 assemble_name (asm_out_file, label);
174 #else
175 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, BITS_PER_UNIT, 1);
176 #endif
177 #endif
178
179 if (flag_debug_asm && comment)
180 {
181 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
182 vfprintf (asm_out_file, comment, ap);
183 }
184 fputc ('\n', asm_out_file);
185
186 VA_CLOSE (ap);
187 }
188
189 /* Output a self-relative reference to a label, possibly in a
190 different section or object file. */
191
192 void
193 dw2_asm_output_pcrel VPARAMS ((int size ATTRIBUTE_UNUSED,
194 const char *label ATTRIBUTE_UNUSED,
195 const char *comment, ...))
196 {
197 VA_OPEN (ap, comment);
198 VA_FIXEDARG (ap, int, size);
199 VA_FIXEDARG (ap, const char *, label);
200 VA_FIXEDARG (ap, const char *, comment);
201
202 #ifdef ASM_OUTPUT_DWARF_PCREL
203 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
204 #else
205 #ifdef UNALIGNED_INT_ASM_OP
206 fputs (unaligned_integer_asm_op (size), asm_out_file);
207 assemble_name (asm_out_file, label);
208 fputc ('-', asm_out_file);
209 fputc ('.', asm_out_file);
210 #else
211 abort ();
212 #endif
213 #endif
214
215 if (flag_debug_asm && comment)
216 {
217 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
218 vfprintf (asm_out_file, comment, ap);
219 }
220 fputc ('\n', asm_out_file);
221
222 VA_CLOSE (ap);
223 }
224
225 /* Output an absolute reference to a label. */
226
227 void
228 dw2_asm_output_addr VPARAMS ((int size, const char *label,
229 const char *comment, ...))
230 {
231 VA_OPEN (ap, comment);
232 VA_FIXEDARG (ap, int, size);
233 VA_FIXEDARG (ap, const char *, label);
234 VA_FIXEDARG (ap, const char *, comment);
235
236 #ifdef UNALIGNED_INT_ASM_OP
237 fputs (unaligned_integer_asm_op (size), asm_out_file);
238 assemble_name (asm_out_file, label);
239 #else
240 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, label), size, BITS_PER_UNIT, 1);
241 #endif
242
243 if (flag_debug_asm && comment)
244 {
245 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
246 vfprintf (asm_out_file, comment, ap);
247 }
248 fputc ('\n', asm_out_file);
249
250 VA_CLOSE (ap);
251 }
252
253 /* Similar, but use an RTX expression instead of a text label. */
254
255 void
256 dw2_asm_output_addr_rtx VPARAMS ((int size, rtx addr,
257 const char *comment, ...))
258 {
259 VA_OPEN (ap, comment);
260 VA_FIXEDARG (ap, int, size);
261 VA_FIXEDARG (ap, rtx, addr);
262 VA_FIXEDARG (ap, const char *, comment);
263
264 #ifdef UNALIGNED_INT_ASM_OP
265 fputs (unaligned_integer_asm_op (size), asm_out_file);
266 output_addr_const (asm_out_file, addr);
267 #else
268 assemble_integer (addr, size, BITS_PER_UNIT, 1);
269 #endif
270
271 if (flag_debug_asm && comment)
272 {
273 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
274 vfprintf (asm_out_file, comment, ap);
275 }
276 fputc ('\n', asm_out_file);
277
278 VA_CLOSE (ap);
279 }
280
281 void
282 dw2_asm_output_nstring VPARAMS ((const char *str, size_t orig_len,
283 const char *comment, ...))
284 {
285 size_t i, len;
286
287 VA_OPEN (ap, comment);
288 VA_FIXEDARG (ap, const char *, str);
289 VA_FIXEDARG (ap, size_t, orig_len);
290 VA_FIXEDARG (ap, const char *, comment);
291
292 len = orig_len;
293
294 if (len == (size_t) -1)
295 len = strlen (str);
296
297 if (flag_debug_asm && comment)
298 {
299 fputs ("\t.ascii \"", asm_out_file);
300 for (i = 0; i < len; i++)
301 {
302 int c = str[i];
303 if (c == '\"' || c == '\\')
304 fputc ('\\', asm_out_file);
305 if (ISPRINT(c))
306 fputc (c, asm_out_file);
307 else
308 fprintf (asm_out_file, "\\%o", c);
309 }
310 fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
311 vfprintf (asm_out_file, comment, ap);
312 fputc ('\n', asm_out_file);
313 }
314 else
315 {
316 /* If an explicit length was given, we can't assume there
317 is a null termination in the string buffer. */
318 if (orig_len == (size_t) -1)
319 len += 1;
320 ASM_OUTPUT_ASCII (asm_out_file, str, len);
321 if (orig_len != (size_t) -1)
322 fprintf (asm_out_file, "%s0\n", ASM_BYTE_OP);
323 }
324
325 VA_CLOSE (ap);
326 }
327 \f
328
329 /* Return the size of an unsigned LEB128 quantity. */
330
331 int
332 size_of_uleb128 (value)
333 unsigned HOST_WIDE_INT value;
334 {
335 int size = 0, byte;
336
337 do
338 {
339 byte = (value & 0x7f);
340 value >>= 7;
341 size += 1;
342 }
343 while (value != 0);
344
345 return size;
346 }
347
348 /* Return the size of a signed LEB128 quantity. */
349
350 int
351 size_of_sleb128 (value)
352 HOST_WIDE_INT value;
353 {
354 int size = 0, byte;
355
356 do
357 {
358 byte = (value & 0x7f);
359 value >>= 7;
360 size += 1;
361 }
362 while (!((value == 0 && (byte & 0x40) == 0)
363 || (value == -1 && (byte & 0x40) != 0)));
364
365 return size;
366 }
367
368 /* Given an encoding, return the number of bytes the format occupies.
369 This is only defined for fixed-size encodings, and so does not
370 include leb128. */
371
372 int
373 size_of_encoded_value (encoding)
374 int encoding;
375 {
376 if (encoding == DW_EH_PE_omit)
377 return 0;
378
379 switch (encoding & 0x07)
380 {
381 case DW_EH_PE_absptr:
382 return POINTER_SIZE / BITS_PER_UNIT;
383 case DW_EH_PE_udata2:
384 return 2;
385 case DW_EH_PE_udata4:
386 return 4;
387 case DW_EH_PE_udata8:
388 return 8;
389 }
390 abort ();
391 }
392
393 /* Yield a name for a given pointer encoding. */
394
395 const char *
396 eh_data_format_name (format)
397 int format;
398 {
399 #if HAVE_DESIGNATED_INITIALIZERS
400 #define S(p, v) [p] = v,
401 #else
402 #define S(p, v) case p: return v;
403 #endif
404
405 #if HAVE_DESIGNATED_INITIALIZERS
406 __extension__ static const char * const format_names[256] = {
407 #else
408 switch (format) {
409 #endif
410
411 S(DW_EH_PE_absptr, "absolute")
412 S(DW_EH_PE_omit, "omit")
413 S(DW_EH_PE_aligned, "aligned absolute")
414
415 S(DW_EH_PE_uleb128, "uleb128")
416 S(DW_EH_PE_udata2, "udata2")
417 S(DW_EH_PE_udata4, "udata4")
418 S(DW_EH_PE_udata8, "udata8")
419 S(DW_EH_PE_sleb128, "sleb128")
420 S(DW_EH_PE_sdata2, "sdata2")
421 S(DW_EH_PE_sdata4, "sdata4")
422 S(DW_EH_PE_sdata8, "sdata8")
423
424 S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
425 S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
426 S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
427 S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
428 S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
429 S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
430 S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
431 S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
432 S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
433
434 S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
435 S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
436 S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
437 S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
438 S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
439 S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
440 S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
441 S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
442 S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
443
444 S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
445 S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
446 S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
447 S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
448 S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
449 S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
450 S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
451 S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
452 S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
453
454 S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
455 S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
456 S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
457 S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
458 S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
459 S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
460 S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
461 S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
462 S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
463
464 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
465 "indirect pcrel")
466 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
467 "indirect pcrel uleb128")
468 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
469 "indirect pcrel udata2")
470 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
471 "indirect pcrel udata4")
472 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
473 "indirect pcrel udata8")
474 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
475 "indirect pcrel sleb128")
476 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
477 "indirect pcrel sdata2")
478 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
479 "indirect pcrel sdata4")
480 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
481 "indirect pcrel sdata8")
482
483 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
484 "indirect textrel")
485 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
486 "indirect textrel uleb128")
487 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
488 "indirect textrel udata2")
489 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
490 "indirect textrel udata4")
491 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
492 "indirect textrel udata8")
493 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
494 "indirect textrel sleb128")
495 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
496 "indirect textrel sdata2")
497 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
498 "indirect textrel sdata4")
499 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
500 "indirect textrel sdata8")
501
502 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
503 "indirect datarel")
504 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
505 "indirect datarel uleb128")
506 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
507 "indirect datarel udata2")
508 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
509 "indirect datarel udata4")
510 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
511 "indirect datarel udata8")
512 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
513 "indirect datarel sleb128")
514 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
515 "indirect datarel sdata2")
516 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
517 "indirect datarel sdata4")
518 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
519 "indirect datarel sdata8")
520
521 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
522 "indirect funcrel")
523 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
524 "indirect funcrel uleb128")
525 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
526 "indirect funcrel udata2")
527 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
528 "indirect funcrel udata4")
529 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
530 "indirect funcrel udata8")
531 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
532 "indirect funcrel sleb128")
533 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
534 "indirect funcrel sdata2")
535 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
536 "indirect funcrel sdata4")
537 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
538 "indirect funcrel sdata8")
539
540 #if HAVE_DESIGNATED_INITIALIZERS
541 };
542
543 if (format < 0 || format > 0xff || format_names[format] == NULL)
544 abort ();
545 return format_names[format];
546 #else
547 }
548 abort ();
549 #endif
550 }
551
552 /* Output an unsigned LEB128 quantity. */
553
554 void
555 dw2_asm_output_data_uleb128 VPARAMS ((unsigned HOST_WIDE_INT value,
556 const char *comment, ...))
557 {
558 VA_OPEN (ap, comment);
559 VA_FIXEDARG (ap, unsigned HOST_WIDE_INT, value);
560 VA_FIXEDARG (ap, const char *, comment);
561
562 #ifdef HAVE_AS_LEB128
563 fputs ("\t.uleb128 ", asm_out_file);
564 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
565
566 if (flag_debug_asm && comment)
567 {
568 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
569 vfprintf (asm_out_file, comment, ap);
570 }
571 #else
572 {
573 unsigned HOST_WIDE_INT work = value;
574
575 fputs (ASM_BYTE_OP, asm_out_file);
576 do
577 {
578 int byte = (work & 0x7f);
579 work >>= 7;
580 if (work != 0)
581 /* More bytes to follow. */
582 byte |= 0x80;
583
584 fprintf (asm_out_file, "0x%x", byte);
585 if (work != 0)
586 fputc (',', asm_out_file);
587 }
588 while (work != 0);
589
590 if (flag_debug_asm)
591 {
592 fprintf (asm_out_file, "\t%s uleb128 ", ASM_COMMENT_START);
593 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_HEX, value);
594 if (comment)
595 {
596 fputs ("; ", asm_out_file);
597 vfprintf (asm_out_file, comment, ap);
598 }
599 }
600 }
601 #endif
602 fputc ('\n', asm_out_file);
603
604 VA_CLOSE (ap);
605 }
606
607 /* Output an signed LEB128 quantity. */
608
609 void
610 dw2_asm_output_data_sleb128 VPARAMS ((HOST_WIDE_INT value,
611 const char *comment, ...))
612 {
613 VA_OPEN (ap, comment);
614 VA_FIXEDARG (ap, HOST_WIDE_INT, value);
615 VA_FIXEDARG (ap, const char *, comment);
616
617 #ifdef HAVE_AS_LEB128
618 fputs ("\t.sleb128 ", asm_out_file);
619 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
620
621 if (flag_debug_asm && comment)
622 {
623 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
624 vfprintf (asm_out_file, comment, ap);
625 }
626 #else
627 {
628 HOST_WIDE_INT work = value;
629 int more, byte;
630
631 fputs (ASM_BYTE_OP, asm_out_file);
632 do
633 {
634 byte = (work & 0x7f);
635 /* arithmetic shift */
636 work >>= 7;
637 more = !((work == 0 && (byte & 0x40) == 0)
638 || (work == -1 && (byte & 0x40) != 0));
639 if (more)
640 byte |= 0x80;
641
642 fprintf (asm_out_file, "0x%x", byte);
643 if (more)
644 fputc (',', asm_out_file);
645 }
646 while (more);
647
648 if (flag_debug_asm)
649 {
650 fprintf (asm_out_file, "\t%s sleb128 ", ASM_COMMENT_START);
651 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, value);
652 if (comment)
653 {
654 fputs ("; ", asm_out_file);
655 vfprintf (asm_out_file, comment, ap);
656 }
657 }
658 }
659 #endif
660 fputc ('\n', asm_out_file);
661
662 VA_CLOSE (ap);
663 }
664
665 void
666 dw2_asm_output_delta_uleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
667 const char *lab2 ATTRIBUTE_UNUSED,
668 const char *comment, ...))
669 {
670 VA_OPEN (ap, comment);
671 VA_FIXEDARG (ap, const char *, lab1);
672 VA_FIXEDARG (ap, const char *, lab2);
673 VA_FIXEDARG (ap, const char *, comment);
674
675 #ifdef HAVE_AS_LEB128
676 fputs ("\t.uleb128 ", asm_out_file);
677 assemble_name (asm_out_file, lab1);
678 fputc ('-', asm_out_file);
679 assemble_name (asm_out_file, lab2);
680 #else
681 abort ();
682 #endif
683
684 if (flag_debug_asm && comment)
685 {
686 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
687 vfprintf (asm_out_file, comment, ap);
688 }
689 fputc ('\n', asm_out_file);
690
691 VA_CLOSE (ap);
692 }
693
694 void
695 dw2_asm_output_delta_sleb128 VPARAMS ((const char *lab1 ATTRIBUTE_UNUSED,
696 const char *lab2 ATTRIBUTE_UNUSED,
697 const char *comment, ...))
698 {
699 VA_OPEN (ap, comment);
700 VA_FIXEDARG (ap, const char *, lab1);
701 VA_FIXEDARG (ap, const char *, lab2);
702 VA_FIXEDARG (ap, const char *, comment);
703
704 #ifdef HAVE_AS_LEB128
705 fputs ("\t.sleb128 ", asm_out_file);
706 assemble_name (asm_out_file, lab1);
707 fputc ('-', asm_out_file);
708 assemble_name (asm_out_file, lab2);
709 #else
710 abort ();
711 #endif
712
713 if (flag_debug_asm && comment)
714 {
715 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
716 vfprintf (asm_out_file, comment, ap);
717 }
718 fputc ('\n', asm_out_file);
719
720 VA_CLOSE (ap);
721 }
722 \f
723 static int mark_indirect_pool_entry PARAMS ((splay_tree_node, void *));
724 static void mark_indirect_pool PARAMS ((PTR arg));
725 static rtx dw2_force_const_mem PARAMS ((rtx));
726 static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
727
728 static splay_tree indirect_pool;
729
730 #if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
731 # define USE_LINKONCE_INDIRECT 1
732 #else
733 # define USE_LINKONCE_INDIRECT 0
734 #endif
735
736 /* Mark all indirect constants for GC. */
737
738 static int
739 mark_indirect_pool_entry (node, data)
740 splay_tree_node node;
741 void* data ATTRIBUTE_UNUSED;
742 {
743 ggc_mark_nonnull_tree ((tree) node->value);
744 return 0;
745 }
746
747 /* Mark all indirect constants for GC. */
748
749 static void
750 mark_indirect_pool (arg)
751 PTR arg ATTRIBUTE_UNUSED;
752 {
753 splay_tree_foreach (indirect_pool, mark_indirect_pool_entry, NULL);
754 }
755
756 /* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
757 memory. Differs from force_const_mem in that a single pool is used for
758 the entire unit of translation, and the memory is not guaranteed to be
759 "near" the function in any interesting sense. */
760
761 static rtx
762 dw2_force_const_mem (x)
763 rtx x;
764 {
765 splay_tree_node node;
766 const char *str;
767 tree decl;
768
769 if (! indirect_pool)
770 {
771 indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
772 ggc_add_root (&indirect_pool, 1, sizeof indirect_pool, mark_indirect_pool);
773 }
774
775 if (GET_CODE (x) != SYMBOL_REF)
776 abort ();
777
778 STRIP_NAME_ENCODING (str, XSTR (x, 0));
779 node = splay_tree_lookup (indirect_pool, (splay_tree_key) str);
780 if (node)
781 decl = (tree) node->value;
782 else
783 {
784 tree id;
785
786 if (USE_LINKONCE_INDIRECT)
787 {
788 char *ref_name = alloca (strlen (str) + sizeof "DW.ref.");
789
790 sprintf (ref_name, "DW.ref.%s", str);
791 id = get_identifier (ref_name);
792 decl = build_decl (VAR_DECL, id, ptr_type_node);
793 DECL_ARTIFICIAL (decl) = 1;
794 TREE_PUBLIC (decl) = 1;
795 DECL_INITIAL (decl) = decl;
796 make_decl_one_only (decl);
797 }
798 else
799 {
800 extern int const_labelno;
801 char label[32];
802
803 ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
804 ++const_labelno;
805 id = get_identifier (label);
806 decl = build_decl (VAR_DECL, id, ptr_type_node);
807 DECL_ARTIFICIAL (decl) = 1;
808 TREE_STATIC (decl) = 1;
809 DECL_INITIAL (decl) = decl;
810 }
811
812 id = maybe_get_identifier (str);
813 if (id)
814 TREE_SYMBOL_REFERENCED (id) = 1;
815
816 splay_tree_insert (indirect_pool, (splay_tree_key) str,
817 (splay_tree_value) decl);
818 }
819
820 return XEXP (DECL_RTL (decl), 0);
821 }
822
823 /* A helper function for dw2_output_indirect_constants called through
824 splay_tree_foreach. Emit one queued constant to memory. */
825
826 static int
827 dw2_output_indirect_constant_1 (node, data)
828 splay_tree_node node;
829 void* data ATTRIBUTE_UNUSED;
830 {
831 const char *sym;
832 rtx sym_ref;
833
834 sym = (const char *) node->key;
835 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
836 if (USE_LINKONCE_INDIRECT)
837 fprintf (asm_out_file, "\t.hidden DW.ref.%s\n", sym);
838 assemble_variable ((tree) node->value, 1, 1, 1);
839 assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
840
841 return 0;
842 }
843
844 /* Emit the constants queued through dw2_force_const_mem. */
845
846 void
847 dw2_output_indirect_constants ()
848 {
849 if (indirect_pool)
850 splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
851 }
852
853 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed. */
854
855 void
856 dw2_asm_output_encoded_addr_rtx VPARAMS ((int encoding,
857 rtx addr,
858 const char *comment, ...))
859 {
860 int size;
861
862 VA_OPEN (ap, comment);
863 VA_FIXEDARG (ap, int, encoding);
864 VA_FIXEDARG (ap, rtx, addr);
865 VA_FIXEDARG (ap, const char *, comment);
866
867 size = size_of_encoded_value (encoding);
868
869 if (encoding == DW_EH_PE_aligned)
870 {
871 assemble_align (POINTER_SIZE);
872 assemble_integer (addr, size, POINTER_SIZE, 1);
873 return;
874 }
875
876 /* NULL is _always_ represented as a plain zero. */
877 if (addr == const0_rtx)
878 assemble_integer (addr, size, BITS_PER_UNIT, 1);
879 else
880 {
881 restart:
882 /* Allow the target first crack at emitting this. Some of the
883 special relocations require special directives instead of
884 just ".4byte" or whatever. */
885 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
886 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
887 addr, done);
888 #endif
889
890 /* Indirection is used to get dynamic relocations out of a
891 read-only section. */
892 if (encoding & DW_EH_PE_indirect)
893 {
894 /* It is very tempting to use force_const_mem so that we share data
895 with the normal constant pool. However, we've already emitted
896 the constant pool for this function. Moreover, we'd like to
897 share these constants across the entire unit of translation,
898 or better, across the entire application (or DSO). */
899 addr = dw2_force_const_mem (addr);
900 encoding &= ~DW_EH_PE_indirect;
901 goto restart;
902 }
903
904 switch (encoding & 0xF0)
905 {
906 case DW_EH_PE_absptr:
907 #ifdef UNALIGNED_INT_ASM_OP
908 fputs (unaligned_integer_asm_op (size), asm_out_file);
909 output_addr_const (asm_out_file, addr);
910 #else
911 assemble_integer (addr, size, BITS_PER_UNIT, 1);
912 #endif
913 break;
914
915 case DW_EH_PE_pcrel:
916 if (GET_CODE (addr) != SYMBOL_REF)
917 abort ();
918 #ifdef ASM_OUTPUT_DWARF_PCREL
919 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
920 #else
921 #ifdef UNALIGNED_INT_ASM_OP
922 fputs (unaligned_integer_asm_op (size), asm_out_file);
923 assemble_name (asm_out_file, XSTR (addr, 0));
924 fputc ('-', asm_out_file);
925 fputc ('.', asm_out_file);
926 #else
927 abort ();
928 #endif
929 #endif
930 break;
931
932 default:
933 /* Other encodings should have been handled by
934 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
935 abort ();
936 }
937
938 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
939 done:;
940 #endif
941 }
942
943 if (flag_debug_asm && comment)
944 {
945 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
946 vfprintf (asm_out_file, comment, ap);
947 }
948 fputc ('\n', asm_out_file);
949
950 VA_CLOSE (ap);
951 }