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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [ehopt.c] - Blame information for rev 288

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

Line No. Rev Author Line
1 147 khays
/* ehopt.c--optimize gcc exception frame information.
2
   Copyright 1998, 2000, 2001, 2003, 2005, 2007, 2008, 2009
3
   Free Software Foundation, Inc.
4
   Written by Ian Lance Taylor <ian@cygnus.com>.
5
 
6
   This file is part of GAS, the GNU Assembler.
7
 
8
   GAS is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3, or (at your option)
11
   any later version.
12
 
13
   GAS is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with GAS; see the file COPYING.  If not, write to the Free
20
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21
   02110-1301, USA.  */
22
 
23
#include "as.h"
24
#include "subsegs.h"
25
#include "struc-symbol.h"
26
 
27
/* We include this ELF file, even though we may not be assembling for
28
   ELF, since the exception frame information is always in a format
29
   derived from DWARF.  */
30
 
31
#include "dwarf2.h"
32
 
33
/* Try to optimize gcc 2.8 exception frame information.
34
 
35
   Exception frame information is emitted for every function in the
36
   .eh_frame or .debug_frame sections.  Simple information for a function
37
   with no exceptions looks like this:
38
 
39
__FRAME_BEGIN__:
40
        .4byte  .LLCIE1 / Length of Common Information Entry
41
.LSCIE1:
42
#if .eh_frame
43
        .4byte  0x0     / CIE Identifier Tag
44
#elif .debug_frame
45
        .4byte  0xffffffff / CIE Identifier Tag
46
#endif
47
        .byte   0x1     / CIE Version
48
        .byte   0x0     / CIE Augmentation (none)
49
        .byte   0x1     / ULEB128 0x1 (CIE Code Alignment Factor)
50
        .byte   0x7c    / SLEB128 -4 (CIE Data Alignment Factor)
51
        .byte   0x8     / CIE RA Column
52
        .byte   0xc     / DW_CFA_def_cfa
53
        .byte   0x4     / ULEB128 0x4
54
        .byte   0x4     / ULEB128 0x4
55
        .byte   0x88    / DW_CFA_offset, column 0x8
56
        .byte   0x1     / ULEB128 0x1
57
        .align 4
58
.LECIE1:
59
        .set    .LLCIE1,.LECIE1-.LSCIE1 / CIE Length Symbol
60
        .4byte  .LLFDE1 / FDE Length
61
.LSFDE1:
62
        .4byte  .LSFDE1-__FRAME_BEGIN__ / FDE CIE offset
63
        .4byte  .LFB1   / FDE initial location
64
        .4byte  .LFE1-.LFB1     / FDE address range
65
        .byte   0x4     / DW_CFA_advance_loc4
66
        .4byte  .LCFI0-.LFB1
67
        .byte   0xe     / DW_CFA_def_cfa_offset
68
        .byte   0x8     / ULEB128 0x8
69
        .byte   0x85    / DW_CFA_offset, column 0x5
70
        .byte   0x2     / ULEB128 0x2
71
        .byte   0x4     / DW_CFA_advance_loc4
72
        .4byte  .LCFI1-.LCFI0
73
        .byte   0xd     / DW_CFA_def_cfa_register
74
        .byte   0x5     / ULEB128 0x5
75
        .byte   0x4     / DW_CFA_advance_loc4
76
        .4byte  .LCFI2-.LCFI1
77
        .byte   0x2e    / DW_CFA_GNU_args_size
78
        .byte   0x4     / ULEB128 0x4
79
        .byte   0x4     / DW_CFA_advance_loc4
80
        .4byte  .LCFI3-.LCFI2
81
        .byte   0x2e    / DW_CFA_GNU_args_size
82
        .byte   0x0     / ULEB128 0x0
83
        .align 4
84
.LEFDE1:
85
        .set    .LLFDE1,.LEFDE1-.LSFDE1 / FDE Length Symbol
86
 
87
   The immediate issue we can address in the assembler is the
88
   DW_CFA_advance_loc4 followed by a four byte value.  The value is
89
   the difference of two addresses in the function.  Since gcc does
90
   not know this value, it always uses four bytes.  We will know the
91
   value at the end of assembly, so we can do better.  */
