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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [dwarf2asm.c] - Blame information for rev 826

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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