From ec5d0088148d1d6218f5f503d1c8e67a529dfacd Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 30 Jun 2015 20:39:50 +0000 Subject: jit: add switch statements gcc/ChangeLog: * typed-splay-tree.h: New file. gcc/jit/ChangeLog: * docs/cp/topics/functions.rst (Blocks): Add switch statements to list of ways to terminate a block. (gccjit::block::end_with_switch): Add function description. (gccjit::case_): Add class. (gccjit::context::new_case): Add function description. * docs/cp/topics/objects.rst: Add "case_" to class hierarchy. * docs/topics/compatibility.rst (LIBGCCJIT_ABI_3): New. * docs/topics/functions.rst (Blocks): Add switch statements to list of ways to terminate a block. (gcc_jit_block_end_with_switch): Add function description. (gcc_jit_case): Add type. (gcc_jit_context_new_case): Add function description. (gcc_jit_case_as_object): Add function description. * docs/topics/objects.rst: Add gcc_jit_case to class hierarchy. * docs/_build/texinfo/libgccjit.texi: Regenerate. * jit-common.h (gcc::jit::recording::case_): Add forward decl. (gcc::jit::playback::case_): Add forward decl. * jit-playback.c (add_case): New function. (gcc::jit::playback::block::add_switch): New function. * jit-playback.h (gcc::jit::playback::case_): New struct. (gcc::jit::playback::block::get_function): New method. (gcc::jit::playback::block::add_switch): New method. * jit-recording.c: Within namespace gcc::jit... (recording::context::new_case): New method. (recording::function::validate): Update for change to get_successor_blocks. (recording::block::end_with_switch): New method. (recording::block::get_successor_blocks): Update to support an arbitrary number of successor blocks. (recording::block::dump_edges_to_dot): Likewise. (memento_of_new_rvalue_from_const ::get_wide_int): New. (memento_of_new_rvalue_from_const ::get_wide_int): New. (memento_of_new_rvalue_from_const ::get_wide_int): New. (memento_of_new_rvalue_from_const ::get_wide_int): New. (recording::statement::get_successor_blocks): Update to support an arbitrary number of successor blocks. (recording::conditional::get_successor_blocks): Likewise. (recording::jump::get_successor_blocks): Likewise. (recording::return_::get_successor_blocks): Likewise. (recording::case_::write_reproducer): New. (recording::case_::make_debug_string): New. (recording::switch_::switch_): New. (recording::switch_::replay_into): New. (recording::switch_::get_successor_blocks): New. (recording::switch_::make_debug_string): New. (recording::switch_::write_reproducer): New. * jit-recording.h: Within namespace gcc::jit::recording... (context::new_case): New. (rvalue::is_constant): New. (rvalue::get_wide_int): New. (block::end_with_switch): New. (block::get_successor_blocks): Update to support an arbitrary number of successor blocks. (memento_of_new_rvalue_from_const::is_constant): New. (memento_of_new_rvalue_from_const::get_wide_int): New. (statement::get_successor_blocks): Update to support an arbitrary number of successor blocks. (conditional::get_successor_blocks): Likewise. (jump::get_successor_blocks): Likewise. (return_::get_successor_blocks): Likewise. (case_): New subclass of memento. (switch_): New subclass of statement. * libgccjit++.h (gccjit::case_): New subclass of gccjit::object. (gccjit::context::new_case): New method. (gccjit::block::end_with_switch): New method. (gccjit::case_::case): New ctors. (gccjit::case_::get_inner_case): New method. * libgccjit.c: Include "typed-splay-tree.h" (struct gcc_jit_case): New. (gcc_jit_context_new_case): New function. (gcc_jit_case_as_object): New function. (valid_dest_for_switch): New function. (valid_case_for_switch): New function. (class api_call_validator): New class. (class case_range_validator): New class. (case_range_validator::case_range_validator): New. (case_range_validator::validate): New. (case_range_validator::case_compare): New. (case_range_validator::get_wide_int): new. (gcc_jit_block_end_with_switch): New. * libgccjit.h: Add gcc_jit_case to class hierarchy comment. (gcc_jit_case): New typedef. (gcc_jit_context_new_case): New function. (gcc_jit_case_as_object): New function. (gcc_jit_block_end_with_switch): New function. (LIBGCCJIT_HAVE_SWITCH_STATEMENTS): New. * libgccjit.map: Add gcc_jit_block_end_with_switch, gcc_jit_case_as_object and gcc_jit_context_new_case. gcc/testsuite/ChangeLog: * jit.dg/all-non-failing-tests.h: Add test-switch.c. * jit.dg/test-error-gcc_jit_block_end_with_switch-NULL-case.c: New testcase. * jit.dg/test-error-gcc_jit_block_end_with_switch-mismatching-case-type.c: New testcase. * jit.dg/test-error-gcc_jit_block_end_with_switch-overlapping-ranges.c: New testcase. * jit.dg/test-error-gcc_jit_context_new_case-non-const-label.c: New testcase. * jit.dg/test-error-gcc_jit_context_new_case-non-integer-type.c: New testcase. * jit.dg/test-error-gcc_jit_context_new_case-reversed-endpoints.c: New testcase. * jit.dg/test-switch.c: New testcase. * jit.dg/test-switch.cc: New testcase. From-SVN: r225207 --- gcc/jit/docs/cp/topics/functions.rst | 82 +++++++++++++++++++++++++++++++++++- gcc/jit/docs/cp/topics/objects.rst | 1 + 2 files changed, 82 insertions(+), 1 deletion(-) (limited to 'gcc/jit/docs/cp') diff --git a/gcc/jit/docs/cp/topics/functions.rst b/gcc/jit/docs/cp/topics/functions.rst index de3570a..57b6298 100644 --- a/gcc/jit/docs/cp/topics/functions.rst +++ b/gcc/jit/docs/cp/topics/functions.rst @@ -98,7 +98,8 @@ Blocks be the entrypoint. Each basic block that you create within a function must be - terminated, either with a conditional, a jump, or a return. + terminated, either with a conditional, a jump, a return, or + a switch. It's legal to have multiple basic blocks that return within one function. @@ -241,3 +242,82 @@ Statements .. code-block:: c return; + +.. function:: void\ + gccjit::block::end_with_switch (gccjit::rvalue expr,\ + gccjit::block default_block,\ + std::vector cases,\ + gccjit::location loc) + + Terminate a block by adding evalation of an rvalue, then performing + a multiway branch. + + This is roughly equivalent to this C code: + + .. code-block:: c + + switch (expr) + { + default: + goto default_block; + + case C0.min_value ... C0.max_value: + goto C0.dest_block; + + case C1.min_value ... C1.max_value: + goto C1.dest_block; + + ...etc... + + case C[N - 1].min_value ... C[N - 1].max_value: + goto C[N - 1].dest_block; + } + + ``expr`` must be of the same integer type as all of the ``min_value`` + and ``max_value`` within the cases. + + The ranges of the cases must not overlap (or have duplicate + values). + + The API entrypoints relating to switch statements and cases: + + * :func:`gccjit::block::end_with_switch` + + * :func:`gccjit::context::new_case` + + were added in :ref:`LIBGCCJIT_ABI_3`; you can test for their presence + using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS + + .. class:: gccjit::case_ + + A `gccjit::case_` represents a case within a switch statement, and + is created within a particular :class:`gccjit::context` using + :func:`gccjit::context::new_case`. It is a subclass of + :class:`gccjit::object`. + + Each case expresses a multivalued range of integer values. You + can express single-valued cases by passing in the same value for + both `min_value` and `max_value`. + + .. function:: gccjit::case_ *\ + gccjit::context::new_case (gccjit::rvalue min_value,\ + gccjit::rvalue max_value,\ + gccjit::block dest_block) + + Create a new gccjit::case for use in a switch statement. + `min_value` and `max_value` must be constants of an integer type, + which must match that of the expression of the switch statement. + + `dest_block` must be within the same function as the switch + statement. + + Here's an example of creating a switch statement: + + .. literalinclude:: ../../../../testsuite/jit.dg/test-switch.cc + :start-after: /* Quote from here in docs/cp/topics/functions.rst. */ + :end-before: /* Quote up to here in docs/cp/topics/functions.rst. */ + :language: c++ diff --git a/gcc/jit/docs/cp/topics/objects.rst b/gcc/jit/docs/cp/topics/objects.rst index 714b645..8d99bd4 100644 --- a/gcc/jit/docs/cp/topics/objects.rst +++ b/gcc/jit/docs/cp/topics/objects.rst @@ -46,6 +46,7 @@ The C++ class hierarchy within the ``gccjit`` namespace looks like this:: +- rvalue +- lvalue +- param + +- case_ The :class:`gccjit::object` base class has the following operations: -- cgit v1.1