92
 
93
struct cie_info
94
{
95
  unsigned code_alignment;
96
  int z_augmentation;
97
};
98
 
99
static int get_cie_info (struct cie_info *);
100
 
101
/* Extract information from the CIE.  */
102
 
103
static int
104
get_cie_info (struct cie_info *info)
105
{
106
  fragS *f;
107
  fixS *fix;
108
  int offset;
109
  char CIE_id;
110
  char augmentation[10];
111
  int iaug;
112
  int code_alignment = 0;
113
 
114
  /* We should find the CIE at the start of the section.  */
115
 
116
  f = seg_info (now_seg)->frchainP->frch_root;
117
  fix = seg_info (now_seg)->frchainP->fix_root;
118
 
119
  /* Look through the frags of the section to find the code alignment.  */
120
 
121
  /* First make sure that the CIE Identifier Tag is 0/-1.  */
122
 
123
  if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
124
    CIE_id = (char)0xff;
125
  else
126
    CIE_id = 0;
127
 
128
  offset = 4;
129
  while (f != NULL && offset >= f->fr_fix)
130
    {
131
      offset -= f->fr_fix;
132
      f = f->fr_next;
133
    }
134
  if (f == NULL
135
      || f->fr_fix - offset < 4
136
      || f->fr_literal[offset] != CIE_id
137
      || f->fr_literal[offset + 1] != CIE_id
138
      || f->fr_literal[offset + 2] != CIE_id
139
      || f->fr_literal[offset + 3] != CIE_id)
140
    return 0;
141
 
142
  /* Next make sure the CIE version number is 1.  */
143
 
144
  offset += 4;
145
  while (f != NULL && offset >= f->fr_fix)
146
    {
147
      offset -= f->fr_fix;
148
      f = f->fr_next;
149
    }
150
  if (f == NULL
151
      || f->fr_fix - offset < 1
152
      || f->fr_literal[offset] != 1)
153
    return 0;
154
 
155
  /* Skip the augmentation (a null terminated string).  */
156
 
157
  iaug = 0;
158
  ++offset;
159
  while (1)
160
    {
161
      while (f != NULL && offset >= f->fr_fix)
162
        {
163
          offset -= f->fr_fix;
164
          f = f->fr_next;
165
        }
166
      if (f == NULL)
167
        return 0;
168
 
169
      while (offset < f->fr_fix && f->fr_literal[offset] != '\0')
170
        {
171
          if ((size_t) iaug < (sizeof augmentation) - 1)
172
            {
173
              augmentation[iaug] = f->fr_literal[offset];
174
              ++iaug;
175
            }
176
          ++offset;
177
        }
178
      if (offset < f->fr_fix)
179
        break;
180
    }
181
  ++offset;
182
  while (f != NULL && offset >= f->fr_fix)
183
    {
184
      offset -= f->fr_fix;
185
      f = f->fr_next;
186
    }
187
  if (f == NULL)
188
    return 0;
189
 
190
  augmentation[iaug] = '\0';
191
  if (augmentation[0] == '\0')
192
    {
193
      /* No augmentation.  */
194
    }
195
  else if (strcmp (augmentation, "eh") == 0)
196
    {
197
      /* We have to skip a pointer.  Unfortunately, we don't know how
198
         large it is.  We find out by looking for a matching fixup.  */
199
      while (fix != NULL
200
             && (fix->fx_frag != f || fix->fx_where != offset))
201
        fix = fix->fx_next;
202
      if (fix == NULL)
203
        offset += 4;
204
      else
205
        offset += fix->fx_size;
206
      while (f != NULL && offset >= f->fr_fix)
207
        {
208
          offset -= f->fr_fix;
209
          f = f->fr_next;
210
        }
211
      if (f == NULL)
212
        return 0;
213
    }
214
  else if (augmentation[0] != 'z')
215
    return 0;
216
 
217
  /* We're now at the code alignment factor, which is a ULEB128.  If
218
     it isn't a single byte, forget it.  */
219
 
220
  code_alignment = f->fr_literal[offset] & 0xff;
221
  if ((code_alignment & 0x80) != 0)
222
    code_alignment = 0;
223
 
224
  info->code_alignment = code_alignment;
225
  info->z_augmentation = (augmentation[0] == 'z');
226
 
227
  return 1;
228
}
229
 
