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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gas/] [ehopt.c] - Blame information for rev 857

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

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

powered by: WebSVN 2.1.0

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