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