xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/dwarf2asm.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* Dwarf2 assembler output helper routines.
2    Copyright (C) 2001-2015 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 3, 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 COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "flags.h"
26 #include "hash-set.h"
27 #include "machmode.h"
28 #include "vec.h"
29 #include "double-int.h"
30 #include "input.h"
31 #include "alias.h"
32 #include "symtab.h"
33 #include "wide-int.h"
34 #include "inchash.h"
35 #include "real.h"
36 #include "tree.h"
37 #include "stringpool.h"
38 #include "varasm.h"
39 #include "rtl.h"
40 #include "output.h"
41 #include "target.h"
42 #include "dwarf2asm.h"
43 #include "dwarf2.h"
44 #include "hash-map.h"
45 #include "ggc.h"
46 #include "tm_p.h"
47 
48 
49 /* Output an unaligned integer with the given value and size.  Prefer not
50    to print a newline, since the caller may want to add a comment.  */
51 
52 void
53 dw2_assemble_integer (int size, rtx x)
54 {
55   const char *op = integer_asm_op (size, FALSE);
56 
57   if (op)
58     {
59       fputs (op, asm_out_file);
60       if (CONST_INT_P (x))
61 	fprint_whex (asm_out_file, (unsigned HOST_WIDE_INT) INTVAL (x));
62       else
63 	output_addr_const (asm_out_file, x);
64     }
65   else
66     assemble_integer (x, size, BITS_PER_UNIT, 1);
67 }
68 
69 
70 /* Output a value of a given size in target byte order.  */
71 
72 void
73 dw2_asm_output_data_raw (int size, unsigned HOST_WIDE_INT value)
74 {
75   unsigned char bytes[8];
76   int i;
77 
78   for (i = 0; i < 8; ++i)
79     {
80       bytes[i] = value & 0xff;
81       value >>= 8;
82     }
83 
84   if (BYTES_BIG_ENDIAN)
85     {
86       for (i = size - 1; i > 0; --i)
87 	fprintf (asm_out_file, "%#x,", bytes[i]);
88       fprintf (asm_out_file, "%#x", bytes[0]);
89     }
90   else
91     {
92       for (i = 0; i < size - 1; ++i)
93 	fprintf (asm_out_file, "%#x,", bytes[i]);
94       fprintf (asm_out_file, "%#x", bytes[i]);
95     }
96 }
97 
98 /* Output an immediate constant in a given SIZE in bytes.  */
99 
100 void
101 dw2_asm_output_data (int size, unsigned HOST_WIDE_INT value,
102 		     const char *comment, ...)
103 {
104   va_list ap;
105   const char *op = integer_asm_op (size, FALSE);
106 
107   va_start (ap, comment);
108 
109   if (size * 8 < HOST_BITS_PER_WIDE_INT)
110     value &= ~(~(unsigned HOST_WIDE_INT) 0 << (size * 8));
111 
112   if (op)
113     {
114       fputs (op, asm_out_file);
115       fprint_whex (asm_out_file, value);
116     }
117   else
118     assemble_integer (GEN_INT (value), size, BITS_PER_UNIT, 1);
119 
120   if (flag_debug_asm && comment)
121     {
122       fputs ("\t" ASM_COMMENT_START " ", asm_out_file);
123       vfprintf (asm_out_file, comment, ap);
124     }
125   putc ('\n', asm_out_file);
126 
127   va_end (ap);
128 }
129 
130 /* Output the difference between two symbols in a given size.  */
131 /* ??? There appear to be assemblers that do not like such
132    subtraction, but do support ASM_SET_OP.  It's unfortunately
133    impossible to do here, since the ASM_SET_OP for the difference
134    symbol must appear after both symbols are defined.  */
135 
136 void
137 dw2_asm_output_delta (int size, const char *lab1, const char *lab2,
138 		      const char *comment, ...)
139 {
140   va_list ap;
141 
142   va_start (ap, comment);
143 
144 #ifdef ASM_OUTPUT_DWARF_DELTA
145   ASM_OUTPUT_DWARF_DELTA (asm_out_file, size, lab1, lab2);
146 #else
147   dw2_assemble_integer (size,
148 			gen_rtx_MINUS (Pmode,
149 				       gen_rtx_SYMBOL_REF (Pmode, lab1),
150 				       gen_rtx_SYMBOL_REF (Pmode, lab2)));
151 #endif
152   if (flag_debug_asm && comment)
153     {
154       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
155       vfprintf (asm_out_file, comment, ap);
156     }
157   fputc ('\n', asm_out_file);
158 
159   va_end (ap);
160 }
161 
162 #ifdef ASM_OUTPUT_DWARF_VMS_DELTA
163 /* Output the difference between two symbols in instruction units
164    in a given size.  */
165 
166 void
167 dw2_asm_output_vms_delta (int size ATTRIBUTE_UNUSED,
168 			  const char *lab1, const char *lab2,
169 			  const char *comment, ...)
170 {
171   va_list ap;
172 
173   va_start (ap, comment);
174 
175   ASM_OUTPUT_DWARF_VMS_DELTA (asm_out_file, size, lab1, lab2);
176   if (flag_debug_asm && comment)
177     {
178       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
179       vfprintf (asm_out_file, comment, ap);
180     }
181   fputc ('\n', asm_out_file);
182 
183   va_end (ap);
184 }
185 #endif
186 
187 /* Output a section-relative reference to a LABEL, which was placed in
188    BASE.  In general this can only be done for debugging symbols.
189    E.g. on most targets with the GNU linker, this is accomplished with
190    a direct reference and the knowledge that the debugging section
191    will be placed at VMA 0.  Some targets have special relocations for
192    this that we must use.  */
193 
194 void
195 dw2_asm_output_offset (int size, const char *label,
196 		       section *base ATTRIBUTE_UNUSED,
197 		       const char *comment, ...)
198 {
199   va_list ap;
200 
201   va_start (ap, comment);
202 
203 #ifdef ASM_OUTPUT_DWARF_OFFSET
204   ASM_OUTPUT_DWARF_OFFSET (asm_out_file, size, label, base);
205 #else
206   dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
207 #endif
208 
209   if (flag_debug_asm && comment)
210     {
211       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
212       vfprintf (asm_out_file, comment, ap);
213     }
214   fputc ('\n', asm_out_file);
215 
216   va_end (ap);
217 }
218 
219 #if 0
220 
221 /* Output a self-relative reference to a label, possibly in a
222    different section or object file.  */
223 
224 void
225 dw2_asm_output_pcrel (int size ATTRIBUTE_UNUSED,
226 		      const char *label ATTRIBUTE_UNUSED,
227 		      const char *comment, ...)
228 {
229   va_list ap;
230 
231   va_start (ap, comment);
232 
233 #ifdef ASM_OUTPUT_DWARF_PCREL
234   ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, label);
235 #else
236   dw2_assemble_integer (size,
237 			gen_rtx_MINUS (Pmode,
238 				       gen_rtx_SYMBOL_REF (Pmode, label),
239 				       pc_rtx));
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_end (ap);
250 }
251 #endif /* 0 */
252 
253 /* Output an absolute reference to a label.  */
254 
255 void
256 dw2_asm_output_addr (int size, const char *label,
257 		     const char *comment, ...)
258 {
259   va_list ap;
260 
261   va_start (ap, comment);
262 
263   dw2_assemble_integer (size, gen_rtx_SYMBOL_REF (Pmode, label));
264 
265   if (flag_debug_asm && comment)
266     {
267       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
268       vfprintf (asm_out_file, comment, ap);
269     }
270   fputc ('\n', asm_out_file);
271 
272   va_end (ap);
273 }
274 
275 /* Similar, but use an RTX expression instead of a text label.  */
276 
277 void
278 dw2_asm_output_addr_rtx (int size, rtx addr,
279 			 const char *comment, ...)
280 {
281   va_list ap;
282 
283   va_start (ap, comment);
284 
285   dw2_assemble_integer (size, addr);
286 
287   if (flag_debug_asm && comment)
288     {
289       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
290       vfprintf (asm_out_file, comment, ap);
291     }
292   fputc ('\n', asm_out_file);
293 
294   va_end (ap);
295 }
296 
297 /* Output the first ORIG_LEN characters of STR as a string.
298    If ORIG_LEN is equal to -1, ignore this parameter and output
299    the entire STR instead.
300    If COMMENT is not NULL and comments in the debug information
301    have been requested by the user, append the given COMMENT
302    to the generated output.  */
303 
304 void
305 dw2_asm_output_nstring (const char *str, size_t orig_len,
306 			const char *comment, ...)
307 {
308   size_t i, len;
309   va_list ap;
310 
311   va_start (ap, comment);
312 
313   len = orig_len;
314 
315   if (len == (size_t) -1)
316     len = strlen (str);
317 
318   if (flag_debug_asm && comment)
319     {
320       fputs ("\t.ascii \"", asm_out_file);
321       for (i = 0; i < len; i++)
322 	{
323 	  int c = str[i];
324 	  if (c == '\"' || c == '\\')
325 	    fputc ('\\', asm_out_file);
326 	  if (ISPRINT (c))
327 	    fputc (c, asm_out_file);
328 	  else
329 	    fprintf (asm_out_file, "\\%o", c);
330 	}
331       fprintf (asm_out_file, "\\0\"\t%s ", ASM_COMMENT_START);
332       vfprintf (asm_out_file, comment, ap);
333       fputc ('\n', asm_out_file);
334     }
335   else
336     {
337       /* If an explicit length was given, we can't assume there
338 	 is a null termination in the string buffer.  */
339       if (orig_len == (size_t) -1)
340 	len += 1;
341       ASM_OUTPUT_ASCII (asm_out_file, str, len);
342       if (orig_len != (size_t) -1)
343 	assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
344     }
345 
346   va_end (ap);
347 }
348 
349 
350 /* Return the size of an unsigned LEB128 quantity.  */
351 
352 int
353 size_of_uleb128 (unsigned HOST_WIDE_INT value)
354 {
355   int size = 0;
356 
357   do
358     {
359       value >>= 7;
360       size += 1;
361     }
362   while (value != 0);
363 
364   return size;
365 }
366 
367 /* Return the size of a signed LEB128 quantity.  */
368 
369 int
370 size_of_sleb128 (HOST_WIDE_INT value)
371 {
372   int size = 0, byte;
373 
374   do
375     {
376       byte = (value & 0x7f);
377       value >>= 7;
378       size += 1;
379     }
380   while (!((value == 0 && (byte & 0x40) == 0)
381 	   || (value == -1 && (byte & 0x40) != 0)));
382 
383   return size;
384 }
385 
386 /* Given an encoding, return the number of bytes the format occupies.
387    This is only defined for fixed-size encodings, and so does not
388    include leb128.  */
389 
390 int
391 size_of_encoded_value (int encoding)
392 {
393   if (encoding == DW_EH_PE_omit)
394     return 0;
395 
396   switch (encoding & 0x07)
397     {
398     case DW_EH_PE_absptr:
399       return POINTER_SIZE_UNITS;
400     case DW_EH_PE_udata2:
401       return 2;
402     case DW_EH_PE_udata4:
403       return 4;
404     case DW_EH_PE_udata8:
405       return 8;
406     default:
407       gcc_unreachable ();
408     }
409 }
410 
411 /* Yield a name for a given pointer encoding.  */
412 
413 const char *
414 eh_data_format_name (int format)
415 {
416 #if HAVE_DESIGNATED_INITIALIZERS
417 #define S(p, v)		[p] = v,
418 #else
419 #define S(p, v)		case p: return v;
420 #endif
421 
422 #if HAVE_DESIGNATED_INITIALIZERS
423   __extension__ static const char * const format_names[256] = {
424 #else
425   switch (format) {
426 #endif
427 
428   S(DW_EH_PE_absptr, "absolute")
429   S(DW_EH_PE_omit, "omit")
430   S(DW_EH_PE_aligned, "aligned absolute")
431 
432   S(DW_EH_PE_uleb128, "uleb128")
433   S(DW_EH_PE_udata2, "udata2")
434   S(DW_EH_PE_udata4, "udata4")
435   S(DW_EH_PE_udata8, "udata8")
436   S(DW_EH_PE_sleb128, "sleb128")
437   S(DW_EH_PE_sdata2, "sdata2")
438   S(DW_EH_PE_sdata4, "sdata4")
439   S(DW_EH_PE_sdata8, "sdata8")
440 
441   S(DW_EH_PE_absptr | DW_EH_PE_pcrel, "pcrel")
442   S(DW_EH_PE_uleb128 | DW_EH_PE_pcrel, "pcrel uleb128")
443   S(DW_EH_PE_udata2 | DW_EH_PE_pcrel, "pcrel udata2")
444   S(DW_EH_PE_udata4 | DW_EH_PE_pcrel, "pcrel udata4")
445   S(DW_EH_PE_udata8 | DW_EH_PE_pcrel, "pcrel udata8")
446   S(DW_EH_PE_sleb128 | DW_EH_PE_pcrel, "pcrel sleb128")
447   S(DW_EH_PE_sdata2 | DW_EH_PE_pcrel, "pcrel sdata2")
448   S(DW_EH_PE_sdata4 | DW_EH_PE_pcrel, "pcrel sdata4")
449   S(DW_EH_PE_sdata8 | DW_EH_PE_pcrel, "pcrel sdata8")
450 
451   S(DW_EH_PE_absptr | DW_EH_PE_textrel, "textrel")
452   S(DW_EH_PE_uleb128 | DW_EH_PE_textrel, "textrel uleb128")
453   S(DW_EH_PE_udata2 | DW_EH_PE_textrel, "textrel udata2")
454   S(DW_EH_PE_udata4 | DW_EH_PE_textrel, "textrel udata4")
455   S(DW_EH_PE_udata8 | DW_EH_PE_textrel, "textrel udata8")
456   S(DW_EH_PE_sleb128 | DW_EH_PE_textrel, "textrel sleb128")
457   S(DW_EH_PE_sdata2 | DW_EH_PE_textrel, "textrel sdata2")
458   S(DW_EH_PE_sdata4 | DW_EH_PE_textrel, "textrel sdata4")
459   S(DW_EH_PE_sdata8 | DW_EH_PE_textrel, "textrel sdata8")
460 
461   S(DW_EH_PE_absptr | DW_EH_PE_datarel, "datarel")
462   S(DW_EH_PE_uleb128 | DW_EH_PE_datarel, "datarel uleb128")
463   S(DW_EH_PE_udata2 | DW_EH_PE_datarel, "datarel udata2")
464   S(DW_EH_PE_udata4 | DW_EH_PE_datarel, "datarel udata4")
465   S(DW_EH_PE_udata8 | DW_EH_PE_datarel, "datarel udata8")
466   S(DW_EH_PE_sleb128 | DW_EH_PE_datarel, "datarel sleb128")
467   S(DW_EH_PE_sdata2 | DW_EH_PE_datarel, "datarel sdata2")
468   S(DW_EH_PE_sdata4 | DW_EH_PE_datarel, "datarel sdata4")
469   S(DW_EH_PE_sdata8 | DW_EH_PE_datarel, "datarel sdata8")
470 
471   S(DW_EH_PE_absptr | DW_EH_PE_funcrel, "funcrel")
472   S(DW_EH_PE_uleb128 | DW_EH_PE_funcrel, "funcrel uleb128")
473   S(DW_EH_PE_udata2 | DW_EH_PE_funcrel, "funcrel udata2")
474   S(DW_EH_PE_udata4 | DW_EH_PE_funcrel, "funcrel udata4")
475   S(DW_EH_PE_udata8 | DW_EH_PE_funcrel, "funcrel udata8")
476   S(DW_EH_PE_sleb128 | DW_EH_PE_funcrel, "funcrel sleb128")
477   S(DW_EH_PE_sdata2 | DW_EH_PE_funcrel, "funcrel sdata2")
478   S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
479   S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
480 
481   S(DW_EH_PE_indirect | DW_EH_PE_absptr, "indirect absolute")
482 
483   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
484     "indirect pcrel")
485   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
486     "indirect pcrel uleb128")
487   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
488     "indirect pcrel udata2")
489   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
490     "indirect pcrel udata4")
491   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
492     "indirect pcrel udata8")
493   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
494     "indirect pcrel sleb128")
495   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
496     "indirect pcrel sdata2")
497   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
498     "indirect pcrel sdata4")
499   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
500     "indirect pcrel sdata8")
501 
502   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
503     "indirect textrel")
504   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
505     "indirect textrel uleb128")
506   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
507     "indirect textrel udata2")
508   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
509     "indirect textrel udata4")
510   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
511     "indirect textrel udata8")
512   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
513     "indirect textrel sleb128")
514   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
515     "indirect textrel sdata2")
516   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
517     "indirect textrel sdata4")
518   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
519     "indirect textrel sdata8")
520 
521   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
522     "indirect datarel")
523   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
524     "indirect datarel uleb128")
525   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
526     "indirect datarel udata2")
527   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
528     "indirect datarel udata4")
529   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
530     "indirect datarel udata8")
531   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
532     "indirect datarel sleb128")
533   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
534     "indirect datarel sdata2")
535   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
536     "indirect datarel sdata4")
537   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
538     "indirect datarel sdata8")
539 
540   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
541     "indirect funcrel")
542   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
543     "indirect funcrel uleb128")
544   S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
545     "indirect funcrel udata2")
546   S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
547     "indirect funcrel udata4")
548   S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
549     "indirect funcrel udata8")
550   S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
551     "indirect funcrel sleb128")
552   S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
553     "indirect funcrel sdata2")
554   S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
555     "indirect funcrel sdata4")
556   S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
557     "indirect funcrel sdata8")
558 
559 #if HAVE_DESIGNATED_INITIALIZERS
560   };
561 
562   gcc_assert (format >= 0 && format < 0x100 && format_names[format]);
563 
564   return format_names[format];
565 #else
566   }
567   gcc_unreachable ();
568 #endif
569 }
570 
571 /* Output an unsigned LEB128 quantity, but only the byte values.  */
572 
573 void
574 dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value)
575 {
576   while (1)
577     {
578       int byte = (value & 0x7f);
579       value >>= 7;
580       if (value != 0)
581 	/* More bytes to follow.  */
582 	byte |= 0x80;
583 
584       fprintf (asm_out_file, "%#x", byte);
585       if (value == 0)
586 	break;
587       fputc (',', asm_out_file);
588     }
589 }
590 
591 /* Output an unsigned LEB128 quantity.  */
592 
593 void
594 dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
595 			     const char *comment, ...)
596 {
597   va_list ap;
598 
599   va_start (ap, comment);
600 
601 #ifdef HAVE_AS_LEB128
602   fputs ("\t.uleb128 ", asm_out_file);
603   fprint_whex (asm_out_file, value);
604 
605   if (flag_debug_asm && comment)
606     {
607       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
608       vfprintf (asm_out_file, comment, ap);
609     }
610 #else
611   {
612     unsigned HOST_WIDE_INT work = value;
613     const char *byte_op = targetm.asm_out.byte_op;
614 
615     if (byte_op)
616       fputs (byte_op, asm_out_file);
617     do
618       {
619 	int byte = (work & 0x7f);
620 	work >>= 7;
621 	if (work != 0)
622 	  /* More bytes to follow.  */
623 	  byte |= 0x80;
624 
625 	if (byte_op)
626 	  {
627 	    fprintf (asm_out_file, "%#x", byte);
628 	    if (work != 0)
629 	      fputc (',', asm_out_file);
630 	  }
631 	else
632 	  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
633       }
634     while (work != 0);
635 
636   if (flag_debug_asm)
637     {
638       fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
639 	       ASM_COMMENT_START, value);
640       if (comment)
641 	{
642 	  fputs ("; ", asm_out_file);
643 	  vfprintf (asm_out_file, comment, ap);
644 	}
645     }
646   }
647 #endif
648   putc ('\n', asm_out_file);
649 
650   va_end (ap);
651 }
652 
653 /* Output an signed LEB128 quantity, but only the byte values.  */
654 
655 void
656 dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value)
657 {
658   int byte, more;
659 
660   while (1)
661     {
662       byte = (value & 0x7f);
663       value >>= 7;
664       more = !((value == 0 && (byte & 0x40) == 0)
665 		|| (value == -1 && (byte & 0x40) != 0));
666       if (more)
667 	byte |= 0x80;
668 
669       fprintf (asm_out_file, "%#x", byte);
670       if (!more)
671 	break;
672       fputc (',', asm_out_file);
673     }
674 }
675 
676 /* Output a signed LEB128 quantity.  */
677 
678 void
679 dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
680 			     const char *comment, ...)
681 {
682   va_list ap;
683 
684   va_start (ap, comment);
685 
686 #ifdef HAVE_AS_LEB128
687   fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
688 
689   if (flag_debug_asm && comment)
690     {
691       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
692       vfprintf (asm_out_file, comment, ap);
693     }
694 #else
695   {
696     HOST_WIDE_INT work = value;
697     int more, byte;
698     const char *byte_op = targetm.asm_out.byte_op;
699 
700     if (byte_op)
701       fputs (byte_op, asm_out_file);
702     do
703       {
704 	byte = (work & 0x7f);
705 	/* arithmetic shift */
706 	work >>= 7;
707 	more = !((work == 0 && (byte & 0x40) == 0)
708 		 || (work == -1 && (byte & 0x40) != 0));
709 	if (more)
710 	  byte |= 0x80;
711 
712 	if (byte_op)
713 	  {
714 	    fprintf (asm_out_file, "%#x", byte);
715 	    if (more)
716 	      fputc (',', asm_out_file);
717 	  }
718 	else
719 	  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
720       }
721     while (more);
722 
723   if (flag_debug_asm)
724     {
725       fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
726 	       ASM_COMMENT_START, value);
727       if (comment)
728 	{
729 	  fputs ("; ", asm_out_file);
730 	  vfprintf (asm_out_file, comment, ap);
731 	}
732     }
733   }
734 #endif
735   fputc ('\n', asm_out_file);
736 
737   va_end (ap);
738 }
739 
740 void
741 dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
742 			      const char *lab2 ATTRIBUTE_UNUSED,
743 			      const char *comment, ...)
744 {
745   va_list ap;
746 
747   va_start (ap, comment);
748 
749 #ifdef HAVE_AS_LEB128
750   fputs ("\t.uleb128 ", asm_out_file);
751   assemble_name (asm_out_file, lab1);
752   putc ('-', asm_out_file);
753   assemble_name (asm_out_file, lab2);
754 #else
755   gcc_unreachable ();
756 #endif
757 
758   if (flag_debug_asm && comment)
759     {
760       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
761       vfprintf (asm_out_file, comment, ap);
762     }
763   fputc ('\n', asm_out_file);
764 
765   va_end (ap);
766 }
767 
768 #if 0
769 
770 void
771 dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
772 			      const char *lab2 ATTRIBUTE_UNUSED,
773 			      const char *comment, ...)
774 {
775   va_list ap;
776 
777   va_start (ap, comment);
778 
779 #ifdef HAVE_AS_LEB128
780   fputs ("\t.sleb128 ", asm_out_file);
781   assemble_name (asm_out_file, lab1);
782   putc ('-', asm_out_file);
783   assemble_name (asm_out_file, lab2);
784 #else
785   gcc_unreachable ();
786 #endif
787 
788   if (flag_debug_asm && comment)
789     {
790       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
791       vfprintf (asm_out_file, comment, ap);
792     }
793   fputc ('\n', asm_out_file);
794 
795   va_end (ap);
796 }
797 #endif /* 0 */
798 
799 static GTY(()) hash_map<const char *, tree> *indirect_pool;
800 
801 static GTY(()) int dw2_const_labelno;
802 
803 #if defined(HAVE_GAS_HIDDEN)
804 # define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY)
805 #else
806 # define USE_LINKONCE_INDIRECT 0
807 #endif
808 
809 /* Compare two std::pair<const char *, tree> by their first element.
810    Returns <0, 0, or
811    >0 to indicate whether K1 is less than, equal to, or greater than
812    K2, respectively.  */
813 
814 static int
815 compare_strings (const void *a, const void *b)
816 {
817   const char *s1 = ((const std::pair<const char *, tree> *) a)->first;
818   const char *s2 = ((const std::pair<const char *, tree> *) b)->first;
819   int ret;
820 
821   if (s1 == s2)
822     return 0;
823 
824   ret = strcmp (s1, s2);
825 
826   /* The strings are always those from IDENTIFIER_NODEs, and,
827      therefore, we should never have two copies of the same
828      string.  */
829   gcc_assert (ret);
830 
831   return ret;
832 }
833 
834 /* Put X, a SYMBOL_REF, in memory.  Return a SYMBOL_REF to the allocated
835    memory.  Differs from force_const_mem in that a single pool is used for
836    the entire unit of translation, and the memory is not guaranteed to be
837    "near" the function in any interesting sense.  IS_PUBLIC controls whether
838    the symbol can be shared across the entire application (or DSO).  */
839 
840 rtx
841 dw2_force_const_mem (rtx x, bool is_public)
842 {
843   const char *key;
844   tree decl_id;
845 
846   if (! indirect_pool)
847     indirect_pool = hash_map<const char *, tree>::create_ggc (64);
848 
849   gcc_assert (GET_CODE (x) == SYMBOL_REF);
850 
851   key = XSTR (x, 0);
852   tree *slot = indirect_pool->get (key);
853   if (slot)
854     decl_id = *slot;
855   else
856     {
857       tree id;
858       const char *str = targetm.strip_name_encoding (key);
859 
860       if (is_public && USE_LINKONCE_INDIRECT)
861 	{
862 	  char *ref_name = XALLOCAVEC (char, strlen (str) + sizeof "DW.ref.");
863 
864 	  sprintf (ref_name, "DW.ref.%s", str);
865 	  gcc_assert (!maybe_get_identifier (ref_name));
866 	  decl_id = get_identifier (ref_name);
867 	  TREE_PUBLIC (decl_id) = 1;
868 	}
869       else
870 	{
871 	  char label[32];
872 
873 	  ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
874 	  ++dw2_const_labelno;
875 	  gcc_assert (!maybe_get_identifier (label));
876 	  decl_id = get_identifier (label);
877 	}
878 
879       id = maybe_get_identifier (str);
880       if (id)
881 	TREE_SYMBOL_REFERENCED (id) = 1;
882 
883       indirect_pool->put (key, decl_id);
884     }
885 
886   return gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (decl_id));
887 }
888 
889 /* A helper function for dw2_output_indirect_constants.  Emit one queued
890    constant to memory.  */
891 
892 static int
893 dw2_output_indirect_constant_1 (const char *sym, tree id)
894 {
895   rtx sym_ref;
896   tree decl;
897 
898   decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, ptr_type_node);
899   SET_DECL_ASSEMBLER_NAME (decl, id);
900   DECL_ARTIFICIAL (decl) = 1;
901   DECL_IGNORED_P (decl) = 1;
902   DECL_INITIAL (decl) = decl;
903   TREE_READONLY (decl) = 1;
904   TREE_STATIC (decl) = 1;
905 
906   if (TREE_PUBLIC (id))
907     {
908       TREE_PUBLIC (decl) = 1;
909       make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
910       if (USE_LINKONCE_INDIRECT)
911 	DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
912     }
913 
914   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
915   assemble_variable (decl, 1, 1, 1);
916   assemble_integer (sym_ref, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
917 
918   return 0;
919 }
920 
921 /* Emit the constants queued through dw2_force_const_mem.  */
922 
923 void
924 dw2_output_indirect_constants (void)
925 {
926   if (!indirect_pool)
927     return;
928 
929   auto_vec<std::pair<const char *, tree> > temp (indirect_pool->elements ());
930   for (hash_map<const char *, tree>::iterator iter = indirect_pool->begin ();
931        iter != indirect_pool->end (); ++iter)
932     temp.quick_push (*iter);
933 
934     temp.qsort (compare_strings);
935 
936     for (unsigned int i = 0; i < temp.length (); i++)
937     dw2_output_indirect_constant_1 (temp[i].first, temp[i].second);
938 }
939 
940 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
941    If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
942    reference is shared across the entire application (or DSO).  */
943 
944 void
945 dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
946 				 const char *comment, ...)
947 {
948   int size;
949   va_list ap;
950 
951   va_start (ap, comment);
952 
953   size = size_of_encoded_value (encoding);
954 
955   if (encoding == DW_EH_PE_aligned)
956     {
957       assemble_align (POINTER_SIZE);
958       assemble_integer (addr, size, POINTER_SIZE, 1);
959       va_end (ap);
960       return;
961     }
962 
963   /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
964      "all others".  */
965   if (addr == const0_rtx || addr == const1_rtx)
966     assemble_integer (addr, size, BITS_PER_UNIT, 1);
967   else
968     {
969     restart:
970       /* Allow the target first crack at emitting this.  Some of the
971 	 special relocations require special directives instead of
972 	 just ".4byte" or whatever.  */
973 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
974       ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
975 					 addr, done);
976 #endif
977 
978       /* Indirection is used to get dynamic relocations out of a
979 	 read-only section.  */
980       if (encoding & DW_EH_PE_indirect)
981 	{
982 	  /* It is very tempting to use force_const_mem so that we share data
983 	     with the normal constant pool.  However, we've already emitted
984 	     the constant pool for this function.  Moreover, we'd like to
985 	     share these constants across the entire unit of translation and
986 	     even, if possible, across the entire application (or DSO).  */
987 	  addr = dw2_force_const_mem (addr, is_public);
988 	  encoding &= ~DW_EH_PE_indirect;
989 	  goto restart;
990 	}
991 
992       switch (encoding & 0xF0)
993 	{
994 	case DW_EH_PE_absptr:
995 	  dw2_assemble_integer (size, addr);
996 	  break;
997 
998 	case DW_EH_PE_pcrel:
999 	  gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1000 #ifdef ASM_OUTPUT_DWARF_PCREL
1001 	  ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
1002 #else
1003 	  dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
1004 #endif
1005 	  break;
1006 
1007 	default:
1008 	  /* Other encodings should have been handled by
1009 	     ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX.  */
1010 	  gcc_unreachable ();
1011 	}
1012 
1013 #ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
1014     done:;
1015 #endif
1016     }
1017 
1018   if (flag_debug_asm && comment)
1019     {
1020       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
1021       vfprintf (asm_out_file, comment, ap);
1022     }
1023   fputc ('\n', asm_out_file);
1024 
1025   va_end (ap);
1026 }
1027 
1028 #include "gt-dwarf2asm.h"
1029