.. Copyright (C) 2014-2022 Free Software Foundation, Inc. Originally contributed by David Malcolm This is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . .. default-domain:: cpp Creating and using functions ============================ Params ------ .. class:: gccjit::param A `gccjit::param` represents a parameter to a function. .. function:: gccjit::param \ gccjit::context::new_param (gccjit::type type,\ const char *name, \ gccjit::location loc) In preparation for creating a function, create a new parameter of the given type and name. :class:`gccjit::param` is a subclass of :class:`gccjit::lvalue` (and thus of :class:`gccjit::rvalue` and :class:`gccjit::object`). It is a thin wrapper around the C API's :c:expr:`gcc_jit_param *`. Functions --------- .. class:: gccjit::function A `gccjit::function` represents a function - either one that we're creating ourselves, or one that we're referencing. .. function:: gccjit::function \ gccjit::context::new_function (enum gcc_jit_function_kind,\ gccjit::type return_type, \ const char *name, \ std::vector ¶ms, \ int is_variadic, \ gccjit::location loc) Create a gcc_jit_function with the given name and parameters. Parameters "is_variadic" and "loc" are optional. This is a wrapper around the C API's :c:func:`gcc_jit_context_new_function`. .. function:: gccjit::function \ gccjit::context::get_builtin_function (const char *name) This is a wrapper around the C API's :c:func:`gcc_jit_context_get_builtin_function`. .. function:: gccjit::param \ gccjit::function::get_param (int index) const Get the param of the given index (0-based). .. function:: void \ gccjit::function::dump_to_dot (const char *path) Emit the function in graphviz format to the given path. .. function:: gccjit::lvalue \ gccjit::function::new_local (gccjit::type type,\ const char *name, \ gccjit::location loc) Create a new local variable within the function, of the given type and name. Blocks ------ .. class:: gccjit::block A `gccjit::block` represents a basic block within a function i.e. a sequence of statements with a single entry point and a single exit point. :class:`gccjit::block` is a subclass of :class:`gccjit::object`. The first basic block that you create within a function will be the entrypoint. Each basic block that you create within a function must be 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. .. function:: gccjit::block \ gccjit::function::new_block (const char *name) Create a basic block of the given name. The name may be NULL, but providing meaningful names is often helpful when debugging: it may show up in dumps of the internal representation, and in error messages. Statements ---------- .. function:: void\ gccjit::block::add_eval (gccjit::rvalue rvalue, \ gccjit::location loc) Add evaluation of an rvalue, discarding the result (e.g. a function call that "returns" void). This is equivalent to this C code: .. code-block:: c (void)expression; .. function:: void\ gccjit::block::add_assignment (gccjit::lvalue lvalue, \ gccjit::rvalue rvalue, \ gccjit::location loc) Add evaluation of an rvalue, assigning the result to the given lvalue. This is roughly equivalent to this C code: .. code-block:: c lvalue = rvalue; .. function:: void\ gccjit::block::add_assignment_op (gccjit::lvalue lvalue, \ enum gcc_jit_binary_op, \ gccjit::rvalue rvalue, \ gccjit::location loc) Add evaluation of an rvalue, using the result to modify an lvalue. This is analogous to "+=" and friends: .. code-block:: c lvalue += rvalue; lvalue *= rvalue; lvalue /= rvalue; etc. For example: .. code-block:: c /* "i++" */ loop_body.add_assignment_op ( i, GCC_JIT_BINARY_OP_PLUS, ctxt.one (int_type)); .. function:: void\ gccjit::block::add_comment (const char *text, \ gccjit::location loc) Add a no-op textual comment to the internal representation of the code. It will be optimized away, but will be visible in the dumps seen via :c:macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` and :c:macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE`, and thus may be of use when debugging how your project's internal representation gets converted to the libgccjit IR. Parameter "loc" is optional. .. function:: void\ gccjit::block::end_with_conditional (gccjit::rvalue boolval,\ gccjit::block on_true,\ gccjit::block on_false, \ gccjit::location loc) Terminate a block by adding evaluation of an rvalue, branching on the result to the appropriate successor block. This is roughly equivalent to this C code: .. code-block:: c if (boolval) goto on_true; else goto on_false; block, boolval, on_true, and on_false must be non-NULL. .. function:: void\ gccjit::block::end_with_jump (gccjit::block target, \ gccjit::location loc) Terminate a block by adding a jump to the given target block. This is roughly equivalent to this C code: .. code-block:: c goto target; .. function:: void\ gccjit::block::end_with_return (gccjit::rvalue rvalue, \ gccjit::location loc) Terminate a block. Both params are optional. An rvalue must be provided for a function returning non-void, and must not be provided by a function "returning" `void`. If an rvalue is provided, the block is terminated by evaluating the rvalue and returning the value. This is roughly equivalent to this C code: .. code-block:: c return expression; If an rvalue is not provided, the block is terminated by adding a valueless return, for use within a function with "void" return type. This is equivalent to this C code: .. code-block:: c return; .. 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. .. 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 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++