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