summaryrefslogtreecommitdiff
path: root/gas/ehopt.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2008-11-28 21:28:28 +0000
committerJakub Jelinek <jakub@redhat.com>2008-11-28 21:28:28 +0000
commitb55fb26fb141fc1df94ddf7a3f1471da3eabab83 (patch)
treed53d4bbdf3e6df71e9b918a05b8100adb60603f6 /gas/ehopt.c
parentd838b8bc626c044dba1661ab716dc9a45a74d5c7 (diff)
downloadbinutils-redhat-b55fb26fb141fc1df94ddf7a3f1471da3eabab83.tar.gz
* Makefile.am (ehopt.o): Add struc-symbol.h.
* Makefile.in: Regenerated. * ehopt.c: Include struc-symbol.h. (check_eh_frame): For very small O_constant DW_CFA_advance_loc4 create correct DW_CFA_advance_loc. Handle O_subtract only for code alignment factor 1, otherwise handle O_divide or O_right_shift of O_subtract and O_constant. (eh_frame_estimate_size_before_relax): Always divide by ca. (eh_frame_convert_frag): Likewise. * dw2gencfi.c (output_cfi_insn): Scale DW_CFA_advance_loc1, DW_CFA_advance_loc2 and DW_CFA_advance_loc4 outputs.
Diffstat (limited to 'gas/ehopt.c')
-rw-r--r--gas/ehopt.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/gas/ehopt.c b/gas/ehopt.c
index 048bc57b5a..323e27e861 100644
--- a/gas/ehopt.c
+++ b/gas/ehopt.c
@@ -1,5 +1,6 @@
/* ehopt.c--optimize gcc exception frame information.
- Copyright 1998, 2000, 2001, 2003, 2005, 2007 Free Software Foundation, Inc.
+ Copyright 1998, 2000, 2001, 2003, 2005, 2007, 2008
+ Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>.
This file is part of GAS, the GNU Assembler.
@@ -21,6 +22,7 @@
#include "as.h"
#include "subsegs.h"
+#include "struc-symbol.h"
/* We include this ELF file, even though we may not be assembling for
ELF, since the exception frame information is always in a format
@@ -398,13 +400,10 @@ check_eh_frame (expressionS *exp, unsigned int *pnbytes)
subtracted were in the same frag and the expression was
reduced to a constant. We can do the optimization entirely
in this function. */
- if (d->cie_info.code_alignment > 0
- && exp->X_add_number % d->cie_info.code_alignment == 0
- && exp->X_add_number / d->cie_info.code_alignment < 0x40)
+ if (exp->X_add_number < 0x40)
{
d->loc4_frag->fr_literal[d->loc4_fix]
- = DW_CFA_advance_loc
- | (exp->X_add_number / d->cie_info.code_alignment);
+ = DW_CFA_advance_loc | exp->X_add_number;
/* No more bytes needed. */
return 1;
}
@@ -419,23 +418,39 @@ check_eh_frame (expressionS *exp, unsigned int *pnbytes)
*pnbytes = 2;
}
}
- else if (exp->X_op == O_subtract)
+ else if (exp->X_op == O_subtract && d->cie_info.code_alignment == 1)
{
/* This is a case we can optimize. The expression was not
reduced, so we can not finish the optimization until the end
of the assembly. We set up a variant frag which we handle
later. */
- int fr_subtype;
-
- if (d->cie_info.code_alignment > 0)
- fr_subtype = d->cie_info.code_alignment << 3;
- else
- fr_subtype = 0;
-
- frag_var (rs_cfa, 4, 0, fr_subtype, make_expr_symbol (exp),
+ frag_var (rs_cfa, 4, 0, 1 << 3, make_expr_symbol (exp),
d->loc4_fix, (char *) d->loc4_frag);
return 1;
}
+ else if ((exp->X_op == O_divide
+ || exp->X_op == O_right_shift)
+ && d->cie_info.code_alignment > 1)
+ {
+ if (exp->X_add_symbol->bsym
+ && exp->X_op_symbol->bsym
+ && exp->X_add_symbol->sy_value.X_op == O_subtract
+ && exp->X_op_symbol->sy_value.X_op == O_constant
+ && ((exp->X_op == O_divide
+ ? exp->X_op_symbol->sy_value.X_add_number
+ : (offsetT) 1 << exp->X_op_symbol->sy_value.X_add_number)
+ == (offsetT) d->cie_info.code_alignment))
+ {
+ /* This is a case we can optimize as well. The expression was
+ not reduced, so we can not finish the optimization until the
+ end of the assembly. We set up a variant frag which we
+ handle later. */
+ frag_var (rs_cfa, 4, 0, d->cie_info.code_alignment << 3,
+ make_expr_symbol (&exp->X_add_symbol->sy_value),
+ d->loc4_fix, (char *) d->loc4_frag);
+ return 1;
+ }
+ }
break;
case state_error:
@@ -459,7 +474,9 @@ eh_frame_estimate_size_before_relax (fragS *frag)
diff = resolve_symbol_value (frag->fr_symbol);
- if (ca > 0 && diff % ca == 0 && diff / ca < 0x40)
+ assert (ca > 0);
+ diff /= ca;
+ if (diff < 0x40)
ret = 0;
else if (diff < 0x100)
ret = 1;
@@ -496,21 +513,21 @@ eh_frame_convert_frag (fragS *frag)
{
offsetT diff;
fragS *loc4_frag;
- int loc4_fix;
+ int loc4_fix, ca;
loc4_frag = (fragS *) frag->fr_opcode;
loc4_fix = (int) frag->fr_offset;
diff = resolve_symbol_value (frag->fr_symbol);
+ ca = frag->fr_subtype >> 3;
+ assert (ca > 0);
+ diff /= ca;
switch (frag->fr_subtype & 7)
{
case 0:
- {
- int ca = frag->fr_subtype >> 3;
- assert (ca > 0 && diff % ca == 0 && diff / ca < 0x40);
- loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | (diff / ca);
- }
+ assert (diff < 0x40);
+ loc4_frag->fr_literal[loc4_fix] = DW_CFA_advance_loc | diff;
break;
case 1: