gas: fold symbol table entries generated for .startof.() / .sizeof.()

Message ID 934d1435-82f7-8bf7-f34c-c9e517531f84@suse.com
State New
Headers show
Series
  • gas: fold symbol table entries generated for .startof.() / .sizeof.()
Related show

Commit Message

Jan Beulich via Binutils June 10, 2021, 11:35 a.m.
When the same such construct is used multiple times in a source file,
there's still no need to emit a separate symbol each time. Under the
assumption that there won't be many of these, use a simple array
lookup method to record previously used symbols.

gas/
2021-06-XX  Jan Beulich  <jbeulich@suse.com>

	* expr.c (symbol_lookup_or_make): New.
	(operand): Use it.
	* testsuite/gas/elf/startof.s, testsuite/gas/elf/startof.d: New.
	* testsuite/gas/elf/elf.exp: Run new test.

Comments

Jan Beulich via Binutils June 17, 2021, 1:41 p.m. | #1
Hi Jan,

> gas/

> 2021-06-XX  Jan Beulich  <jbeulich@suse.com>

> 

> 	* expr.c (symbol_lookup_or_make): New.

> 	(operand): Use it.

> 	* testsuite/gas/elf/startof.s, testsuite/gas/elf/startof.d: New.

> 	* testsuite/gas/elf/elf.exp: Run new test.


Approved - please apply.

Cheers
   Nick
+

Patch

--- a/gas/expr.c
+++ b/gas/expr.c
@@ -127,6 +127,52 @@  expr_symbol_where (symbolS *sym, const c
 
   return 0;
 }
+
+/* Look up a previously used .startof. / .sizeof. symbol, or make a fresh
+   one.  */
+
+static symbolS *
+symbol_lookup_or_make (const char *name, bool start)
+{
+  static symbolS **seen[2];
+  static unsigned int nr_seen[2];
+  char *buf = concat (start ? ".startof." : ".sizeof.", name, NULL);
+  symbolS *symbolP;
+  unsigned int i;
+
+  for (i = 0; i < nr_seen[start]; ++i)
+    {
+    symbolP = seen[start][i];
+
+    if (! symbolP)
+      break;
+
+    name = S_GET_NAME (symbolP);
+    if ((symbols_case_sensitive
+	 ? strcasecmp (buf, name)
+	 : strcmp (buf, name)) == 0)
+      {
+	free (buf);
+	return symbolP;
+      }
+    }
+
+  symbolP = symbol_make (buf);
+  free (buf);
+
+  if (i >= nr_seen[start])
+    {
+      unsigned int nr = (i + 1) * 2;
+
+      seen[start] = XRESIZEVEC (symbolS *, seen[start], nr);
+      nr_seen[start] = nr;
+      memset (&seen[start][i + 1], 0, (nr - i - 1) * sizeof(seen[0][0]));
+    }
+
+  seen[start][i] = symbolP;
+
+  return symbolP;
+}
 
 /* Utilities for building expressions.
    Since complex expressions are recorded as symbols for use in other
@@ -1159,8 +1205,6 @@  operand (expressionS *expressionP, enum
 	    as_bad (_("syntax error in .startof. or .sizeof."));
 	  else
 	    {
-	      char *buf;
-
 	      ++input_line_pointer;
 	      SKIP_WHITESPACE ();
 	      c = get_symbol_name (& name);
@@ -1175,13 +1219,8 @@  operand (expressionS *expressionP, enum
 		  break;
 		}
 
-	      buf = concat (start ? ".startof." : ".sizeof.", name,
-			    (char *) NULL);
-	      symbolP = symbol_make (buf);
-	      free (buf);
-
 	      expressionP->X_op = O_symbol;
-	      expressionP->X_add_symbol = symbolP;
+	      expressionP->X_add_symbol = symbol_lookup_or_make (name, start);
 	      expressionP->X_add_number = 0;
 
 	      *input_line_pointer = c;
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -309,6 +309,7 @@  if { [is_elf_format] } then {
     run_dump_test "pr27355"
 
     run_dump_test "syms"
+    run_dump_test "startof"
 
     run_dump_test "missing-build-notes"
     
--- /dev/null
+++ b/gas/testsuite/gas/elf/startof.d
@@ -0,0 +1,10 @@ 
+#name: .startof. / .sizeof.
+#readelf: -s
+
+Symbol table .*
+   Num: .*
+     0: 0+ .*
+#...
+     [1-8]: 0+ .* UND \.startof\.\.text
+     [2-9]: 0+ .* UND \.sizeof\.\.text
+#pass
--- /dev/null
+++ b/gas/testsuite/gas/elf/startof.s
@@ -0,0 +1,6 @@ 
+	.data
+	.dc.a	.startof.(.text)
+	.dc.a	.sizeof.(.text)
+	.dc.a	0
+	.dc.a	.sizeof.(.text)
+	.dc.a	.startof.(.text)