OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [dwarf2asm.c] - Blame information for rev 749

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.