230
enum frame_state
231
{
232
  state_idle,
233
  state_saw_size,
234
  state_saw_cie_offset,
235
  state_saw_pc_begin,
236
  state_seeing_aug_size,
237
  state_skipping_aug,
238
  state_wait_loc4,
239
  state_saw_loc4,
240
  state_error,
241
};
242
 
243
/* This function is called from emit_expr.  It looks for cases which
244
   we can optimize.
245
 
246
   Rather than try to parse all this information as we read it, we
247
   look for a single byte DW_CFA_advance_loc4 followed by a 4 byte
248
   difference.  We turn that into a rs_cfa_advance frag, and handle
249
   those frags at the end of the assembly.  If the gcc output changes
250
   somewhat, this optimization may stop working.
251
 
252
   This function returns non-zero if it handled the expression and
253
   emit_expr should not do anything, or zero otherwise.  It can also
254
   change *EXP and *PNBYTES.  */
255
 
256
int
257
check_eh_frame (expressionS *exp, unsigned int *pnbytes)
258
{
259
  struct frame_data
260
  {
261
    enum frame_state state;
262
 
263
    int cie_info_ok;
264
    struct cie_info cie_info;
265
 
266
    symbolS *size_end_sym;
267
    fragS *loc4_frag;
268
    int loc4_fix;
269
 
270
    int aug_size;
271
    int aug_shift;
272
  };
273
 
274
  static struct frame_data eh_frame_data;
275
  static struct frame_data debug_frame_data;
276
  struct frame_data *d;
277
 
278
  /* Don't optimize.  */
279
  if (flag_traditional_format)
280
    return 0;
281
 
282
#ifdef md_allow_eh_opt
283
  if (! md_allow_eh_opt)
284
    return 0;
285
#endif
286
 
287
  /* Select the proper section data.  */
288
  if (strncmp (segment_name (now_seg), ".eh_frame", 9) == 0
289
      && segment_name (now_seg)[9] != '_')
290
    d = &eh_frame_data;
291
  else if (strncmp (segment_name (now_seg), ".debug_frame", 12) == 0)
292
    d = &debug_frame_data;
293
  else
294
    return 0;
295
 
296
  if (d->state >= state_saw_size && S_IS_DEFINED (d->size_end_sym))
297
    {
298
      /* We have come to the end of the CIE or FDE.  See below where
299
         we set saw_size.  We must check this first because we may now
300
         be looking at the next size.  */
301
      d->state = state_idle;
302
    }
303
 
304
  switch (d->state)
305
    {
306
    case state_idle:
307
      if (*pnbytes == 4)
308
        {
309
          /* This might be the size of the CIE or FDE.  We want to know
310
             the size so that we don't accidentally optimize across an FDE
311
             boundary.  We recognize the size in one of two forms: a
312
             symbol which will later be defined as a difference, or a
313
             subtraction of two symbols.  Either way, we can tell when we
314
             are at the end of the FDE because the symbol becomes defined
315
             (in the case of a subtraction, the end symbol, from which the
316
             start symbol is being subtracted).  Other ways of describing
317
             the size will not be optimized.  */
318
          if ((exp->X_op == O_symbol || exp->X_op == O_subtract)
319
              && ! S_IS_DEFINED (exp->X_add_symbol))
320
            {
321
              d->state = state_saw_size;
322
              d->size_end_sym = exp->X_add_symbol;
323
            }
324
        }
325
      break;
326
 
327
    case state_saw_size:
328
    case state_saw_cie_offset:
329
      /* Assume whatever form it appears in, it appears atomically.  */
330
      d->state = (enum frame_state) (d->state + 1);
331
      break;
332
 
333
    case state_saw_pc_begin:
334
      /* Decide whether we should see an augmentation.  */
335
      if (! d->cie_info_ok
336
          && ! (d->cie_info_ok = get_cie_info (&d->cie_info)))
337
        d->state = state_error;
338
      else if (d->cie_info.z_augmentation)
339
        {
340
          d->state = state_seeing_aug_size;
341
          d->aug_size = 0;
342
          d->aug_shift = 0;
343
        }
344
      else
345
        d->state = state_wait_loc4;
346
      break;
347
 
348
    case state_seeing_aug_size:
349
      /* Bytes == -1 means this comes from an leb128 directive.  */
350
      if ((int)*pnbytes == -1 && exp->X_op == O_constant)
351
        {
352
          d->aug_size = exp->X_add_number;
353
          d->state = state_skipping_aug;
354
        }
355
      else if (*pnbytes == 1 && exp->X_op == O_constant)
356
        {
357
          unsigned char byte = exp->X_add_number;
358
          d->aug_size |= (byte & 0x7f) << d->aug_shift;
359
          d->aug_shift += 7;
360
          if ((byte & 0x80) == 0)
361
            d->state = state_skipping_aug;
362
        }
363
      else
364
        d->state = state_error;
365
      if (d->state == state_skipping_aug && d->aug_size == 0)
366
        d->state = state_wait_loc4;
367
      break;
368
 
369
    case state_skipping_aug:
370
      if ((int)*pnbytes < 0)
371
        d->state = state_error;
372
      else
373
        {
374
          int left = (d->aug_size -= *pnbytes);
375
          if (left == 0)
376
            d->state = state_wait_loc4;
377
          else if (left < 0)
378
            d->state = state_error;
379
        }
380
      break;
381
 
382
    case state_wait_loc4:
383
      if (*pnbytes == 1
384
          && exp->X_op == O_constant
385
          && exp->X_add_number == DW_CFA_advance_loc4)
386
        {
387
          /* This might be a DW_CFA_advance_loc4.  Record the frag and the
388
             position within the frag, so that we can change it later.  */
389
          frag_grow (1);
390
          d->state = state_saw_loc4;
391
          d->loc4_frag = frag_now;
392
          d->loc4_fix = frag_now_fix ();
393
        }
394
      break;
395
 
396
    case state_saw_loc4:
397
      d->state = state_wait_loc4;
398
      if (*pnbytes != 4)
399
        break;
400
      if (exp->X_op == O_constant)
401
        {
402
          /* This is a case which we can optimize.  The two symbols being
403
             subtracted were in the same frag and the expression was
404
             reduced to a constant.  We can do the optimization entirely
405
             in this function.  */
406
          if (exp->X_add_number < 0x40)
407
            {
408
              d->loc4_frag->fr_literal[d->loc4_fix]
409
                = DW_CFA_advance_loc | exp->X_add_number;
410
              /* No more bytes needed.  */
411
              return 1;
412
            }
413
          else if (exp->X_add_number < 0x100)
414
            {
415
              d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc1;
416
              *pnbytes = 1;
417
            }
418
          else if (exp->X_add_number < 0x10000)
419
            {
420
              d->loc4_frag->fr_literal[d->loc4_fix] = DW_CFA_advance_loc2;
421
              *pnbytes = 2;
422
            }
423
        }
424
      else if (exp->X_op == O_subtract && d->cie_info.code_alignment == 1)
425
        {
426
          /* This is a case we can optimize.  The expression was not
427
             reduced, so we can not finish the optimization until the end
428
             of the assembly.  We set up a variant frag which we handle
429
             later.  */
430
          frag_var (rs_cfa, 4, 0, 1 << 3, make_expr_symbol (exp),
431
                    d->loc4_fix, (char *) d->loc4_frag);
432
          return 1;
433
        }
434
      else if ((exp->X_op == O_divide
435
                || exp->X_op == O_right_shift)
436
               && d->cie_info.code_alignment > 1)
437
        {
438
          if (exp->X_add_symbol->bsym
439
              && exp->X_op_symbol->bsym
440
              && exp->X_add_symbol->sy_value.X_op == O_subtract
441
              && exp->X_op_symbol->sy_value.X_op == O_constant
442
              && ((exp->X_op == O_divide
443
                   ? exp->X_op_symbol->sy_value.X_add_number
444
                   : (offsetT) 1 << exp->X_op_symbol->sy_value.X_add_number)
445
                  == (offsetT) d->cie_info.code_alignment))
446
            {
447
              /* This is a case we can optimize as well.  The expression was
448
                 not reduced, so we can not finish the optimization until the
449
                 end of the assembly.  We set up a variant frag which we
450
                 handle later.  */
451
              frag_var (rs_cfa, 4, 0, d->cie_info.code_alignment << 3,
452
                        make_expr_symbol (&exp->X_add_symbol->sy_value),
453
                        d->loc4_fix, (char *) d->loc4_frag);
454
              return 1;
455
            }
456
        }
457
      break;
458
 
459
    case state_error:
460
      /* Just skipping everything.  */
461
      break;
462
    }
463
 
464
  return 0;
465
}
466
 
