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