This is the mail archive of the binutils@sourceware.org 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]
Other format: [Raw text]

Committed: MMIX: fix FAIL: gas/mmix/fb-2


Somewhat non-trivial: the test-case contains a LOC (kind-of like
.org) with an expression complex enough that the section is
indeterminable at the first pass, but not actually changing.
Changing sections using LOC, at least to a section not trivially
determinable seems useless, as mmixal has no actual notion of
sections: the handling of sections is just a mapping of constant
values.  Thus, for such expressions I settled for not changing
sections and verifying that there was no intended section
change, matching the failing test-case.  Which in turn required
actually checking for section changes and emitting appropriate
errors; covered by a new test-case.

Thanks to Alan's fixes in the ld-mmix test-suite earlier, the
MMIX test-results are clean (though only in absence of a target
compiler), so I'll add mmix-knuth-mmixware to my binutils
autotester; tagging along with arm-unknown-eabi,
mipsisa32r2el-unknown-linux-gnu, cris-axis-linux-gnu and
cris-axis-elf.  Yay.

gas:
	* config/tc-mmix.c (loc_asserts): New variable.
	(mmix_greg_internal): Handle expressions not determinable at first
	pass.
	(s_loc): Ditto.  Record expressions where the section isn't
	determinable at the first pass, and assume they don't refer to
	other sections.
	(mmix_md_end): Verify that recorded LOC expressions weren't
	to other sections, else emit error messages.

gas/testsuite:
	* gas/mmix/err-fb-2.s: New test.

Index: config/tc-mmix.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mmix.c,v
retrieving revision 1.36
diff -p -u -r1.36 tc-mmix.c
--- config/tc-mmix.c	17 May 2012 15:13:16 -0000	1.36
+++ config/tc-mmix.c	14 Aug 2012 02:21:55 -0000
@@ -109,6 +109,13 @@ static struct
    expressionS exp;
  } mmix_raw_gregs[MAX_GREGS];

+static struct loc_assert_s
+ {
+   segT old_seg;
+   symbolS *loc_sym;
+   struct loc_assert_s *next;
+ } *loc_asserts = NULL;
+
 /* Fixups for all unique GREG registers.  We store the fixups here in
    md_convert_frag, then we use the array to convert
    BFD_RELOC_MMIX_BASE_PLUS_OFFSET fixups in tc_gen_reloc.  The index is
@@ -1994,10 +2001,11 @@ static void
 mmix_greg_internal (char *label)
 {
   expressionS *expP = &mmix_raw_gregs[n_of_raw_gregs].exp;
+  segT section;

   /* Don't set the section to register contents section before the
      expression has been parsed; it may refer to the current position.  */
-  expression (expP);
+  section = expression (expP);

   /* FIXME: Check that no expression refers to the register contents
      section.  May need to be done in elf64-mmix.c.  */
@@ -2011,6 +2019,24 @@ mmix_greg_internal (char *label)
       expP->X_op_symbol = NULL;
     }

+  if (section == undefined_section)
+    {
+      /* This is an error or a LOC with an expression involving
+	 forward references.  For the expression to be correctly
+	 evaluated, we need to force a proper symbol; gas loses track
+	 of the segment for "local symbols".  */
+      if (expP->X_op == O_add)
+	{
+	  symbol_get_value_expression (expP->X_op_symbol);
+	  symbol_get_value_expression (expP->X_add_symbol);
+	}
+      else
+	{
+	  gas_assert (expP->X_op == O_symbol);
+	  symbol_get_value_expression (expP->X_add_symbol);
+	}
+    }
+
   /* We must handle prefixes here, as we save the labels and expressions
      to be output later.  */
   mmix_raw_gregs[n_of_raw_gregs].label
@@ -3457,6 +3483,7 @@ mmix_md_end (void)
   fragS *fragP;
   symbolS *mainsym;
   asection *regsec;
+  struct loc_assert_s *loc_assert;
   int i;

   /* The first frag of GREG:s going into the register contents section.  */
@@ -3514,6 +3541,29 @@ mmix_md_end (void)
       S_SET_EXTERNAL (mainsym);
     }

