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