[jit] Check that code labels are placed exactly once

David Malcolm dmalcolm@redhat.com
Thu Jan 30 22:56:00 GMT 2014


Committed to branch dmalcolm/jit:

gcc/jit/
	* TODO.rst: Label-placement is now checked.

	* internal-api.c (gcc::jit::recording::context::replay_into): Give
	up if any errors occur during the playback.
	(gcc::jit::recording::label::replay_into): Issue an error if the
	label has not yet been placed (at playback time).
	(gcc::jit::recording::place_label::place_label): Move this here
	from internal-api.h.  Issue an error if the label has already
	been placed (at recording time).

	* internal-api.h (gcc::jit::recording::label): Add an
	m_has_been_placed field, and make class place_label a friend so
	it can set it.
	(gcc::jit::recording::label::has_been_placed): New accessor.
	(gcc::jit::recording::place_label::place_label): Move to
	internal-api.c.

	(gcc::jit::playback::context::errors_occurred): Make public, for
	use by gcc::jit::recording::context::replay_into.

gcc/testsuite/
	* jit.dg/test-error-label-already-placed.c: New test case.
	* jit.dg/test-error-unplaced-label.c: New test case.
---
 gcc/jit/ChangeLog.jit                              | 22 ++++++++
 gcc/jit/TODO.rst                                   |  6 ---
 gcc/jit/internal-api.c                             | 25 ++++++++-
 gcc/jit/internal-api.h                             | 22 ++++----
 gcc/testsuite/ChangeLog.jit                        |  5 ++
 .../jit.dg/test-error-label-already-placed.c       | 59 ++++++++++++++++++++++
 gcc/testsuite/jit.dg/test-error-unplaced-label.c   | 50 ++++++++++++++++++
 7 files changed, 173 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/jit.dg/test-error-label-already-placed.c
 create mode 100644 gcc/testsuite/jit.dg/test-error-unplaced-label.c

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index 58e82eb..380d345 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,27 @@
 2014-01-30  David Malcolm  <dmalcolm@redhat.com>
 
+	* TODO.rst: Label-placement is now checked.
+
+	* internal-api.c (gcc::jit::recording::context::replay_into): Give
+	up if any errors occur during the playback.
+	(gcc::jit::recording::label::replay_into): Issue an error if the
+	label has not yet been placed (at playback time).
+	(gcc::jit::recording::place_label::place_label): Move this here
+	from internal-api.h.  Issue an error if the label has already
+	been placed (at recording time).
+
+	* internal-api.h (gcc::jit::recording::label): Add an
+	m_has_been_placed field, and make class place_label a friend so
+	it can set it.
+	(gcc::jit::recording::label::has_been_placed): New accessor.
+	(gcc::jit::recording::place_label::place_label): Move to
+	internal-api.c.
+
+	(gcc::jit::playback::context::errors_occurred): Make public, for
+	use by gcc::jit::recording::context::replay_into.
+
+2014-01-30  David Malcolm  <dmalcolm@redhat.com>
+
 	* internal-api.c (gcc::jit::recording::type::get_pointer):
 	Ensure that repeated calls yield the same type.
 	(gcc::jit::recording::memento_of_get_pointer::
diff --git a/gcc/jit/TODO.rst b/gcc/jit/TODO.rst
index 4f16ae4..5b6e0f7 100644
--- a/gcc/jit/TODO.rst
+++ b/gcc/jit/TODO.rst
@@ -127,18 +127,12 @@ Initial Release
 
     * gcc_jit_function_new_local: type must not be void
 
-    * gcc_jit_function_place_forward_label: must not already have been
-      placed
-
     * gcc_jit_function_add_assignment_op: check the types
 
     * gcc_jit_function_add_conditional: boolval must be of numeric type
 
     * gcc_jit_loop_end: verify that loops are validly nested?
 
-    * verify that all used labels have been placed when attempting to
-      compile
-
 Future milestones
 =================
 * try porting llvmpipe to gcc
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 58495ac..e061ebd 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -131,6 +131,9 @@ recording::context::replay_into (replayer *r)
   if (m_parent_ctxt)
     m_parent_ctxt->replay_into (r);
 
+  if (r->errors_occurred ())
+    return;
+
   /* Replay this context's saved operations into r.  */
   FOR_EACH_VEC_ELT (m_mementos, i, m)
     {
@@ -145,6 +148,9 @@ recording::context::replay_into (replayer *r)
 		(void *)this, (void *)m, m->get_debug_string ());
 
       m->replay_into (r);
+
+      if (r->errors_occurred ())
+	return;
     }
 }
 
@@ -989,8 +995,13 @@ recording::function::make_debug_string ()
 /* gcc::jit::recording::label:: */
 
 void
-recording::label::replay_into (replayer *)
+recording::label::replay_into (replayer *r)
 {
+  if (!m_has_been_placed)
+    {
+      r->add_error ("unplaced label: %s", get_debug_string ());
+      return;
+    }
   set_playback_obj (m_func->playback_function ()
 		      ->new_forward_label (playback_string (m_name)));
 }
