[PATCH] macro purging

Jan Beulich JBeulich@novell.com
Mon Apr 18 12:10:00 GMT 2005


(A slightly adjusted version of a previously posted patch, namely to remove
a couple of testsuite failures caused by a few targets issuing multiple error
messages on unrecognized instructions.)

Defining macros with upper-case letters and using them with the lower-case
(or mixed-case) equivalents was no problem, purging macros however worked
with passing in fully lower-case names only.
Also, purging macros did not free the memory the macro was using; this was
particularly problematic because each macro carries a hash table with it,
which is by default about 256k/512k (32-/64-bit hosts) in size (used to be
16k/32k up to 2.16). Defining and purging thousands of (perhaps machine
generated) macros caused the assembler to slow down to the point of becoming
useless (or even fail). Generally it would probably make sense to allow
hash_new to have a size hint parameter, so that this kind of overkill could
be avoided when the hash size can reasonably be expected to never grow this
large.

Built and tested on i686-pc-linux-gnu.

gas/
2005-04-18  Jan Beulich  <jbeulich@novell.com>

	* macro.c (free_token): New, freeing all the memory associated with a
	macro.
	(do_formals): Move initializers to ...
	(define_macro): ... here.
	(delete_macro): Convert passed in name to lower case. Warn when
	purging macro that doesn't exist. Use hash_jam instead of hash_delete.

gas/testsuite/
2005-04-18  Jan Beulich  <jbeulich@novell.com>

	* gas/macros/purge.[ls]: New.
	* gas/macros/macros.exp: Run new test.

--- /home/jbeulich/src/binutils/mainline/2005-04-15/gas/macro.c	2005-03-29 15:57:46.000000000 +0200
+++ 2005-04-15/gas/macro.c	2005-04-15 11:13:59.000000000 +0200
@@ -77,6 +77,7 @@ static int sub_actual (int, sb *, sb *, 
 static const char *macro_expand_body
   (sb *, sb *, formal_entry *, struct hash_control *, int);
 static const char *macro_expand (int, sb *, macro_entry *, sb *);
+static void free_macro(macro_entry *);
 
 #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
 
@@ -471,8 +472,6 @@ do_formals (macro_entry *macro, int idx,
 {
   formal_entry **p = &macro->formals;
 
-  macro->formal_count = 0;
-  macro->formal_hash = hash_new ();
   idx = sb_skip_white (idx, in);
   while (idx < in->len)
     {
@@ -568,6 +567,7 @@ define_macro (int idx, sb *in, sb *label
 
   macro->formal_count = 0;
   macro->formals = 0;
+  macro->formal_hash = hash_new ();
 
   idx = sb_skip_white (idx, in);
   if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
@@ -1142,12 +1142,52 @@ check_macro (const char *line, sb *expan
   return 1;
 }
 
+/* Free the memory allocated to a macro.  */
+
+static void
+free_macro(macro_entry *macro)
+{
+  formal_entry *formal;
+
+  for (formal = macro->formals; formal; )
+    {
+      void *ptr;
+
+      sb_kill (&formal->name);
+      sb_kill (&formal->def);
+      sb_kill (&formal->actual);
+      ptr = formal;
+      formal = formal->next;
+      free (ptr);
+    }
+  hash_die (macro->formal_hash);
+  sb_kill (&macro->sub);
+  free (macro);
+}
+
 /* Delete a macro.  */
 
 void
 delete_macro (const char *name)
 {
-  hash_delete (macro_hash, name);
+  char *copy;
+  size_t i, len;
+  macro_entry *macro;
+
+  len = strlen (name);
+  copy = (char *) alloca (len + 1);
+  for (i = 0; i < len; ++i)
+    copy[i] = TOLOWER (name[i]);
+  copy[i] = '\0';
+
+  /* Since hash_delete doesn't free memory, just clear out the entry.  */
+  if ((macro = hash_find (macro_hash, copy)) != NULL)
+    {
+      hash_jam (macro_hash, copy, NULL);
+      free_macro (macro);
+    }
+  else
+    as_warn (_("Attempt to purge non-existant macro `%s'"), copy);
 }
 
 /* Handle the MRI IRP and IRPC pseudo-ops.  These are handled as a
--- /home/jbeulich/src/binutils/mainline/2005-04-15/gas/testsuite/gas/macros/macros.exp	2005-03-29 15:57:46.000000000 +0200
+++ 2005-04-15/gas/testsuite/gas/macros/macros.exp	2005-04-15 11:15:34.000000000 +0200
@@ -78,4 +78,5 @@ case $target_triplet in {
     default { run_list_test dot "-alm" }
 }
 run_list_test end ""
+run_list_test purge ""
 run_list_test redef ""
--- /home/jbeulich/src/binutils/mainline/2005-04-15/gas/testsuite/gas/macros/purge.l	1970-01-01 01:00:00.000000000 +0100
+++ 2005-04-15/gas/testsuite/gas/macros/purge.l	2005-04-14 12:02:07.000000000 +0200
@@ -0,0 +1,7 @@
+.*: Assembler messages:
+.*:11: Error: .*
+.*:12: Error: .*
+.*:13: Error: .*
+.*:14: Error: .*
+.*:15: Warning: .*
+.*:16: Warning: .*
--- /home/jbeulich/src/binutils/mainline/2005-04-15/gas/testsuite/gas/macros/purge.s	1970-01-01 01:00:00.000000000 +0100
+++ 2005-04-15/gas/testsuite/gas/macros/purge.s	2005-04-15 09:16:42.000000000 +0200
@@ -0,0 +1,41 @@
+ .macro MACRO1
+ .endm
+ .macro macro2
+ .endm
+	MACRO1
+	MACRO2
+	macro1
+	macro2
+ .purgem MACRO1
+ .purgem macro2
+	MACRO1
+	MACRO2
+	macro1
+	macro2
+ .purgem macro1
+ .purgem MACRO2
+ .macro macro1
+ .endm
+ .macro MACRO2
+ .endm
+	MACRO1
+	MACRO2
+	macro1
+	macro2
+ .purgem MACRO1
+ .purgem macro2
+
+ .irpc a,ABCDEFGHIJKLMNOPQRSTUVWXYZ
+  .irpc b,ABCDEFGHIJKLMNOPQRSTUVWXYZ
+   .irpc c,ABCDEFGHIJKLMNOPQRSTUVWXYZ
+    .irpc d,ABCDEFGHIJKLMNOPQRSTUVWXYZ
+     .macro \a\b\c\d arg1=0, arg2=0
+      .if \arg1 + \arg2
+       .purgem \a\b\c\d
+      .endif
+     .endm
+	\a\b\c\d 1, 2
+    .endr
+   .endr
+  .endr
+ .endr

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: binutils-mainline-macro-purge.patch
URL: <https://sourceware.org/pipermail/binutils/attachments/20050418/9dec6b06/attachment.ksh>


More information about the Binutils mailing list