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