]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/dwarf2asm.c
haifa-sched.c (insn_finishes_cycle_p): New static function.
[thirdparty/gcc.git] / gcc / dwarf2asm.c
CommitLineData
2e4b9b8c 1/* Dwarf2 assembler output helper routines.
66647d44
JJ
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008
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"
bbf531f0 32#include "elf/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. */
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
f90811a2
RH
449 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
450 "indirect pcrel")
e1f9550a
RH
451 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,
452 "indirect pcrel uleb128")
453 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_pcrel,
454 "indirect pcrel udata2")
455 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_pcrel,
456 "indirect pcrel udata4")
457 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_pcrel,
458 "indirect pcrel udata8")
459 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_pcrel,
460 "indirect pcrel sleb128")
461 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_pcrel,
462 "indirect pcrel sdata2")
463 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_pcrel,
464 "indirect pcrel sdata4")
465 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_pcrel,
466 "indirect pcrel sdata8")
467
f90811a2
RH
468 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_textrel,
469 "indirect textrel")
e1f9550a
RH
470 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_textrel,
471 "indirect textrel uleb128")
472 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_textrel,
473 "indirect textrel udata2")
474 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_textrel,
475 "indirect textrel udata4")
476 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_textrel,
477 "indirect textrel udata8")
478 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_textrel,
479 "indirect textrel sleb128")
480 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_textrel,
481 "indirect textrel sdata2")
482 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_textrel,
483 "indirect textrel sdata4")
484 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_textrel,
485 "indirect textrel sdata8")
486
f90811a2
RH
487 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_datarel,
488 "indirect datarel")
e1f9550a
RH
489 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_datarel,
490 "indirect datarel uleb128")
491 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_datarel,
492 "indirect datarel udata2")
493 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_datarel,
494 "indirect datarel udata4")
495 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_datarel,
496 "indirect datarel udata8")
497 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_datarel,
498 "indirect datarel sleb128")
499 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_datarel,
500 "indirect datarel sdata2")
501 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_datarel,
502 "indirect datarel sdata4")
503 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_datarel,
504 "indirect datarel sdata8")
505
f90811a2
RH
506 S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_funcrel,
507 "indirect funcrel")
e1f9550a
RH
508 S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_funcrel,
509 "indirect funcrel uleb128")
510 S(DW_EH_PE_indirect | DW_EH_PE_udata2 | DW_EH_PE_funcrel,
511 "indirect funcrel udata2")
512 S(DW_EH_PE_indirect | DW_EH_PE_udata4 | DW_EH_PE_funcrel,
513 "indirect funcrel udata4")
514 S(DW_EH_PE_indirect | DW_EH_PE_udata8 | DW_EH_PE_funcrel,
515 "indirect funcrel udata8")
516 S(DW_EH_PE_indirect | DW_EH_PE_sleb128 | DW_EH_PE_funcrel,
517 "indirect funcrel sleb128")
518 S(DW_EH_PE_indirect | DW_EH_PE_sdata2 | DW_EH_PE_funcrel,
519 "indirect funcrel sdata2")
520 S(DW_EH_PE_indirect | DW_EH_PE_sdata4 | DW_EH_PE_funcrel,
521 "indirect funcrel sdata4")
522 S(DW_EH_PE_indirect | DW_EH_PE_sdata8 | DW_EH_PE_funcrel,
523 "indirect funcrel sdata8")
524
525#if HAVE_DESIGNATED_INITIALIZERS
526 };
527
ced3f397
NS
528 gcc_assert (format >= 0 && format < 0x100 && format_names[format]);
529
e1f9550a
RH
530 return format_names[format];
531#else
532 }
ced3f397 533 gcc_unreachable ();
e1f9550a
RH
534#endif
535}
536
d4ea4622
RH
537/* Output an unsigned LEB128 quantity, but only the byte values. */
538
539void
540dw2_asm_output_data_uleb128_raw (unsigned HOST_WIDE_INT value)
541{
542 while (1)
543 {
544 int byte = (value & 0x7f);
545 value >>= 7;
546 if (value != 0)
547 /* More bytes to follow. */
548 byte |= 0x80;
549
550 fprintf (asm_out_file, "0x%x", byte);
551 if (value == 0)
552 break;
553 fputc (',', asm_out_file);
554 }
555}
556
2e4b9b8c
RH
557/* Output an unsigned LEB128 quantity. */
558
559void
e34d07f2
KG
560dw2_asm_output_data_uleb128 (unsigned HOST_WIDE_INT value,
561 const char *comment, ...)
2e4b9b8c 562{
e34d07f2 563 va_list ap;
7080f735 564
e34d07f2 565 va_start (ap, comment);
2e4b9b8c
RH
566
567#ifdef HAVE_AS_LEB128
90ff44cf 568 fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
2e4b9b8c
RH
569
570 if (flag_debug_asm && comment)
571 {
572 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
573 vfprintf (asm_out_file, comment, ap);
574 }
575#else
576 {
577 unsigned HOST_WIDE_INT work = value;
301d03af 578 const char *byte_op = targetm.asm_out.byte_op;
2e4b9b8c 579
301d03af
RS
580 if (byte_op)
581 fputs (byte_op, asm_out_file);
2e4b9b8c
RH
582 do
583 {
584 int byte = (work & 0x7f);
585 work >>= 7;
586 if (work != 0)
587 /* More bytes to follow. */
588 byte |= 0x80;
589
301d03af
RS
590 if (byte_op)
591 {
592 fprintf (asm_out_file, "0x%x", byte);
593 if (work != 0)
594 fputc (',', asm_out_file);
595 }
596 else
597 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
2e4b9b8c
RH
598 }
599 while (work != 0);
600
601 if (flag_debug_asm)
602 {
90ff44cf
KG
603 fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
604 ASM_COMMENT_START, value);
2e4b9b8c
RH
605 if (comment)
606 {
607 fputs ("; ", asm_out_file);
608 vfprintf (asm_out_file, comment, ap);
609 }
610 }
611 }
612#endif
613 fputc ('\n', asm_out_file);
614
e34d07f2 615 va_end (ap);
2e4b9b8c
RH
616}
617
d4ea4622
RH
618/* Output an signed LEB128 quantity, but only the byte values. */
619
620void
621dw2_asm_output_data_sleb128_raw (HOST_WIDE_INT value)
622{
623 int byte, more;
624
625 while (1)
626 {
627 byte = (value & 0x7f);
628 value >>= 7;
629 more = !((value == 0 && (byte & 0x40) == 0)
630 || (value == -1 && (byte & 0x40) != 0));
631 if (more)
632 byte |= 0x80;
633
634 fprintf (asm_out_file, "0x%x", byte);
635 if (!more)
636 break;
637 fputc (',', asm_out_file);
638 }
639}
640
09da1532 641/* Output a signed LEB128 quantity. */
2e4b9b8c
RH
642
643void
e34d07f2
KG
644dw2_asm_output_data_sleb128 (HOST_WIDE_INT value,
645 const char *comment, ...)
2e4b9b8c 646{
e34d07f2 647 va_list ap;
7080f735 648
e34d07f2 649 va_start (ap, comment);
2e4b9b8c
RH
650
651#ifdef HAVE_AS_LEB128
90ff44cf 652 fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
2e4b9b8c
RH
653
654 if (flag_debug_asm && comment)
655 {
656 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
657 vfprintf (asm_out_file, comment, ap);
658 }
659#else
660 {
661 HOST_WIDE_INT work = value;
662 int more, byte;
301d03af 663 const char *byte_op = targetm.asm_out.byte_op;
2e4b9b8c 664
301d03af
RS
665 if (byte_op)
666 fputs (byte_op, asm_out_file);
2e4b9b8c
RH
667 do
668 {
669 byte = (work & 0x7f);
670 /* arithmetic shift */
671 work >>= 7;
672 more = !((work == 0 && (byte & 0x40) == 0)
673 || (work == -1 && (byte & 0x40) != 0));
674 if (more)
675 byte |= 0x80;
676
301d03af
RS
677 if (byte_op)
678 {
679 fprintf (asm_out_file, "0x%x", byte);
680 if (more)
681 fputc (',', asm_out_file);
682 }
683 else
684 assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
2e4b9b8c
RH
685 }
686 while (more);
687
688 if (flag_debug_asm)
689 {
90ff44cf
KG
690 fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
691 ASM_COMMENT_START, value);
2e4b9b8c
RH
692 if (comment)
693 {
694 fputs ("; ", asm_out_file);
695 vfprintf (asm_out_file, comment, ap);
696 }
697 }
698 }
699#endif
700 fputc ('\n', asm_out_file);
701
e34d07f2 702 va_end (ap);
2e4b9b8c
RH
703}
704
705void
e34d07f2
KG
706dw2_asm_output_delta_uleb128 (const char *lab1 ATTRIBUTE_UNUSED,
707 const char *lab2 ATTRIBUTE_UNUSED,
708 const char *comment, ...)
2e4b9b8c 709{
e34d07f2
KG
710 va_list ap;
711
712 va_start (ap, comment);
2e4b9b8c
RH
713
714#ifdef HAVE_AS_LEB128
da6af203 715 fputs ("\t.uleb128 ", asm_out_file);
2e4b9b8c
RH
716 assemble_name (asm_out_file, lab1);
717 fputc ('-', asm_out_file);
718 assemble_name (asm_out_file, lab2);
719#else
ced3f397 720 gcc_unreachable ();
2e4b9b8c
RH
721#endif
722
723 if (flag_debug_asm && comment)
724 {
725 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
726 vfprintf (asm_out_file, comment, ap);
727 }
728 fputc ('\n', asm_out_file);
729
e34d07f2 730 va_end (ap);
2e4b9b8c
RH
731}
732
c8f4fe99
BE
733#if 0
734
2e4b9b8c 735void
e34d07f2
KG
736dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
737 const char *lab2 ATTRIBUTE_UNUSED,
738 const char *comment, ...)
2e4b9b8c 739{
e34d07f2 740 va_list ap;
7080f735 741
e34d07f2 742 va_start (ap, comment);
2e4b9b8c
RH
743
744#ifdef HAVE_AS_LEB128
da6af203 745 fputs ("\t.sleb128 ", asm_out_file);
2e4b9b8c
RH
746 assemble_name (asm_out_file, lab1);
747 fputc ('-', asm_out_file);
748 assemble_name (asm_out_file, lab2);
749#else
ced3f397 750 gcc_unreachable ();
2e4b9b8c
RH
751#endif
752
753 if (flag_debug_asm && comment)
754 {
755 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
756 vfprintf (asm_out_file, comment, ap);
757 }
758 fputc ('\n', asm_out_file);
759
e34d07f2 760 va_end (ap);
2e4b9b8c 761}
c8f4fe99 762#endif /* 0 */
2a1ee410 763\f
7080f735 764static int dw2_output_indirect_constant_1 (splay_tree_node, void *);
2a1ee410 765
17211ab5
GK
766static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
767
768static GTY(()) int dw2_const_labelno;
2a1ee410 769
d6d26764
JJ
770#if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
771# define USE_LINKONCE_INDIRECT 1
772#else
773# define USE_LINKONCE_INDIRECT 0
774#endif
775
dc1327cd
AO
776/* Comparison function for a splay tree in which the keys are strings.
777 K1 and K2 have the dynamic type "const char *". Returns <0, 0, or
778 >0 to indicate whether K1 is less than, equal to, or greater than
779 K2, respectively. */
780
781static int
782splay_tree_compare_strings (splay_tree_key k1, splay_tree_key k2)
783{
784 const char *s1 = (const char *)k1;
785 const char *s2 = (const char *)k2;
786 int ret;
787
788 if (s1 == s2)
789 return 0;
790
791 ret = strcmp (s1, s2);
792
793 /* The strings are always those from IDENTIFIER_NODEs, and,
794 therefore, we should never have two copies of the same
795 string. */
796 gcc_assert (ret);
797
798 return ret;
799}
800
e1f9550a
RH
801/* Put X, a SYMBOL_REF, in memory. Return a SYMBOL_REF to the allocated
802 memory. Differs from force_const_mem in that a single pool is used for
803 the entire unit of translation, and the memory is not guaranteed to be
d858f359 804 "near" the function in any interesting sense. IS_PUBLIC controls whether
b03e9863 805 the symbol can be shared across the entire application (or DSO). */
e1f9550a 806
d4ea4622 807rtx
d858f359 808dw2_force_const_mem (rtx x, bool is_public)
2a1ee410
RH
809{
810 splay_tree_node node;
a2649528 811 const char *key;
78bd9046 812 tree decl_id;
2a1ee410
RH
813
814 if (! indirect_pool)
dc1327cd
AO
815 /* We use strcmp, rather than just comparing pointers, so that the
816 sort order will not depend on the host system. */
817 indirect_pool = splay_tree_new_ggc (splay_tree_compare_strings);
2a1ee410 818
ced3f397 819 gcc_assert (GET_CODE (x) == SYMBOL_REF);
1ee9fb20 820
a2649528
JDA
821 key = XSTR (x, 0);
822 node = splay_tree_lookup (indirect_pool, (splay_tree_key) key);
2a1ee410 823 if (node)
78bd9046 824 decl_id = (tree) node->value;
2a1ee410
RH
825 else
826 {
2a1ee410 827 tree id;
a2649528 828 const char *str = targetm.strip_name_encoding (key);
2a1ee410 829
d858f359 830 if (is_public && USE_LINKONCE_INDIRECT)
d6d26764 831 {
f883e0a7 832 char *ref_name = XALLOCAVEC (char, strlen (str) + sizeof "DW.ref.");
d6d26764 833
1ee9fb20 834 sprintf (ref_name, "DW.ref.%s", str);
78bd9046
AO
835 gcc_assert (!maybe_get_identifier (ref_name));
836 decl_id = get_identifier (ref_name);
837 TREE_PUBLIC (decl_id) = 1;
d6d26764
JJ
838 }
839 else
840 {
d6d26764
JJ
841 char label[32];
842
17211ab5
GK
843 ASM_GENERATE_INTERNAL_LABEL (label, "LDFCM", dw2_const_labelno);
844 ++dw2_const_labelno;
78bd9046
AO
845 gcc_assert (!maybe_get_identifier (label));
846 decl_id = get_identifier (label);
d6d26764 847 }
2a1ee410 848
1ee9fb20 849 id = maybe_get_identifier (str);
2a1ee410
RH
850 if (id)
851 TREE_SYMBOL_REFERENCED (id) = 1;
852
a2649528 853 splay_tree_insert (indirect_pool, (splay_tree_key) key,
78bd9046 854 (splay_tree_value) decl_id);
2a1ee410
RH
855 }
856
78bd9046 857 return gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (decl_id));
2a1ee410
RH
858}
859
e1f9550a
RH
860/* A helper function for dw2_output_indirect_constants called through
861 splay_tree_foreach. Emit one queued constant to memory. */
862
2a1ee410 863static int
7080f735
AJ
864dw2_output_indirect_constant_1 (splay_tree_node node,
865 void *data ATTRIBUTE_UNUSED)
2a1ee410 866{
d6d26764 867 const char *sym;
2a1ee410 868 rtx sym_ref;
78bd9046 869 tree id, decl;
2a1ee410 870
2a1ee410 871 sym = (const char *) node->key;
78bd9046
AO
872 id = (tree) node->value;
873
c2255bc4 874 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, ptr_type_node);
78bd9046
AO
875 DECL_ARTIFICIAL (decl) = 1;
876 DECL_IGNORED_P (decl) = 1;
877 DECL_INITIAL (decl) = decl;
878
879 if (TREE_PUBLIC (id))
880 {
881 TREE_PUBLIC (decl) = 1;
fc26fae3 882 make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
78bd9046
AO
883 }
884 else
885 TREE_STATIC (decl) = 1;
886
2a1ee410 887 sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
a2649528 888 sym = targetm.strip_name_encoding (sym);
b03e9863 889 if (TREE_PUBLIC (decl) && USE_LINKONCE_INDIRECT)
a5c414e0 890 fprintf (asm_out_file, "\t.hidden %sDW.ref.%s\n", user_label_prefix, sym);
b03e9863 891 assemble_variable (decl, 1, 1, 1);
2919600a 892 assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
2a1ee410
RH
893
894 return 0;
895}
896
e1f9550a
RH
897/* Emit the constants queued through dw2_force_const_mem. */
898
2a1ee410 899void
7080f735 900dw2_output_indirect_constants (void)
2a1ee410 901{
d6d26764
JJ
902 if (indirect_pool)
903 splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
2a1ee410
RH
904}
905
b03e9863
EB
906/* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
907 If PUBLIC is set and the encoding is DW_EH_PE_indirect, the indirect
908 reference is shared across the entire application (or DSO). */
e1f9550a 909
2a1ee410 910void
d858f359 911dw2_asm_output_encoded_addr_rtx (int encoding, rtx addr, bool is_public,
e34d07f2 912 const char *comment, ...)
2a1ee410
RH
913{
914 int size;
e34d07f2 915 va_list ap;
7080f735 916
e34d07f2 917 va_start (ap, comment);
e1f9550a
RH
918
919 size = size_of_encoded_value (encoding);
2a1ee410 920
099c8b17
RH
921 if (encoding == DW_EH_PE_aligned)
922 {
923 assemble_align (POINTER_SIZE);
9f5cd0c5
RH
924 assemble_integer (addr, size, POINTER_SIZE, 1);
925 return;
099c8b17
RH
926 }
927
3248917b
RK
928 /* NULL is _always_ represented as a plain zero, as is 1 for Ada's
929 "all others". */
930 if (addr == const0_rtx || addr == const1_rtx)
c8af3574 931 assemble_integer (addr, size, BITS_PER_UNIT, 1);
e1f9550a 932 else
2a1ee410 933 {
e1f9550a
RH
934 restart:
935 /* Allow the target first crack at emitting this. Some of the
3a538a66 936 special relocations require special directives instead of
e1f9550a 937 just ".4byte" or whatever. */
2a1ee410 938#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
e1f9550a
RH
939 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX (asm_out_file, encoding, size,
940 addr, done);
2a1ee410
RH
941#endif
942
e1f9550a
RH
943 /* Indirection is used to get dynamic relocations out of a
944 read-only section. */
945 if (encoding & DW_EH_PE_indirect)
946 {
947 /* It is very tempting to use force_const_mem so that we share data
948 with the normal constant pool. However, we've already emitted
949 the constant pool for this function. Moreover, we'd like to
b03e9863
EB
950 share these constants across the entire unit of translation and
951 even, if possible, across the entire application (or DSO). */
d858f359 952 addr = dw2_force_const_mem (addr, is_public);
e1f9550a
RH
953 encoding &= ~DW_EH_PE_indirect;
954 goto restart;
955 }
2a1ee410 956
e1f9550a
RH
957 switch (encoding & 0xF0)
958 {
959 case DW_EH_PE_absptr:
301d03af 960 dw2_assemble_integer (size, addr);
e1f9550a 961 break;
2a1ee410 962
e1f9550a 963 case DW_EH_PE_pcrel:
ced3f397 964 gcc_assert (GET_CODE (addr) == SYMBOL_REF);
2a1ee410 965#ifdef ASM_OUTPUT_DWARF_PCREL
e1f9550a 966 ASM_OUTPUT_DWARF_PCREL (asm_out_file, size, XSTR (addr, 0));
2a1ee410 967#else
301d03af 968 dw2_assemble_integer (size, gen_rtx_MINUS (Pmode, addr, pc_rtx));
2a1ee410 969#endif
e1f9550a 970 break;
2a1ee410 971
e1f9550a 972 default:
3a538a66 973 /* Other encodings should have been handled by
e1f9550a 974 ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX. */
ced3f397 975 gcc_unreachable ();
e1f9550a 976 }
2a1ee410
RH
977
978#ifdef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
e1f9550a 979 done:;
2a1ee410 980#endif
e1f9550a
RH
981 }
982
983 if (flag_debug_asm && comment)
984 {
985 fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
986 vfprintf (asm_out_file, comment, ap);
987 }
2a1ee410 988 fputc ('\n', asm_out_file);
e1f9550a 989
e34d07f2 990 va_end (ap);
2a1ee410 991}
17211ab5
GK
992
993#include "gt-dwarf2asm.h"