This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Teach .org to handle complex expressions


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]