aboutsummaryrefslogtreecommitdiff
path: root/gas/expr.c
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2010-12-02 13:25:13 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2010-12-02 13:25:13 +0000
commitc969da647374bec1548589cd47406e2a12a7800c (patch)
tree70576c6e17cf11e39b7eb45aac6bf109929e911e /gas/expr.c
parent0c98115d15fbd16d6808a5a7718d748072c00dd7 (diff)
downloadfsf-binutils-gdb-c969da647374bec1548589cd47406e2a12a7800c.zip
fsf-binutils-gdb-c969da647374bec1548589cd47406e2a12a7800c.tar.gz
fsf-binutils-gdb-c969da647374bec1548589cd47406e2a12a7800c.tar.bz2
gas/
* symbols.c (S_FORCE_RELOC): Return true for indirect functions even if !strict. * expr.c (operand): Don't convert absolute symbols to constants if S_FORCE_RELOC is true. (expr): Only reduce subtractions between different symbols if S_FORCE_RELOC is false for both of them. * write.c (fixup_segment): Don't remove symbols if S_FORCE_RELOC is true for them, regardless of their segment. gas/testsuite/ * gas/i386/ifunc-2.s, gas/i386/ifunc-2.l: New test. * gas/i386/ifunc-3.s, gas/i386/ifunc-3.d: Likeise. * gas/i386/i386.exp: Run them.
Diffstat (limited to 'gas/expr.c')
-rw-r--r--gas/expr.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/gas/expr.c b/gas/expr.c
index 215b2ba..f818ad3 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -1325,7 +1325,9 @@ operand (expressionS *expressionP, enum expr_mode mode)
/* If we have an absolute symbol or a reg, then we know its
value now. */
segment = S_GET_SEGMENT (symbolP);
- if (mode != expr_defer && segment == absolute_section)
+ if (mode != expr_defer
+ && segment == absolute_section
+ && !S_FORCE_RELOC (symbolP, 0))
{
expressionP->X_op = O_constant;
expressionP->X_add_number = S_GET_VALUE (symbolP);
@@ -1840,7 +1842,9 @@ expr (int rankarg, /* Larger # is higher rank. */
#ifdef md_allow_local_subtract
&& md_allow_local_subtract (resultP, & right, rightseg)
#endif
- && (SEG_NORMAL (rightseg)
+ && ((SEG_NORMAL (rightseg)
+ && !S_FORCE_RELOC (resultP->X_add_symbol, 0)
+ && !S_FORCE_RELOC (right.X_add_symbol, 0))
|| right.X_add_symbol == resultP->X_add_symbol)
&& frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol),
symbol_get_frag (right.X_add_symbol),
@@ -1954,7 +1958,10 @@ expr (int rankarg, /* Larger # is higher rank. */
else if (op_left == O_subtract)
{
resultP->X_add_number -= right.X_add_number;
- if (retval == rightseg && SEG_NORMAL (retval))
+ if (retval == rightseg
+ && SEG_NORMAL (retval)
+ && !S_FORCE_RELOC (resultP->X_add_symbol, 0)
+ && !S_FORCE_RELOC (right.X_add_symbol, 0))
{
retval = absolute_section;
rightseg = absolute_section;