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