467
/* The function estimates the size of a rs_cfa variant frag based on
468
   the current values of the symbols.  It is called before the
469
   relaxation loop.  We set fr_subtype{0:2} to the expected length.  */
470
 
471
int
472
eh_frame_estimate_size_before_relax (fragS *frag)
473
{
474
  offsetT diff;
475
  int ca = frag->fr_subtype >> 3;
476
  int ret;
477
 
478
  diff = resolve_symbol_value (frag->fr_symbol);
479
 
480
  gas_assert (ca > 0);
481
  diff /= ca;
482
  if (diff < 0x40)
483
    ret = 0;
484
  else if (diff < 0x100)
485
    ret = 1;
486
  else if (diff < 0x10000)
487
    ret = 2;
488
  else
489
    ret = 4;
490
 
491
  frag->fr_subtype = (frag->fr_subtype & ~7) | ret;
492
 
493
  return ret;
494
}
495
 
496
/* This function relaxes a rs_cfa variant frag based on the current
497
   values of the symbols.  fr_subtype{0:2} is the current length of
498
   the frag.  This returns the change in frag length.  */
499
 
500
int
501
eh_frame_relax_frag (fragS *frag)
502
{
503
  int oldsize, newsize;
504
 
505
  oldsize = frag->fr_subtype & 7;
506
  newsize = eh_frame_estimate_size_before_relax (frag);
507
  return newsize - oldsize;
508
}
509
 
