This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Teach .org to handle complex expressions
- To: binutils at sourceware dot cygnus dot com
- Subject: Teach .org to handle complex expressions
- From: Alan Modra <alan at linuxcare dot com dot au>
- Date: Tue, 13 Mar 2001 23:48:30 +1100 (EST)
This patch corrects a couple of places in the assembler where frag_var is
passed some_expression->X_add_symbol and some_expression->X_add_number.
That's fine for simple expressions involving a constant and possibly a
symbol, but more complex expressions lose. Something like
x1:
some code
x2:
.org (x2 - x1) + . # leave space to copy <some code>
won't work if x2 - x1 cannot be evaluated immediately, for example when
<some code> contains relaxable instructions, or even, due to a quirk
in the assembler, when listings are turned on. Part of the expression
(X_op_symbol and the operator) will be dropped, and in the above case,
you'll be left with ".org (x2 - x1)".
Thus:
gas/ChangeLog
* read.c (do_org): Handle complex expressions.
* cgen.c (gas_cgen_finish_insn): Likewise.
OK, it turns out that this patch is not sufficient to make the .org
example work for relaxable code. For the rest of the solution, see
http://sources.redhat.com/ml/binutils/2001-03/msg00131.html
Note also that there are a number of gas/config/ target files with
similar suspicious calls to frag_var that should probably be fixed.
If no one screams, I'll check this in tomorrow.
Alan Modra
--
Linuxcare
Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.33
diff -u -p -r1.33 read.c
--- read.c 2001/03/08 23:24:22 1.33
+++ read.c 2001/03/13 11:00:19
@@ -2379,9 +2379,17 @@ do_org (segment, exp, fill)
else
{
char *p;
+ symbolS *sym = exp->X_add_symbol;
+ offsetT off = exp->X_add_number * OCTETS_PER_BYTE;
- p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol,
- exp->X_add_number * OCTETS_PER_BYTE, (char *) NULL);
+ if (exp->X_op != O_constant && exp->X_op != O_symbol)
+ {
+ /* Handle complex expressions. */
+ sym = make_expr_symbol (exp);
+ off = 0;
+ }
+
+ p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0);
*p = fill;
}
}
Index: gas/cgen.c
===================================================================
RCS file: /cvs/src/src/gas/cgen.c,v
retrieving revision 1.10
diff -u -p -r1.10 cgen.c
--- cgen.c 2001/03/08 23:24:22 1.10
+++ cgen.c 2001/03/13 11:00:20
@@ -398,6 +398,9 @@ gas_cgen_finish_insn (insn, buf, length,
{
int max_len;
fragS *old_frag;
+ expressionS *exp;
+ symbolS *sym;
+ offsetT off;
#ifdef TC_CGEN_MAX_RELAX
max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
@@ -414,14 +417,24 @@ gas_cgen_finish_insn (insn, buf, length,
/* Create a relaxable fragment for this instruction. */
old_frag = frag_now;
+ exp = &fixups[relax_operand].exp;
+ sym = exp->X_add_symbol;
+ off = exp->X_add_number;
+ if (exp->X_op != O_constant && exp->X_op != O_symbol)
+ {
+ /* Handle complex expressions. */
+ sym = make_expr_symbol (exp);
+ off = 0;
+ }
+
frag_var (rs_machine_dependent,
max_len - byte_len /* max chars */,
0 /* variable part already allocated */,
/* FIXME: When we machine generate the relax table,
machine generate a macro to compute subtype. */
1 /* subtype */,
- fixups[relax_operand].exp.X_add_symbol,
- fixups[relax_operand].exp.X_add_number,
+ sym,
+ off,
f);
/* Record the operand number with the fragment so md_convert_frag