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 <dmalc...@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 <dmalc...@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 <dmalc...@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 <dmalc...@redhat.com> + * jit.dg/test-error-call-with-mismatching-args.c: New test case. 2014-01-30 David Malcolm <dmalc...@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