510
/* This function converts a rs_cfa variant frag into a normal fill
511
   frag.  This is called after all relaxation has been done.
512
   fr_subtype{0:2} will be the desired length of the frag.  */
513
 
514
void
515
eh_frame_convert_frag (fragS *frag)
516
{
517
  offsetT diff;
518
  fragS *loc4_frag;
519
  int loc4_fix, ca;
520
 
521
  loc4_frag = (fragS *) frag->fr_opcode;
522
  loc4_fix = (int) frag->fr_offset;
523
 
524
  diff = resolve_symbol_value (frag->fr_symbol);
525
 
526
  ca = frag->fr_subtype >> 3;
527
  gas_assert (ca > 0);
528
  diff /= ca;
529
  switch (frag->fr_subtype & 7)
530
    {
531
    case 0:
532
      gas_assert (diff < 0x40);
533
      loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | diff;
534
      break;
535
 
536
    case 1:
537
      gas_assert (diff < 0x100);
538
      loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc1;
539
      frag->fr_literal[frag->fr_fix] = diff;
540
      break;
541
 
542
    case 2:
543
      gas_assert (diff < 0x10000);
544
      loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc2;
545
      md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 2);
546
      break;
547
 
548
    default:
549
      md_number_to_chars (frag->fr_literal + frag->fr_fix, diff, 4);
550
      break;
551
    }
552
 
553
  frag->fr_fix += frag->fr_subtype & 7;
554
  frag->fr_type = rs_fill;
555
  frag->fr_subtype = 0;
556
  frag->fr_offset = 0;
557
}

powered by: WebSVN 2.1.0

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