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]
Other format: [Raw text]

[PATCH] ia64: make .proc/.endp match assembly language spec


This finally makes .proc/.endp spec conformant in that the arguments of .proc
get recorded and those of .endp ignored (except that we issue warnings on
inconsistencies in order to aid the programmer in writing clean code).

Built and tested on ia64-unknown-linux-gnu.

Jan

gas/
2005-05-23  Jan Beulich  <jbeulich@novell.com>

	* config/tc-ia64.c (struct proc_pending): New.
	(unwind): Replace proc_start with proc_pending.
	(unwind_diagnostic): Check unwind.proc_pending.sym.
	(dot_proc): Replace unwind.proc_start with unwind.proc_pending.sym.
	Check if previous proc not closed. Record all entry points.
	(dot_endp): Replace unwind.proc_start with unwind.proc_pending.sym.
	Set symbol sizes for entry points recorded in dot_proc. Check
	arguments for consistency with respective .proc's.
	(md_assemble): Replace unwind.proc_start with
	unwind.proc_pending.sym.

gas/testsuite/
2005-05-23  Jan Beulich  <jbeulich@novell.com>

	* gas/ia64/proc.l: Adjust.

--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/config/tc-ia64.c	2005-05-09 08:31:38.000000000 +0200
+++ 2005-05-18/gas/config/tc-ia64.c	2005-05-23 17:51:06.561913649 +0200
@@ -711,6 +711,12 @@ typedef struct label_prologue_count
   unsigned int prologue_count;
 } label_prologue_count;
 
