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