[PATCH] allow nested .bundle_lock

Roland McGrath mcgrathr@google.com
Thu May 17 20:01:00 GMT 2012


I came across a use case for letting .bundle_lock/.bundle_unlock pairs nest.

Ok for trunk?


Thanks,
Roland


gas/
2012-05-17  Roland McGrath  <mcgrathr@google.com>

	* read.c [HANDLE_BUNDLE] (bundle_lock_depth): New variable.
	(read_a_source_file) [HANDLE_BUNDLE]: Reset it.
	[HANDLE_BUNDLE] (s_bundle_lock, s_bundle_unlock): Allow nested
	pairs.

gas/testsuite/
2012-05-17  Roland McGrath  <mcgrathr@google.com>

	* gas/i386/bundle-bad.s: Remove nested .bundle_lock case.
	* gas/i386/bundle-bad.l: Remove expected error line.
	* gas/i386/bundle-lock.s: Add nested .bundle_lock case.
	* gas/i386/bundle-lock.d: Update expectations.

diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index 694c806..6608958 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -4346,9 +4346,12 @@ first instruction of the sequence so that the whole sequence starts on an
 aligned bundle boundary.  It's an error if the sequence is longer than the
 bundle size.
 
-Bundle-locked sequences do not nest.  It's an error if two
-@code{.bundle_lock} directives appear without an intervening
-@code{.bundle_unlock} directive.
+For convenience when using @code{.bundle_lock} and @code{.bundle_unlock}
+inside assembler macros (@pxref{Macro}), bundle-locked sequences may be
+nested.  That is, a second @code{.bundle_lock} directive before the next
+@code{.bundle_unlock} directive has no effect except that it must be
+matched by another closing @code{.bundle_unlock} so that there is the
+same number of @code{.bundle_lock} and @code{.bundle_unlock} directives.
 
 @node Byte
 @section @code{.byte @var{expressions}}
diff --git a/gas/read.c b/gas/read.c
index 4ff3313..49ba551 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -232,6 +232,10 @@ static unsigned int bundle_align_p2;
    we are expecting to see .bundle_unlock.  */
 static fragS *bundle_lock_frag;
 static frchainS *bundle_lock_frchain;
+
+/* This is incremented by .bundle_lock and decremented by .bundle_unlock,
+   to allow nesting.  */
+static unsigned int bundle_lock_depth;
 #endif
 
 static void do_s_func (int end_p, const char *default_prefix);
@@ -1287,6 +1291,7 @@ read_a_source_file (char *name)
 		    _(".bundle_lock with no matching .bundle_unlock"));
       bundle_lock_frag = NULL;
       bundle_lock_frchain = NULL;
+      bundle_lock_depth = 0;
     }
 #endif
 
@@ -6062,14 +6067,12 @@ s_bundle_lock (int arg ATTRIBUTE_UNUSED)
       return;
     }
 
-  if (bundle_lock_frag != NULL)
+  if (bundle_lock_depth == 0)
     {
-      as_bad (_("second .bundle_lock without .bundle_unlock"));
-      return;
+      bundle_lock_frchain = frchain_now;
+      bundle_lock_frag = start_bundle ();
     }
-
-  bundle_lock_frchain = frchain_now;
-  bundle_lock_frag = start_bundle ();
+  ++bundle_lock_depth;
 }
 
 void
@@ -6087,6 +6090,10 @@ s_bundle_unlock (int arg ATTRIBUTE_UNUSED)
 
   gas_assert (bundle_align_p2 > 0);
 
+  gas_assert (bundle_lock_depth > 0);
+  if (--bundle_lock_depth > 0)
+    return;
+
   size = pending_bundle_size (bundle_lock_frag);
 
   if (size > (1U << bundle_align_p2))
diff --git a/gas/testsuite/gas/i386/bundle-bad.l b/gas/testsuite/gas/i386/bundle-bad.l
index ece5d7e..dd6a793 100644
--- a/gas/testsuite/gas/i386/bundle-bad.l
+++ b/gas/testsuite/gas/i386/bundle-bad.l
@@ -7,5 +7,4 @@
 [^:]*:26:.*cannot change section or subsection inside \.bundle_lock
 [^:]*:31:.*cannot change \.bundle_align_mode inside \.bundle_lock
 [^:]*:36:.*\.bundle_unlock without preceding \.bundle_lock
-[^:]*:41:.*second \.bundle_lock without \.bundle_unlock
-[^:]*:46:.*\.bundle_lock with no matching \.bundle_unlock
+[^:]*:39:.*\.bundle_lock with no matching \.bundle_unlock
diff --git a/gas/testsuite/gas/i386/bundle-bad.s b/gas/testsuite/gas/i386/bundle-bad.s
index 0974d30..0234ae5 100644
--- a/gas/testsuite/gas/i386/bundle-bad.s
+++ b/gas/testsuite/gas/i386/bundle-bad.s
@@ -35,13 +35,6 @@
 	hlt
 	.bundle_unlock
 
-	# Nested .bundle_lock.
-	.bundle_lock
-	clc
-	.bundle_lock
-	cld
-	.bundle_unlock
-
 	# End of input with dangling .bundle_lock.
 	.bundle_lock
 	hlt
diff --git a/gas/testsuite/gas/i386/bundle-lock.d b/gas/testsuite/gas/i386/bundle-lock.d
index afca500..86547e0 100644
--- a/gas/testsuite/gas/i386/bundle-lock.d
+++ b/gas/testsuite/gas/i386/bundle-lock.d
@@ -3052,5 +3052,9 @@ Disassembly of section \.text:
 #...
  *bde0:\s+(f4\s+hlt|f8\s+clc)\s*
 #...
- *be00:\s+f4\s+hlt\s*
+ *be00:\s+f8\s+clc\s*
+ *be01:\s+fc\s+cld\s*
+ *be02:\s+f8\s+clc\s*
+#...
+ *be20:\s+f4\s+hlt\s*
 #pass
diff --git a/gas/testsuite/gas/i386/bundle-lock.s b/gas/testsuite/gas/i386/bundle-lock.s
index 6fca9c8..af52e99 100644
--- a/gas/testsuite/gas/i386/bundle-lock.s
+++ b/gas/testsuite/gas/i386/bundle-lock.s
@@ -90,4 +90,14 @@ sequence_\size\()_offset_\offset\():
 	test_offsets 32
 
 .p2align 5
+	# Nested .bundle_lock.
+	.bundle_lock
+	clc
+	.bundle_lock
+	cld
+	.bundle_unlock
+	clc
+	.bundle_unlock
+
+.p2align 5
 	hlt



More information about the Binutils mailing list