+typedef struct proc_pending
+{
+  symbolS *sym;
+  struct proc_pending *next;
+} proc_pending;
+
 static struct
 {
   /* Maintain a list of unwind entries for the current function.  */
@@ -722,7 +728,7 @@ static struct
   unw_rec_list *current_entry;
 
   /* These are used to create the unwind table entry for this function.  */
-  symbolS *proc_start;
+  proc_pending proc_pending;
   symbolS *info;		/* pointer to unwind info */
   symbolS *personality_routine;
   segT saved_text_seg;
@@ -3132,7 +3138,7 @@ unwind_diagnostic (const char * region, 
 static int
 in_procedure (const char *directive)
 {
-  if (unwind.proc_start
+  if (unwind.proc_pending.sym
       && (!unwind.saved_text_seg || strcmp (directive, "endp") == 0))
     return 1;
   return unwind_diagnostic ("procedure", directive);
@@ -4269,8 +4275,22 @@ dot_proc (dummy)
 {
   char *name, *p, c;
   symbolS *sym;
+  proc_pending *pending, *last_pending;
+
+  if (unwind.proc_pending.sym)
+    {
+      (md.unwind_check == unwind_check_warning
+       ? as_warn
+       : as_bad) ("Missing .endp after previous .proc");
+      while (unwind.proc_pending.next)
+	{
+	  pending = unwind.proc_pending.next;
+	  unwind.proc_pending.next = pending->next;
+	  free (pending);
+	}
+    }
+  last_pending = NULL;
 
-  unwind.proc_start = 0;
   /* Parse names of main and alternate entry points and mark them as
      function symbols:  */
   while (1)
@@ -4286,9 +4306,16 @@ dot_proc (dummy)
 	  sym = symbol_find_or_make (name);
 	  if (S_IS_DEFINED (sym))
 	    as_bad ("`%s' was already defined", name);
-	  else if (unwind.proc_start == 0)
+	  else if (!last_pending)
+	    {
+	      unwind.proc_pending.sym = sym;
+	      last_pending = &unwind.proc_pending;
+	    }
+	  else
 	    {
-	      unwind.proc_start = sym;
+	      pending = xmalloc (sizeof (*pending));
+	      pending->sym = sym;
+	      last_pending = last_pending->next = pending;
 	    }
 	  symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
 	}
@@ -4298,8 +4325,12 @@ dot_proc (dummy)
 	break;
       ++input_line_pointer;
     }
-  if (unwind.proc_start == 0)
-    unwind.proc_start = expr_build_dot ();
+  if (!last_pending)
+    {
+      unwind.proc_pending.sym = expr_build_dot ();
+      last_pending = &unwind.proc_pending;
+    }
+  last_pending->next = NULL;
   demand_empty_rest_of_line ();
   ia64_do_align (16);
 
@@ -4392,8 +4423,7 @@ dot_endp (dummy)
   long where;
   segT saved_seg;
   subsegT saved_subseg;
-  char *name, *default_name, *p, c;
-  symbolS *sym;
+  proc_pending *pending;
   int unwind_check = md.unwind_check;
 
   md.unwind_check = unwind_check_error;
@@ -4442,13 +4472,13 @@ dot_endp (dummy)
       e.X_op = O_pseudo_fixup;
       e.X_op_symbol = pseudo_func[FUNC_SEG_RELATIVE].u.sym;
       e.X_add_number = 0;
-      if (!S_IS_LOCAL (unwind.proc_start)
-	  && S_IS_DEFINED (unwind.proc_start))
-	e.X_add_symbol = symbol_temp_new (S_GET_SEGMENT (unwind.proc_start),
-					  S_GET_VALUE (unwind.proc_start),
-					  symbol_get_frag (unwind.proc_start));
+      if (!S_IS_LOCAL (unwind.proc_pending.sym)
+	  && S_IS_DEFINED (unwind.proc_pending.sym))
+	e.X_add_symbol = symbol_temp_new (S_GET_SEGMENT (unwind.proc_pending.sym),
+					  S_GET_VALUE (unwind.proc_pending.sym),
+					  symbol_get_frag (unwind.proc_pending.sym));
       else
-	e.X_add_symbol = unwind.proc_start;
+	e.X_add_symbol = unwind.proc_pending.sym;
       ia64_cons_fix_new (frag_now, where, bytes_per_address, &e);
 
       e.X_op = O_pseudo_fixup;
@@ -4468,62 +4504,22 @@ dot_endp (dummy)
     }
   subseg_set (saved_seg, saved_subseg);
 
-  if (unwind.proc_start)
-    default_name = (char *) S_GET_NAME (unwind.proc_start);
-  else
-    default_name = NULL;
-
-  /* Parse names of main and alternate entry points and set symbol sizes.  */
-  while (1)
-    {
-      SKIP_WHITESPACE ();
-      name = input_line_pointer;
-      c = get_symbol_end ();
-      p = input_line_pointer;
-      if (!*name)
-	{
-	  if (md.unwind_check == unwind_check_warning)
+  /* Set symbol sizes.  */
+  pending = &unwind.proc_pending;
+  if (S_GET_NAME (pending->sym))
+    {
+      do
+	{
+	  symbolS *sym = pending->sym;
+
+	  if (!S_IS_DEFINED (sym))
+	    as_bad ("`%s' was not defined within procedure", S_GET_NAME (sym));
+	  else if (S_GET_SIZE (sym) == 0
+		   && symbol_get_obj (sym)->size == NULL)
 	    {
-	      if (default_name)
-		{
-		  as_warn ("Empty argument of .endp. Use the default name `%s'",
-			   default_name);
-		  name = default_name;
-		}
-	      else
-		as_warn ("Empty argument of .endp");
-	    }
-	  else
-	    as_bad ("Empty argument of .endp");
-	}
-      if (*name)
-	{
-	  sym = symbol_find (name);
-	  if (!sym
-	      && md.unwind_check == unwind_check_warning
-	      && default_name
-	      && default_name != name)
-	    {
-	      /* We have a bad name. Try the default one if needed.  */
-	      as_warn ("`%s' was not defined within procedure. Use the default name `%s'",
-		       name, default_name);
-	      name = default_name;
-	      sym = symbol_find (name);
-	    }
-	  if (!sym || !S_IS_DEFINED (sym))
-	    as_bad ("`%s' was not defined within procedure", name);
-	  else if (unwind.proc_start
-	      && (symbol_get_bfdsym (sym)->flags & BSF_FUNCTION)
-	      && S_GET_SIZE (sym) == 0 && symbol_get_obj (sym)->size == NULL)
-	    {
-	      fragS *fr = symbol_get_frag (unwind.proc_start);
 	      fragS *frag = symbol_get_frag (sym);
 
-	      /* Check whether the function label is at or beyond last
-		 .proc directive.  */
-	      while (fr && fr != frag)
-		fr = fr->fr_next;
-	      if (fr)
+	      if (frag)
 		{
 		  if (frag == frag_now && SEG_NORMAL (now_seg))
 		    S_SET_SIZE (sym, frag_now_fix () - S_GET_VALUE (sym));
@@ -4540,6 +4536,36 @@ dot_endp (dummy)
 		    }
 		}
 	    }
+	} while ((pending = pending->next) != NULL);
+    }
+
+  /* Parse names of main and alternate entry points.  */
+  while (1)
+    {
+      char *name, *p, c;
+
+      SKIP_WHITESPACE ();
+      name = input_line_pointer;
+      c = get_symbol_end ();
+      p = input_line_pointer;
+      if (!*name)
+	(md.unwind_check == unwind_check_warning
+	 ? as_warn
+	 : as_bad) ("Empty argument of .endp");
+      else
+	{
+	  symbolS *sym = symbol_find (name);
+
+	  for (pending = &unwind.proc_pending; pending; pending = pending->next)
+	    {
+	      if (sym == pending->sym)
+		{
+		  pending->sym = NULL;
+		  break;
+		}
+	    }
+	  if (!sym || !pending)
+	    as_warn ("`%s' was not specified with previous .proc", name);
 	}
       *p = c;
       SKIP_WHITESPACE ();
@@ -4548,7 +4574,21 @@ dot_endp (dummy)
       ++input_line_pointer;
     }
   demand_empty_rest_of_line ();
-  unwind.proc_start = unwind.info = 0;
+
+  /* Deliberately only checking for the main entry point here; the
+     language spec even says all arguments to .endp are ignored.  */
+  if (unwind.proc_pending.sym
+      && S_GET_NAME (unwind.proc_pending.sym)
+      && strcmp (S_GET_NAME (unwind.proc_pending.sym), FAKE_LABEL_NAME))
+    as_warn ("`%s' should be an operand to this .endp",
+	     S_GET_NAME (unwind.proc_pending.sym));
+  while (unwind.proc_pending.next)
+    {
+      pending = unwind.proc_pending.next;
+      unwind.proc_pending.next = pending->next;
+      free (pending);
+    }
+  unwind.proc_pending.sym = unwind.info = NULL;
 }
 
 static void
@@ -10772,7 +10812,7 @@ md_assemble (str)
       CURR_SLOT.unwind_record = unwind.current_entry;
       unwind.current_entry = NULL;
     }
-  if (unwind.proc_start && S_IS_DEFINED (unwind.proc_start))
+  if (unwind.proc_pending.sym && S_IS_DEFINED (unwind.proc_pending.sym))
     unwind.insn = 1;
 
   /* Check for dependency violations.  */
--- /home/jbeulich/src/binutils/mainline/2005-05-18/gas/testsuite/gas/ia64/proc.l	2005-01-28 10:23:04.000000000 +0100
+++ 2005-05-18/gas/testsuite/gas/ia64/proc.l	2005-05-23 17:47:24.517971056 +0200
@@ -1,5 +1,6 @@
 .*: Assembler messages:
 .*:4: Error: .* already defined.*
 .*:7: Error: .* not defined.*
+.*:7: Warning: .* not specified.*
 .*:12: Error: Empty argument of .proc
 .*:13: Error: Empty argument of .endp

Attachment: binutils-mainline-ia64-proc-endp.patch
Description: Text document


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