@@ -1458,6 +1469,18 @@ recording::conditional::make_debug_string ()
 				m_on_true->get_debug_string ());
 }
 
+recording::place_label::place_label (function *func,
+				     location *loc,
+				     label *lab)
+: statement (func, loc),
+  m_label (lab)
+{
+  if (lab->m_has_been_placed)
+    m_ctxt->add_error ("label %s has already been placed",
+		       lab->get_debug_string ());
+  lab->m_has_been_placed = true;
+}
+
 void
 recording::place_label::replay_into (replayer *)
 {
diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h
index fce6927..5c7f132 100644
--- a/gcc/jit/internal-api.h
+++ b/gcc/jit/internal-api.h
@@ -745,7 +745,8 @@ public:
   label (function *func, string *name)
   : memento (func->m_ctxt),
     m_func (func),
-    m_name (name)
+    m_name (name),
+    m_has_been_placed (false)
   {
   }
 
@@ -757,12 +758,17 @@ public:
     return static_cast <playback::label *> (m_playback_obj);
   }
 
+  bool has_been_placed () { return m_has_been_placed; }
+
 private:
   string * make_debug_string ();
 
 private:
   function *m_func;
   string *m_name;
+  bool m_has_been_placed;
+
+  friend class place_label;
 };
 
 class global : public lvalue
@@ -1230,9 +1236,7 @@ class place_label : public statement
 public:
   place_label (function *func,
 	       location *loc,
-	       label *lab)
-  : statement (func, loc),
-    m_label (lab) {}
+	       label *lab);
 
   void replay_into (replayer *r);
 
@@ -1498,6 +1502,11 @@ public:
   tree
   as_truth_value (tree expr, location *loc);
 
+  bool errors_occurred () const
+  {
+    return m_recording_ctxt->errors_occurred ();
+  }
+
 private:
   void dump_generated_code ();
 
@@ -1506,11 +1515,6 @@ private:
 
   void handle_locations ();
 
-  bool errors_occurred () const
-  {
-    return m_recording_ctxt->errors_occurred ();
-  }
-
 private:
   ::gcc::jit::recording::context *m_recording_ctxt;
 
diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index b1ab250..47dface 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,5 +1,10 @@
 2014-01-30  David Malcolm  <dmalcolm@redhat.com>
 
+	* jit.dg/test-error-label-already-placed.c: New test case.
+	* jit.dg/test-error-unplaced-label.c: New test case.
+
+2014-01-30  David Malcolm  <dmalcolm@redhat.com>
+
 	* jit.dg/test-error-call-with-mismatching-args.c: New test case.
 
 2014-01-30  David Malcolm  <dmalcolm@redhat.com>
diff --git a/gcc/testsuite/jit.dg/test-error-label-already-placed.c b/gcc/testsuite/jit.dg/test-error-label-already-placed.c
new file mode 100644
index 0000000..a20134b
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-label-already-placed.c
@@ -0,0 +1,59 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+
+      int
+      test_fn (void)
+      {
+	foo:
+	   return 0;
+
+	foo:
+	   return 1;
+
+      }
+
+     and verify that the 2nd attempt to place the label fails.
+   */
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+  gcc_jit_function *func =
+    gcc_jit_context_new_function (ctxt, NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  int_type,
+				  "test_fn",
+				  0, NULL, 0);
+
+  /* Create forward label: */
+  gcc_jit_label *label =
+    gcc_jit_function_new_forward_label (func, "foo");
+
+  gcc_jit_function_place_forward_label (func, NULL, label);
+  gcc_jit_function_add_return (func, NULL,
+			       gcc_jit_context_zero (ctxt, int_type));
+
+  /* Erroneous 2nd placement of label: */
+  gcc_jit_function_place_forward_label (func, NULL, label);
+  gcc_jit_function_add_return (func, NULL,
+			       gcc_jit_context_one (ctxt, int_type));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "label foo has already been placed");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-unplaced-label.c b/gcc/testsuite/jit.dg/test-error-unplaced-label.c
new file mode 100644
index 0000000..64073f47
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-unplaced-label.c
@@ -0,0 +1,50 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+
+      void
+      test_fn (void)
+      {
+        goto foo;
+      }
+
+     and verify that an error is issued due to label "foo" not being
+     placed.
+   */
+  gcc_jit_type *void_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+
+  gcc_jit_function *func =
+    gcc_jit_context_new_function (ctxt, NULL,
+				  GCC_JIT_FUNCTION_EXPORTED,
+				  void_type,
+				  "test_fn",
+				  0, NULL, 0);
+
+  /* Create forward label: */
+  gcc_jit_label *unplaced_label =
+    gcc_jit_function_new_forward_label (func, "foo");
+
+  /* Use it (but never place it): */
+  gcc_jit_function_add_jump (func, NULL, unplaced_label);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+		      "unplaced label: foo");
+}
+
-- 
1.7.11.7



More information about the Gcc-patches mailing list