+  /* Check that we didn't LOC into the unknown, or rather that when it
+     was unknown, we actually change sections.  */
+  for (loc_assert = loc_asserts;
+       loc_assert != NULL;
+       loc_assert = loc_assert->next)
+    {
+      segT actual_seg;
+
+      resolve_symbol_value (loc_assert->loc_sym);
+      actual_seg = S_GET_SEGMENT (loc_assert->loc_sym);
+      if (actual_seg != loc_assert->old_seg)
+	{
+	  char *fnam;
+	  unsigned int line;
+	  int e_valid = expr_symbol_where (loc_assert->loc_sym, &fnam, &line);
+
+	  gas_assert (e_valid == 1);
+	  as_bad_where (fnam, line,
+			_("LOC to section unknown or indeterminable "
+			  "at first pass"));
+	}
+    }
+
   if (n_of_raw_gregs != 0)
     {
       /* Emit GREGs.  They are collected in order of appearance, but must
@@ -3892,13 +3942,30 @@ s_loc (int ignore ATTRIBUTE_UNUSED)

   if (exp.X_op == O_illegal
       || exp.X_op == O_absent
-      || exp.X_op == O_big
-      || section == undefined_section)
+      || exp.X_op == O_big)
     {
       as_bad (_("invalid LOC expression"));
       return;
     }

+  if (section == undefined_section)
+    {
+      /* This is an error or a LOC with an expression involving
+	 forward references.  For the expression to be correctly
+	 evaluated, we need to force a proper symbol; gas loses track
+	 of the segment for "local symbols".  */
+      if (exp.X_op == O_add)
+	{
+	  symbol_get_value_expression (exp.X_op_symbol);
+	  symbol_get_value_expression (exp.X_add_symbol);
+	}
+      else
+	{
+	  gas_assert (exp.X_op == O_symbol);
+	  symbol_get_value_expression (exp.X_add_symbol);
+	}
+    }
+
   if (section == absolute_section)
     {
       /* Translate a constant into a suitable section.  */
@@ -3970,7 +4037,9 @@ s_loc (int ignore ATTRIBUTE_UNUSED)
 	}
     }

-  if (section != now_seg)
+  /* If we can't deduce the section, it must be the current one.
+     Below, we arrange to assert this.  */
+  if (section != now_seg && section != undefined_section)
     {
       obj_elf_section_change_hook ();
       subseg_set (section, 0);
@@ -3981,16 +4050,41 @@ s_loc (int ignore ATTRIBUTE_UNUSED)

   if (exp.X_op != O_absent)
     {
+      symbolS *esym = NULL;
+
       if (exp.X_op != O_constant && exp.X_op != O_symbol)
 	{
 	  /* Handle complex expressions.  */
-	  sym = make_expr_symbol (&exp);
+	  esym = sym = make_expr_symbol (&exp);
 	  off = 0;
 	}
       else
 	{
 	  sym = exp.X_add_symbol;
 	  off = exp.X_add_number;
+
+	  if (section == undefined_section)
+	    {
+	      /* We need an expr_symbol when tracking sections.  In
+		 order to make this an expr_symbol with file and line
+		 tracked, we have to make the exp non-trivial; not an
+		 O_symbol with .X_add_number == 0.  The constant part
+		 is unused.  */
+	      exp.X_add_number = 1;
+	      esym = make_expr_symbol (&exp);
+	    }
+	}
+
+      /* Track the LOC's where we couldn't deduce the section: assert
+	 that we weren't supposed to change section.  */
+      if (section == undefined_section)
+	{
+	  struct loc_assert_s *next = loc_asserts;
+	  loc_asserts
+	    = (struct loc_assert_s *) xmalloc (sizeof (*loc_asserts));
+	  loc_asserts->next = next;
+	  loc_asserts->old_seg = now_seg;
+	  loc_asserts->loc_sym = esym;
 	}

       p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0);
Index: gas/mmix/err-fb-2.s
===================================================================
RCS file: gas/mmix/err-fb-2.s
diff -N gas/mmix/err-fb-2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/mmix/err-fb-2.s	14 Aug 2012 02:09:11 -0000
@@ -0,0 +1,26 @@
+# { dg-do assemble { target mmix-*-* } }
+# Mostly like fb-2.s, but with LOCs to indeterminable sections
+# *different* to the one LOC'd from.  Two cases are tested: an
+# undefined symbol and a section just indeterminable at the first pass
+# (at the point of the LOC).
+
+1H IS 5
+0H LOC #10
+1H BYTE 1B
+0H LOC 2F+#20+0F 		# { dg-error "indeterminable" "" }
+0H IS 4
+   .section .text.unknown
+2H SWYM
+1H IS 50
+1H GREG 1B+1F
+ SWYM
+1H LDA $30,1B
+1H OCTA 1B,1F
+   LOC undefd 			# { dg-error "unknown" "" }
+1H SWYM
+
+9H IS 42
+ WYDE 9B,9F
+9H IS 9B+1
+ WYDE 9B,9F
+9H IS 9B+1

brgds, H-P


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