diff options
author | Martin Liska <mliska@suse.cz> | 2022-11-13 21:59:20 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-11-14 09:35:06 +0100 |
commit | 40a39381063fdd83c4cbf5eacebfc50a2201308b (patch) | |
tree | 1f33224e8587aee59e622085792d4befca0e6d61 /gcc/jit/docs/topics | |
parent | 64d5610f44c995b88261bf83f53a200355cb530f (diff) | |
download | gcc-40a39381063fdd83c4cbf5eacebfc50a2201308b.zip gcc-40a39381063fdd83c4cbf5eacebfc50a2201308b.tar.gz gcc-40a39381063fdd83c4cbf5eacebfc50a2201308b.tar.bz2 |
Revert "sphinx: jit: port libgccjit to shared Sphinx"
This reverts commit 94246daa3efba88d4ae6619f24d737c01ba3dc89.
Diffstat (limited to 'gcc/jit/docs/topics')
-rw-r--r-- | gcc/jit/docs/topics/asm.rst | 311 | ||||
-rw-r--r-- | gcc/jit/docs/topics/compatibility.rst | 373 | ||||
-rw-r--r-- | gcc/jit/docs/topics/compilation.rst | 201 | ||||
-rw-r--r-- | gcc/jit/docs/topics/contexts.rst | 601 | ||||
-rw-r--r-- | gcc/jit/docs/topics/expressions.rst | 1022 | ||||
-rw-r--r-- | gcc/jit/docs/topics/function-pointers.rst | 82 | ||||
-rw-r--r-- | gcc/jit/docs/topics/functions.rst | 489 | ||||
-rw-r--r-- | gcc/jit/docs/topics/index.rst | 34 | ||||
-rw-r--r-- | gcc/jit/docs/topics/locations.rst | 73 | ||||
-rw-r--r-- | gcc/jit/docs/topics/objects.rst | 88 | ||||
-rw-r--r-- | gcc/jit/docs/topics/performance.rst | 240 | ||||
-rw-r--r-- | gcc/jit/docs/topics/types.rst | 543 |
12 files changed, 4057 insertions, 0 deletions
diff --git a/gcc/jit/docs/topics/asm.rst b/gcc/jit/docs/topics/asm.rst new file mode 100644 index 0000000..6c1397f --- /dev/null +++ b/gcc/jit/docs/topics/asm.rst @@ -0,0 +1,311 @@ +.. Copyright (C) 2020-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Using Assembly Language with libgccjit +====================================== + +libgccjit has some support for directly embedding assembler instructions. +This is based on GCC's support for inline ``asm`` in C code, and the +following assumes a familiarity with that functionality. See +`How to Use Inline Assembly Language in C Code <https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html>`_ +in GCC's documentation, the "Extended Asm" section in particular. + +These entrypoints were added in :ref:`LIBGCCJIT_ABI_15`; you can test +for their presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS + +Adding assembler instructions within a function +*********************************************** + +.. type:: gcc_jit_extended_asm + + A `gcc_jit_extended_asm` represents an extended ``asm`` statement: a + series of low-level instructions inside a function that convert inputs + to outputs. + + To avoid having an API entrypoint with a very large number of + parameters, an extended ``asm`` statement is made in stages: + an initial call to create the :type:`gcc_jit_extended_asm`, + followed by calls to add operands and set other properties of the + statement. + + There are two API entrypoints for creating a :type:`gcc_jit_extended_asm`: + + * :func:`gcc_jit_block_add_extended_asm` for an ``asm`` statement with + no control flow, and + + * :func:`gcc_jit_block_end_with_extended_asm_goto` for an ``asm goto``. + + For example, to create the equivalent of: + + .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c + :start-after: // Quote from here in docs/topics/asm.rst: example 1: C + :end-before: // Quote up to here in docs/topics/asm.rst: example 1: C + :language: c + + the following API calls could be used: + + .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c + :start-after: /* Quote from here in docs/topics/asm.rst: example 1: jit. */ + :end-before: /* Quote up to here in docs/topics/asm.rst: example 1: jit. */ + :language: c + + .. warning:: When considering the numbering of operands within an + extended ``asm`` statement (e.g. the ``%0`` and ``%1`` + above), the equivalent to the C syntax is followed i.e. all + output operands, then all input operands, regardless of + what order the calls to + :func:`gcc_jit_extended_asm_add_output_operand` and + :func:`gcc_jit_extended_asm_add_input_operand` were made in. + + As in the C syntax, operands can be given symbolic names to avoid having + to number them. For example, to create the equivalent of: + + .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c + :start-after: // Quote from here in docs/topics/asm.rst: example 2: C + :end-before: // Quote up to here in docs/topics/asm.rst: example 2: C + :language: c + + the following API calls could be used: + + .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c + :start-after: /* Quote from here in docs/topics/asm.rst: example 2: jit. */ + :end-before: /* Quote up to here in docs/topics/asm.rst: example 2: jit. */ + :language: c + +.. function:: gcc_jit_extended_asm *\ + gcc_jit_block_add_extended_asm (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + const char *asm_template) + + Create a :type:`gcc_jit_extended_asm` for an extended ``asm`` statement + with no control flow (i.e. without the ``goto`` qualifier). + + The parameter ``asm_template`` corresponds to the `AssemblerTemplate` + within C's extended ``asm`` syntax. It must be non-NULL. The call takes + a copy of the underlying string, so it is valid to pass in a pointer to + an on-stack buffer. + +.. function:: gcc_jit_extended_asm *\ + gcc_jit_block_end_with_extended_asm_goto (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + const char *asm_template,\ + int num_goto_blocks,\ + gcc_jit_block **goto_blocks,\ + gcc_jit_block *fallthrough_block) + + Create a :type:`gcc_jit_extended_asm` for an extended ``asm`` statement + that may perform jumps, and use it to terminate the given block. + This is equivalent to the ``goto`` qualifier in C's extended ``asm`` + syntax. + + For example, to create the equivalent of: + + .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c + :start-after: // Quote from here in docs/topics/asm.rst: example 3b: C + :end-before: // Quote up to here in docs/topics/asm.rst: example 3b: C + :language: c + + the following API calls could be used: + + .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c + :start-after: /* Quote from here in docs/topics/asm.rst: example 3: jit. */ + :end-before: /* Quote up to here in docs/topics/asm.rst: example 3: jit. */ + :language: c + + here referencing a :type:`gcc_jit_block` named "carry". + + ``num_goto_blocks`` must be >= 0. + + ``goto_blocks`` must be non-NULL. This corresponds to the ``GotoLabels`` + parameter within C's extended ``asm`` syntax. The block names can be + referenced within the assembler template. + + ``fallthrough_block`` can be NULL. If non-NULL, it specifies the block + to fall through to after the statement. + + .. note:: This is needed since each :type:`gcc_jit_block` must have a + single exit point, as a basic block: you can't jump from the + middle of a block. A "goto" is implicitly added after the + asm to handle the fallthrough case, which is equivalent to what + would have happened in the C case. + +.. function:: void\ + gcc_jit_extended_asm_set_volatile_flag (gcc_jit_extended_asm *ext_asm,\ + int flag) + + Set whether the :type:`gcc_jit_extended_asm` has side-effects, equivalent to the + `volatile <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile>`_ + qualifier in C's extended asm syntax. + + For example, to create the equivalent of: + + .. code-block:: c + + asm volatile ("rdtsc\n\t" // Returns the time in EDX:EAX. + "shl $32, %%rdx\n\t" // Shift the upper bits left. + "or %%rdx, %0" // 'Or' in the lower bits. + : "=a" (msr) + : + : "rdx"); + + the following API calls could be used: + + .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c + :start-after: /* Quote from here in docs/topics/asm.rst: example 4: jit. */ + :end-before: /* Quote up to here in docs/topics/asm.rst: example 4: jit. */ + :language: c + + where the :type:`gcc_jit_extended_asm` is flagged as volatile. + +.. function:: void\ + gcc_jit_extended_asm_set_inline_flag (gcc_jit_extended_asm *ext_asm,\ + int flag) + + Set the equivalent of the + `inline <https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm>`_ + qualifier in C's extended ``asm`` syntax. + +.. function:: void\ + gcc_jit_extended_asm_add_output_operand (gcc_jit_extended_asm *ext_asm,\ + const char *asm_symbolic_name,\ + const char *constraint,\ + gcc_jit_lvalue *dest) + + Add an output operand to the extended ``asm`` statement. See the + `Output Operands <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands>`_ + section of the documentation of the C syntax. + + ``asm_symbolic_name`` corresponds to the ``asmSymbolicName`` component of C's + extended ``asm`` syntax. It can be NULL. If non-NULL it specifies the + symbolic name for the operand. + + ``constraint`` corresponds to the ``constraint`` component of C's extended + ``asm`` syntax. It must be non-NULL. + + ``dest`` corresponds to the ``cvariablename`` component of C's extended + ``asm`` syntax. It must be non-NULL. + + .. code-block:: c + + // Example with a NULL symbolic name, the equivalent of: + // : "=r" (dst) + gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst); + + // Example with a symbolic name ("aIndex"), the equivalent of: + // : [aIndex] "=r" (index) + gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index); + + This function can't be called on an ``asm goto`` as such instructions can't + have outputs; see the + `Goto Labels <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels>`_ + section of GCC's "Extended Asm" documentation. + +.. function:: void\ + gcc_jit_extended_asm_add_input_operand (gcc_jit_extended_asm *ext_asm,\ + const char *asm_symbolic_name,\ + const char *constraint,\ + gcc_jit_rvalue *src) + + Add an input operand to the extended ``asm`` statement. See the + `Input Operands <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands>`_ + section of the documentation of the C syntax. + + ``asm_symbolic_name`` corresponds to the ``asmSymbolicName`` component of C's + extended ``asm`` syntax. It can be NULL. If non-NULL it specifies the + symbolic name for the operand. + + ``constraint`` corresponds to the ``constraint`` component of C's extended + ``asm`` syntax. It must be non-NULL. + + ``src`` corresponds to the ``cexpression`` component of C's extended + ``asm`` syntax. It must be non-NULL. + + .. code-block:: c + + // Example with a NULL symbolic name, the equivalent of: + // : "r" (src) + gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r", + gcc_jit_lvalue_as_rvalue (src)); + + // Example with a symbolic name ("aMask"), the equivalent of: + // : [aMask] "r" (Mask) + gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r", + gcc_jit_lvalue_as_rvalue (mask)); + +.. function:: void\ + gcc_jit_extended_asm_add_clobber (gcc_jit_extended_asm *ext_asm,\ + const char *victim) + + Add `victim` to the list of registers clobbered by the extended ``asm`` + statement. It must be non-NULL. See the + `Clobbers and Scratch Registers <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#>`_ + section of the documentation of the C syntax. + + Statements with multiple clobbers will require multiple calls, one per + clobber. + + For example: + + .. code-block:: c + + gcc_jit_extended_asm_add_clobber (ext_asm, "r0"); + gcc_jit_extended_asm_add_clobber (ext_asm, "cc"); + gcc_jit_extended_asm_add_clobber (ext_asm, "memory"); + +A :type:`gcc_jit_extended_asm` is a :type:`gcc_jit_object` "owned" by +the block's context. The following upcast is available: + +.. function:: gcc_jit_object *\ + gcc_jit_extended_asm_as_object (gcc_jit_extended_asm *ext_asm) + + Upcast from extended ``asm`` to object. + + +Adding top-level assembler statements +************************************* + +In addition to creating extended ``asm`` instructions within a function, +there is support for creating "top-level" assembler statements, outside +of any function. + +.. function:: void \ + gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + const char *asm_stmts) + + Create a set of top-level asm statements, analogous to those created + by GCC's "basic" ``asm`` syntax in C at file scope. + + For example, to create the equivalent of: + + .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c + :start-after: // Quote from here in docs/topics/asm.rst: example 5: C + :end-before: // Quote up to here in docs/topics/asm.rst: example 5: C + :language: c + + the following API calls could be used: + + .. literalinclude:: ../../../testsuite/jit.dg/test-asm.c + :start-after: /* Quote from here in docs/topics/asm.rst: example 5: jit. */ + :end-before: /* Quote up to here in docs/topics/asm.rst: example 5: jit. */ + :language: c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst new file mode 100644 index 0000000..27845ea --- /dev/null +++ b/gcc/jit/docs/topics/compatibility.rst @@ -0,0 +1,373 @@ +.. Copyright (C) 2015-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +ABI and API compatibility +========================= + +The libgccjit developers strive for ABI and API backward-compatibility: +programs built against libgccjit.so stand a good chance of running +without recompilation against newer versions of libgccjit.so, and +ought to recompile without modification against newer versions of +libgccjit.h. + +.. note:: The libgccjit++.h C++ API is more experimental, and less + locked-down at this time. + +API compatibility is achieved by extending the API rather than changing +it. For ABI compatiblity, we avoid bumping the SONAME, and instead use +symbol versioning to tag each symbol, so that a binary linked against +libgccjit.so is tagged according to the symbols that it uses. + +For example, :func:`gcc_jit_context_add_command_line_option` was added in +``LIBGCCJIT_ABI_1``. If a client program uses it, this can be detected +from metadata by using ``objdump``: + +.. code-block:: bash + + $ objdump -p testsuite/jit/test-extra-options.c.exe | tail -n 8 + + Version References: + required from libgccjit.so.0: + 0x00824161 0x00 04 LIBGCCJIT_ABI_1 + 0x00824160 0x00 03 LIBGCCJIT_ABI_0 + required from libc.so.6: + +You can see the symbol tags provided by libgccjit.so using ``objdump``: + +.. code-block:: bash + + $ objdump -p libgccjit.so | less + [...snip...] + Version definitions: + 1 0x01 0x0ff81f20 libgccjit.so.0 + 2 0x00 0x00824160 LIBGCCJIT_ABI_0 + 3 0x00 0x00824161 LIBGCCJIT_ABI_1 + LIBGCCJIT_ABI_0 + [...snip...] + +Programmatically checking version +********************************* + +Client code can programmatically check libgccjit version using: + +.. function:: int gcc_jit_version_major (void) + + Return libgccjit major version. This is analogous to __GNUC__ in C code. + +.. function:: int gcc_jit_version_minor (void) + + Return libgccjit minor version. This is analogous to + __GNUC_MINOR__ in C code. + +.. function:: int gcc_jit_version_patchlevel (void) + + Return libgccjit patchlevel version. This is analogous to + __GNUC_PATCHLEVEL__ in C code. + +.. note:: These entry points has been added with ``LIBGCCJIT_ABI_13`` + (see below). + +ABI symbol tags +*************** + +The initial release of libgccjit (in gcc 5.1) did not use symbol versioning. + +Newer releases use the following tags. + +.. _LIBGCCJIT_ABI_0: + +``LIBGCCJIT_ABI_0`` +------------------- + +All entrypoints in the initial release of libgccjit are tagged with +``LIBGCCJIT_ABI_0``, to signify the transition to symbol versioning. + +Binaries built against older copies of ``libgccjit.so`` should +continue to work, with this being handled transparently by the linker +(see `this post +<https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02126.html>`_) + +.. _LIBGCCJIT_ABI_1: + +``LIBGCCJIT_ABI_1`` +------------------- +``LIBGCCJIT_ABI_1`` covers the addition of +:func:`gcc_jit_context_add_command_line_option` + +.. _LIBGCCJIT_ABI_2: + +``LIBGCCJIT_ABI_2`` +------------------- +``LIBGCCJIT_ABI_2`` covers the addition of +:func:`gcc_jit_context_set_bool_allow_unreachable_blocks` + +.. _LIBGCCJIT_ABI_3: + +``LIBGCCJIT_ABI_3`` +------------------- +``LIBGCCJIT_ABI_3`` covers the addition of switch statements via API +entrypoints: + + * :func:`gcc_jit_block_end_with_switch` + + * :func:`gcc_jit_case_as_object` + + * :func:`gcc_jit_context_new_case` + +.. _LIBGCCJIT_ABI_4: + +``LIBGCCJIT_ABI_4`` +------------------- +``LIBGCCJIT_ABI_4`` covers the addition of timers via API +entrypoints: + + * :func:`gcc_jit_context_get_timer` + + * :func:`gcc_jit_context_set_timer` + + * :func:`gcc_jit_timer_new` + + * :func:`gcc_jit_timer_release` + + * :func:`gcc_jit_timer_push` + + * :func:`gcc_jit_timer_pop` + + * :func:`gcc_jit_timer_print` + +.. _LIBGCCJIT_ABI_5: + +``LIBGCCJIT_ABI_5`` +------------------- +``LIBGCCJIT_ABI_5`` covers the addition of +:func:`gcc_jit_context_set_bool_use_external_driver` + +.. _LIBGCCJIT_ABI_6: + +``LIBGCCJIT_ABI_6`` +------------------- +``LIBGCCJIT_ABI_6`` covers the addition of +:func:`gcc_jit_rvalue_set_bool_require_tail_call` + +.. _LIBGCCJIT_ABI_7: + +``LIBGCCJIT_ABI_7`` +------------------- +``LIBGCCJIT_ABI_7`` covers the addition of +:func:`gcc_jit_type_get_aligned` + +.. _LIBGCCJIT_ABI_8: + +``LIBGCCJIT_ABI_8`` +------------------- +``LIBGCCJIT_ABI_8`` covers the addition of +:func:`gcc_jit_type_get_vector` + +.. _LIBGCCJIT_ABI_9: + +``LIBGCCJIT_ABI_9`` +------------------- +``LIBGCCJIT_ABI_9`` covers the addition of +:func:`gcc_jit_function_get_address` + +.. _LIBGCCJIT_ABI_10: + +``LIBGCCJIT_ABI_10`` +-------------------- +``LIBGCCJIT_ABI_10`` covers the addition of +:func:`gcc_jit_context_new_rvalue_from_vector` + +.. _LIBGCCJIT_ABI_11: + +``LIBGCCJIT_ABI_11`` +-------------------- +``LIBGCCJIT_ABI_11`` covers the addition of +:func:`gcc_jit_context_add_driver_option` + +.. _LIBGCCJIT_ABI_12: + +``LIBGCCJIT_ABI_12`` +-------------------- +``LIBGCCJIT_ABI_12`` covers the addition of +:func:`gcc_jit_context_new_bitfield` + +.. _LIBGCCJIT_ABI_13: + +``LIBGCCJIT_ABI_13`` +-------------------- +``LIBGCCJIT_ABI_13`` covers the addition of version functions via API +entrypoints: + + * :func:`gcc_jit_version_major` + + * :func:`gcc_jit_version_minor` + + * :func:`gcc_jit_version_patchlevel` + +.. _LIBGCCJIT_ABI_14: + +``LIBGCCJIT_ABI_14`` +-------------------- +``LIBGCCJIT_ABI_14`` covers the addition of +:func:`gcc_jit_global_set_initializer` + +.. _LIBGCCJIT_ABI_15: + +``LIBGCCJIT_ABI_15`` +-------------------- +``LIBGCCJIT_ABI_15`` covers the addition of API entrypoints for directly +embedding assembler instructions: + + * :func:`gcc_jit_block_add_extended_asm` + * :func:`gcc_jit_block_end_with_extended_asm_goto` + * :func:`gcc_jit_extended_asm_as_object` + * :func:`gcc_jit_extended_asm_set_volatile_flag` + * :func:`gcc_jit_extended_asm_set_inline_flag` + * :func:`gcc_jit_extended_asm_add_output_operand` + * :func:`gcc_jit_extended_asm_add_input_operand` + * :func:`gcc_jit_extended_asm_add_clobber` + * :func:`gcc_jit_context_add_top_level_asm` + +.. _LIBGCCJIT_ABI_16: + +``LIBGCCJIT_ABI_16`` +-------------------- +``LIBGCCJIT_ABI_16`` covers the addition of reflection functions via API +entrypoints: + + * :func:`gcc_jit_function_get_return_type` + + * :func:`gcc_jit_function_get_param_count` + + * :func:`gcc_jit_type_dyncast_array` + + * :func:`gcc_jit_type_is_bool` + + * :func:`gcc_jit_type_is_integral` + + * :func:`gcc_jit_type_is_pointer` + + * :func:`gcc_jit_type_is_struct` + + * :func:`gcc_jit_type_dyncast_vector` + + * :func:`gcc_jit_type_unqualified` + + * :func:`gcc_jit_type_dyncast_function_ptr_type` + + * :func:`gcc_jit_function_type_get_return_type` + + * :func:`gcc_jit_function_type_get_param_count` + + * :func:`gcc_jit_function_type_get_param_type` + + * :func:`gcc_jit_vector_type_get_num_units` + + * :func:`gcc_jit_vector_type_get_element_type` + + * :func:`gcc_jit_struct_get_field` + + * :func:`gcc_jit_struct_get_field_count` + +.. _LIBGCCJIT_ABI_17: + +``LIBGCCJIT_ABI_17`` +----------------------- +``LIBGCCJIT_ABI_17`` covers the addition of an API entrypoint to set the +thread-local storage model of a variable: + + * :func:`gcc_jit_lvalue_set_tls_model` + +.. _LIBGCCJIT_ABI_18: + +``LIBGCCJIT_ABI_18`` +----------------------- +``LIBGCCJIT_ABI_18`` covers the addition of an API entrypoint to set the link +section of a variable: + + * :func:`gcc_jit_lvalue_set_link_section` + +.. _LIBGCCJIT_ABI_19: + +``LIBGCCJIT_ABI_19`` +----------------------- +``LIBGCCJIT_ABI_19`` covers the addition of API entrypoints to set the initial value +of a global with an rvalue and to use constructors: + + * :func:`gcc_jit_context_new_array_constructor` + * :func:`gcc_jit_context_new_struct_constructor` + * :func:`gcc_jit_context_new_union_constructor` + * :func:`gcc_jit_global_set_initializer_rvalue` + +.. _LIBGCCJIT_ABI_20: + +``LIBGCCJIT_ABI_20`` +----------------------- +``LIBGCCJIT_ABI_20`` covers the addition of sized integer types, including +128-bit integers and helper functions for types: + + * :func:`gcc_jit_compatible_types` + * :func:`gcc_jit_type_get_size` + * :c:macro:`GCC_JIT_TYPE_UINT8_T` + * :c:macro:`GCC_JIT_TYPE_UINT16_T` + * :c:macro:`GCC_JIT_TYPE_UINT32_T` + * :c:macro:`GCC_JIT_TYPE_UINT64_T` + * :c:macro:`GCC_JIT_TYPE_UINT128_T` + * :c:macro:`GCC_JIT_TYPE_INT8_T` + * :c:macro:`GCC_JIT_TYPE_INT16_T` + * :c:macro:`GCC_JIT_TYPE_INT32_T` + * :c:macro:`GCC_JIT_TYPE_INT64_T` + * :c:macro:`GCC_JIT_TYPE_INT128_T` + +.. _LIBGCCJIT_ABI_21: + +``LIBGCCJIT_ABI_21`` +-------------------- +``LIBGCCJIT_ABI_21`` covers the addition of an API entrypoint to bitcast a +value from one type to another: + + * :func:`gcc_jit_context_new_bitcast` + +.. _LIBGCCJIT_ABI_22: + +``LIBGCCJIT_ABI_22`` +-------------------- +``LIBGCCJIT_ABI_22`` covers the addition of an API entrypoint to set the +register name of a variable: + + * :func:`gcc_jit_lvalue_set_register_name` + +.. _LIBGCCJIT_ABI_23: + +``LIBGCCJIT_ABI_23`` +-------------------- +``LIBGCCJIT_ABI_23`` covers the addition of an API entrypoint to hide stderr +logs: + + * :func:`gcc_jit_context_set_bool_print_errors_to_stderr` + +.. _LIBGCCJIT_ABI_24: + +``LIBGCCJIT_ABI_24`` +-------------------- +``LIBGCCJIT_ABI_24`` covers the addition of functions to get and set the +alignment of a variable: + + * :func:`gcc_jit_lvalue_set_alignment` + * :func:`gcc_jit_lvalue_get_alignment` diff --git a/gcc/jit/docs/topics/compilation.rst b/gcc/jit/docs/topics/compilation.rst new file mode 100644 index 0000000..3dd9bc6 --- /dev/null +++ b/gcc/jit/docs/topics/compilation.rst @@ -0,0 +1,201 @@ +.. Copyright (C) 2014-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Compiling a context +=================== + +Once populated, a :c:expr:`gcc_jit_context *` can be compiled to +machine code, either in-memory via :c:func:`gcc_jit_context_compile` or +to disk via :c:func:`gcc_jit_context_compile_to_file`. + +You can compile a context multiple times (using either form of +compilation), although any errors that occur on the context will +prevent any future compilation of that context. + +In-memory compilation +********************* + +.. function:: gcc_jit_result *\ + gcc_jit_context_compile (gcc_jit_context *ctxt) + + This calls into GCC and builds the code, returning a + `gcc_jit_result *`. + + If the result is non-NULL, the caller becomes responsible for + calling :func:`gcc_jit_result_release` on it once they're done + with it. + +.. type:: gcc_jit_result + + A `gcc_jit_result` encapsulates the result of compiling a context + in-memory, and the lifetimes of any machine code functions or globals + that are within the result. + +.. function:: void *\ + gcc_jit_result_get_code (gcc_jit_result *result,\ + const char *funcname) + + Locate a given function within the built machine code. + + Functions are looked up by name. For this to succeed, a function + with a name matching `funcname` must have been created on + `result`'s context (or a parent context) via a call to + :func:`gcc_jit_context_new_function` with `kind` + :macro:`GCC_JIT_FUNCTION_EXPORTED`: + + .. code-block:: c + + gcc_jit_context_new_function (ctxt, + any_location, /* or NULL */ + /* Required for func to be visible to + gcc_jit_result_get_code: */ + GCC_JIT_FUNCTION_EXPORTED, + any_return_type, + /* Must string-compare equal: */ + funcname, + /* etc */); + + If such a function is not found (or `result` or `funcname` are + ``NULL``), an error message will be emitted on stderr and + ``NULL`` will be returned. + + If the function is found, the result will need to be cast to a + function pointer of the correct type before it can be called. + + Note that the resulting machine code becomes invalid after + :func:`gcc_jit_result_release` is called on the + :expr:`gcc_jit_result *`; attempting to call it after that may lead + to a segmentation fault. + +.. function:: void *\ + gcc_jit_result_get_global (gcc_jit_result *result,\ + const char *name) + + Locate a given global within the built machine code. + + Globals are looked up by name. For this to succeed, a global + with a name matching `name` must have been created on + `result`'s context (or a parent context) via a call to + :func:`gcc_jit_context_new_global` with `kind` + :macro:`GCC_JIT_GLOBAL_EXPORTED`. + + If the global is found, the result will need to be cast to a + pointer of the correct type before it can be called. + + This is a *pointer* to the global, so e.g. for an :expr:`int` this is + an :expr:`int *`. + + For example, given an ``int foo;`` created this way: + + .. code-block:: c + + gcc_jit_lvalue *exported_global = + gcc_jit_context_new_global (ctxt, + any_location, /* or NULL */ + GCC_JIT_GLOBAL_EXPORTED, + int_type, + "foo"); + + we can access it like this: + + .. code-block:: c + + int *ptr_to_foo = + (int *)gcc_jit_result_get_global (result, "foo"); + + If such a global is not found (or `result` or `name` are + ``NULL``), an error message will be emitted on stderr and + ``NULL`` will be returned. + + Note that the resulting address becomes invalid after + :func:`gcc_jit_result_release` is called on the + :expr:`gcc_jit_result *`; attempting to use it after that may lead + to a segmentation fault. + +.. function:: void\ + gcc_jit_result_release (gcc_jit_result *result) + + Once we're done with the code, this unloads the built .so file. + This cleans up the result; after calling this, it's no longer + valid to use the result, or any code or globals that were obtained + by calling :func:`gcc_jit_result_get_code` or + :func:`gcc_jit_result_get_global` on it. + + +Ahead-of-time compilation +************************* + +Although libgccjit is primarily aimed at just-in-time compilation, it +can also be used for implementing more traditional ahead-of-time +compilers, via the :c:func:`gcc_jit_context_compile_to_file` +API entrypoint. + +For linking in object files, use :c:func:`gcc_jit_context_add_driver_option`. + +.. function:: void \ + gcc_jit_context_compile_to_file (gcc_jit_context *ctxt, \ + enum gcc_jit_output_kind output_kind,\ + const char *output_path) + + Compile the :c:expr:`gcc_jit_context *` to a file of the given + kind. + +:c:func:`gcc_jit_context_compile_to_file` ignores the suffix of +``output_path``, and insteads uses the given +:c:enum:`gcc_jit_output_kind` to decide what to do. + +.. note:: + + This is different from the ``gcc`` program, which does make use of the + suffix of the output file when determining what to do. + +.. enum:: gcc_jit_output_kind + +The available kinds of output are: + +.. list-table:: + :header-rows: 1 + + * - Output kind + - Typical suffix + + * - :c:macro:`GCC_JIT_OUTPUT_KIND_ASSEMBLER` + - .s + * - :c:macro:`GCC_JIT_OUTPUT_KIND_OBJECT_FILE` + - .o + * - :c:macro:`GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY` + - .so or .dll + * - :c:macro:`GCC_JIT_OUTPUT_KIND_EXECUTABLE` + - None, or .exe + +.. c:macro:: GCC_JIT_OUTPUT_KIND_ASSEMBLER + + Compile the context to an assembler file. + +.. c:macro:: GCC_JIT_OUTPUT_KIND_OBJECT_FILE + + Compile the context to an object file. + +.. c:macro:: GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY + + Compile the context to a dynamic library. + +.. c:macro:: GCC_JIT_OUTPUT_KIND_EXECUTABLE + + Compile the context to an executable. diff --git a/gcc/jit/docs/topics/contexts.rst b/gcc/jit/docs/topics/contexts.rst new file mode 100644 index 0000000..b1a7a0a --- /dev/null +++ b/gcc/jit/docs/topics/contexts.rst @@ -0,0 +1,601 @@ +.. Copyright (C) 2014-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Compilation contexts +==================== + +.. type:: gcc_jit_context + +The top-level of the API is the :c:type:`gcc_jit_context` type. + +A :c:type:`gcc_jit_context` instance encapsulates the state of a +compilation. + +You can set up options on it, and add types, functions and code. +Invoking :c:func:`gcc_jit_context_compile` on it gives you a +:c:type:`gcc_jit_result`. + +Lifetime-management +------------------- +Contexts are the unit of lifetime-management within the API: objects +have their lifetime bounded by the context they are created within, and +cleanup of such objects is done for you when the context is released. + +.. function:: gcc_jit_context *gcc_jit_context_acquire (void) + + This function acquires a new :c:expr:`gcc_jit_context *` instance, + which is independent of any others that may be present within this + process. + +.. function:: void gcc_jit_context_release (gcc_jit_context *ctxt) + + This function releases all resources associated with the given context. + Both the context itself and all of its :c:expr:`gcc_jit_object *` + instances are cleaned up. It should be called exactly once on a given + context. + + It is invalid to use the context or any of its "contextual" objects + after calling this. + + .. code-block:: c + + gcc_jit_context_release (ctxt); + +.. function:: gcc_jit_context * gcc_jit_context_new_child_context (gcc_jit_context *parent_ctxt) + + Given an existing JIT context, create a child context. + + The child inherits a copy of all option-settings from the parent. + + The child can reference objects created within the parent, but not + vice-versa. + + The lifetime of the child context must be bounded by that of the + parent: you should release a child context before releasing the parent + context. + + If you use a function from a parent context within a child context, + you have to compile the parent context before you can compile the + child context, and the gcc_jit_result of the parent context must + outlive the gcc_jit_result of the child context. + + This allows caching of shared initializations. For example, you could + create types and declarations of global functions in a parent context + once within a process, and then create child contexts whenever a + function or loop becomes hot. Each such child context can be used for + JIT-compiling just one function or loop, but can reference types + and helper functions created within the parent context. + + Contexts can be arbitrarily nested, provided the above rules are + followed, but it's probably not worth going above 2 or 3 levels, and + there will likely be a performance hit for such nesting. + + +Thread-safety +------------- +Instances of :c:expr:`gcc_jit_context *` created via +:c:func:`gcc_jit_context_acquire` are independent from each other: +only one thread may use a given context at once, but multiple threads +could each have their own contexts without needing locks. + +Contexts created via :c:func:`gcc_jit_context_new_child_context` are +related to their parent context. They can be partitioned by their +ultimate ancestor into independent "family trees". Only one thread +within a process may use a given "family tree" of such contexts at once, +and if you're using multiple threads you should provide your own locking +around entire such context partitions. + +.. _error-handling: + +Error-handling +-------------- +Various kinds of errors are possible when using the API, such as +mismatched types in an assignment. You can only compile and get code from +a context if no errors occur. + +Errors are printed on stderr and can be queried using +:c:func:`gcc_jit_context_get_first_error`. + +They typically contain the name of the API entrypoint where the error +occurred, and pertinent information on the problem: + +.. code-block:: console + + ./buggy-program: error: gcc_jit_block_add_assignment: mismatching types: assignment to i (type: int) from "hello world" (type: const char *) + +In general, if an error occurs when using an API entrypoint, the +entrypoint returns NULL. You don't have to check everywhere for NULL +results, since the API handles a NULL being passed in for any +argument by issuing another error. This typically leads to a cascade of +followup error messages, but is safe (albeit verbose). The first error +message is usually the one to pay attention to, since it is likely to +be responsible for all of the rest: + +.. function:: const char *\ + gcc_jit_context_get_first_error (gcc_jit_context *ctxt) + + Returns the first error message that occurred on the context. + + The returned string is valid for the rest of the lifetime of the + context. + + If no errors occurred, this will be NULL. + +If you are wrapping the C API for a higher-level language that supports +exception-handling, you may instead be interested in the last error that +occurred on the context, so that you can embed this in an exception: + +.. function:: const char *\ + gcc_jit_context_get_last_error (gcc_jit_context *ctxt) + + Returns the last error message that occurred on the context. + + If no errors occurred, this will be NULL. + + If non-NULL, the returned string is only guaranteed to be valid until + the next call to libgccjit relating to this context. + +Debugging +--------- + +.. function:: void\ + gcc_jit_context_dump_to_file (gcc_jit_context *ctxt,\ + const char *path,\ + int update_locations) + + To help with debugging: dump a C-like representation to the given path, + describing what's been set up on the context. + + If "update_locations" is true, then also set up :type:`gcc_jit_location` + information throughout the context, pointing at the dump file as if it + were a source file. This may be of use in conjunction with + :macro:`GCC_JIT_BOOL_OPTION_DEBUGINFO` to allow stepping through the + code in a debugger. + +.. function:: void\ + gcc_jit_context_set_logfile (gcc_jit_context *ctxt,\ + FILE *logfile,\ + int flags,\ + int verbosity) + + To help with debugging; enable ongoing logging of the context's + activity to the given file. + + For example, the following will enable logging to stderr. + + .. code-block:: c + + gcc_jit_context_set_logfile (ctxt, stderr, 0, 0); + + Examples of information logged include: + + * API calls + + * the various steps involved within compilation + + * activity on any :c:type:`gcc_jit_result` instances created by + the context + + * activity within any child contexts + + An example of a log can be seen :ref:`here <example-of-log-file>`, + though the precise format and kinds of information logged is subject + to change. + + The caller remains responsible for closing `logfile`, and it must not + be closed until all users are released. In particular, note that + child contexts and :c:type:`gcc_jit_result` instances created by + the context will use the logfile. + + There may a performance cost for logging. + + You can turn off logging on `ctxt` by passing `NULL` for `logfile`. + Doing so only affects the context; it does not affect child contexts + or :c:type:`gcc_jit_result` instances already created by + the context. + + The parameters "flags" and "verbosity" are reserved for future + expansion, and must be zero for now. + +To contrast the above: :c:func:`gcc_jit_context_dump_to_file` dumps the +current state of a context to the given path, whereas +:c:func:`gcc_jit_context_set_logfile` enables on-going logging of +future activies on a context to the given `FILE *`. + + +.. function:: void\ + gcc_jit_context_dump_reproducer_to_file (gcc_jit_context *ctxt,\ + const char *path) + + Write C source code into `path` that can be compiled into a + self-contained executable (i.e. with libgccjit as the only dependency). + The generated code will attempt to replay the API calls that have been + made into the given context. + + This may be useful when debugging the library or client code, for + reducing a complicated recipe for reproducing a bug into a simpler + form. For example, consider client code that parses some source file + into some internal representation, and then walks this IR, calling into + libgccjit. If this encounters a bug, a call to + `gcc_jit_context_dump_reproducer_to_file` will write out C code for + a much simpler executable that performs the equivalent calls into + libgccjit, without needing the client code and its data. + + Typically you need to supply :option:`-Wno-unused-variable` when + compiling the generated file (since the result of each API call is + assigned to a unique variable within the generated C source, and not + all are necessarily then used). + +.. function:: void\ + gcc_jit_context_enable_dump (gcc_jit_context *ctxt,\ + const char *dumpname, \ + char **out_ptr) + + Enable the dumping of a specific set of internal state from the + compilation, capturing the result in-memory as a buffer. + + Parameter "dumpname" corresponds to the equivalent gcc command-line + option, without the "-fdump-" prefix. + For example, to get the equivalent of :option:`-fdump-tree-vrp1`, + supply ``"tree-vrp1"``: + + .. code-block:: c + + static char *dump_vrp1; + + void + create_code (gcc_jit_context *ctxt) + { + gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1); + /* (other API calls omitted for brevity) */ + } + + The context directly stores the dumpname as a ``(const char *)``, so + the passed string must outlive the context. + + :func:`gcc_jit_context_compile` will capture the dump as a + dynamically-allocated buffer, writing it to ``*out_ptr``. + + The caller becomes responsible for calling: + + .. code-block:: c + + free (*out_ptr) + + each time that :func:`gcc_jit_context_compile` is called. + ``*out_ptr`` will be written to, either with the address of a buffer, + or with ``NULL`` if an error occurred. + + .. warning:: + + This API entrypoint is likely to be less stable than the others. + In particular, both the precise dumpnames, and the format and content + of the dumps are subject to change. + + It exists primarily for writing the library's own test suite. + +Options +------- + +Options present in the initial release of libgccjit were handled using +enums, whereas those added subsequently have their own per-option API +entrypoints. + +Adding entrypoints for each new option means that client code that use +the new options can be identified directly from binary metadata, which +would not be possible if we instead extended the various +``enum gcc_jit_*_option``. + +String Options +************** + +.. function:: void gcc_jit_context_set_str_option(gcc_jit_context *ctxt, \ + enum gcc_jit_str_option opt, \ + const char *value) + + Set a string option of the context. + + .. enum:: gcc_jit_str_option + + The parameter ``value`` can be NULL. If non-NULL, the call takes a + copy of the underlying string, so it is valid to pass in a pointer to + an on-stack buffer. + + There is just one string option specified this way: + + .. macro:: GCC_JIT_STR_OPTION_PROGNAME + + The name of the program, for use as a prefix when printing error + messages to stderr. If `NULL`, or default, "libgccjit.so" is used. + +Boolean options +*************** + +.. function:: void gcc_jit_context_set_bool_option(gcc_jit_context *ctxt, \ + enum gcc_jit_bool_option opt, \ + int value) + + Set a boolean option of the context. + Zero is "false" (the default), non-zero is "true". + + .. enum:: gcc_jit_bool_option + + .. macro:: GCC_JIT_BOOL_OPTION_DEBUGINFO + + If true, :func:`gcc_jit_context_compile` will attempt to do the right + thing so that if you attach a debugger to the process, it will + be able to inspect variables and step through your code. + + Note that you can't step through code unless you set up source + location information for the code (by creating and passing in + :type:`gcc_jit_location` instances). + + .. macro:: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE + + If true, :func:`gcc_jit_context_compile` will dump its initial + "tree" representation of your code to stderr (before any + optimizations). + + Here's some sample output (from the `square` example):: + + <statement_list 0x7f4875a62cc0 + type <void_type 0x7f4875a64bd0 VOID + align 8 symtab 0 alias set -1 canonical type 0x7f4875a64bd0 + pointer_to_this <pointer_type 0x7f4875a64c78>> + side-effects head 0x7f4875a761e0 tail 0x7f4875a761f8 stmts 0x7f4875a62d20 0x7f4875a62d00 + + stmt <label_expr 0x7f4875a62d20 type <void_type 0x7f4875a64bd0> + side-effects + arg 0 <label_decl 0x7f4875a79080 entry type <void_type 0x7f4875a64bd0> + VOID file (null) line 0 col 0 + align 1 context <function_decl 0x7f4875a77500 square>>> + stmt <return_expr 0x7f4875a62d00 + type <integer_type 0x7f4875a645e8 public SI + size <integer_cst 0x7f4875a623a0 constant 32> + unit size <integer_cst 0x7f4875a623c0 constant 4> + align 32 symtab 0 alias set -1 canonical type 0x7f4875a645e8 precision 32 min <integer_cst 0x7f4875a62340 -2147483648> max <integer_cst 0x7f4875a62360 2147483647> + pointer_to_this <pointer_type 0x7f4875a6b348>> + side-effects + arg 0 <modify_expr 0x7f4875a72a78 type <integer_type 0x7f4875a645e8> + side-effects arg 0 <result_decl 0x7f4875a7a000 D.54> + arg 1 <mult_expr 0x7f4875a72a50 type <integer_type 0x7f4875a645e8> + arg 0 <parm_decl 0x7f4875a79000 i> arg 1 <parm_decl 0x7f4875a79000 i>>>>> + + .. macro:: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE + + If true, :func:`gcc_jit_context_compile` will dump the "gimple" + representation of your code to stderr, before any optimizations + are performed. The dump resembles C code: + + .. code-block:: c + + square (signed int i) + { + signed int D.56; + + entry: + D.56 = i * i; + return D.56; + } + + .. macro:: GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE + + If true, :func:`gcc_jit_context_compile` will dump the final + generated code to stderr, in the form of assembly language: + + .. code-block:: gas + + .file "fake.c" + .text + .globl square + .type square, @function + square: + .LFB0: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl %edi, -4(%rbp) + .L2: + movl -4(%rbp), %eax + imull -4(%rbp), %eax + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc + .LFE0: + .size square, .-square + .ident "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2)" + .section .note.GNU-stack,"",@progbits + + + .. macro:: GCC_JIT_BOOL_OPTION_DUMP_SUMMARY + + If true, :func:`gcc_jit_context_compile` will print information to stderr + on the actions it is performing. + + .. macro:: GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING + + If true, :func:`gcc_jit_context_compile` will dump copious + amount of information on what it's doing to various + files within a temporary directory. Use + :macro:`GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES` (see below) to + see the results. The files are intended to be human-readable, + but the exact files and their formats are subject to change. + + .. macro:: GCC_JIT_BOOL_OPTION_SELFCHECK_GC + + If true, libgccjit will aggressively run its garbage collector, to + shake out bugs (greatly slowing down the compile). This is likely + to only be of interest to developers *of* the library. It is + used when running the selftest suite. + + .. macro:: GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES + + If true, the :type:`gcc_jit_context` will not clean up intermediate files + written to the filesystem, and will display their location on stderr. + +.. function:: void \ + gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt, \ + int bool_value) + + By default, libgccjit will issue an error about unreachable blocks + within a function. + + This entrypoint can be used to disable that error. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_2`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks + +.. function:: void \ + gcc_jit_context_set_bool_use_external_driver (gcc_jit_context *ctxt, \ + int bool_value) + + libgccjit internally generates assembler, and uses "driver" code + for converting it to other formats (e.g. shared libraries). + + By default, libgccjit will use an embedded copy of the driver + code. + + This option can be used to instead invoke an external driver executable + as a subprocess. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_5`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver + +.. function:: void \ + gcc_jit_context_set_bool_print_errors_to_stderr (gcc_jit_context *ctxt, \ + int enabled) + + By default, libgccjit will print errors to stderr. + + This entrypoint can be used to disable the printing. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_23`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_print_errors_to_stderr + +Integer options +*************** + +.. function:: void gcc_jit_context_set_int_option (gcc_jit_context *ctxt, \ + enum gcc_jit_int_option opt, \ + int value) + + Set an integer option of the context. + + .. enum:: gcc_jit_int_option + + There is just one integer option specified this way: + + .. macro:: GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL + + How much to optimize the code. + + Valid values are 0-3, corresponding to GCC's command-line options + -O0 through -O3. + + The default value is 0 (unoptimized). + +Additional command-line options +******************************* + +.. function:: void gcc_jit_context_add_command_line_option (gcc_jit_context *ctxt,\ + const char *optname) + + Add an arbitrary gcc command-line option to the context, for use + by :func:`gcc_jit_context_compile` and + :func:`gcc_jit_context_compile_to_file`. + + The parameter ``optname`` must be non-NULL. The underlying buffer is + copied, so that it does not need to outlive the call. + + Extra options added by `gcc_jit_context_add_command_line_option` are + applied *after* the regular options above, potentially overriding them. + Options from parent contexts are inherited by child contexts; options + from the parent are applied *before* those from the child. + + For example: + + .. code-block:: c + + gcc_jit_context_add_command_line_option (ctxt, "-ffast-math"); + gcc_jit_context_add_command_line_option (ctxt, "-fverbose-asm"); + + Note that only some options are likely to be meaningful; there is no + "frontend" within libgccjit, so typically only those affecting + optimization and code-generation are likely to be useful. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_1`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option + +.. function:: void gcc_jit_context_add_driver_option (gcc_jit_context *ctxt,\ + const char *optname) + + Add an arbitrary gcc driver option to the context, for use by + :func:`gcc_jit_context_compile` and + :func:`gcc_jit_context_compile_to_file`. + + The parameter ``optname`` must be non-NULL. The underlying buffer is + copied, so that it does not need to outlive the call. + + Extra options added by `gcc_jit_context_add_driver_option` are + applied *after* all other options potentially overriding them. + Options from parent contexts are inherited by child contexts; options + from the parent are applied *before* those from the child. + + For example: + + .. code-block:: c + + gcc_jit_context_add_driver_option (ctxt, "-lm"); + gcc_jit_context_add_driver_option (ctxt, "-fuse-linker-plugin"); + + gcc_jit_context_add_driver_option (ctxt, "obj.o"); + + gcc_jit_context_add_driver_option (ctxt, "-L."); + gcc_jit_context_add_driver_option (ctxt, "-lwhatever"); + + Note that only some options are likely to be meaningful; there is no + "frontend" within libgccjit, so typically only those affecting + assembler and linker are likely to be useful. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_11`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_driver_option diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst new file mode 100644 index 0000000..ff1eec8 --- /dev/null +++ b/gcc/jit/docs/topics/expressions.rst @@ -0,0 +1,1022 @@ +.. Copyright (C) 2014-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Expressions +=========== + +Rvalues +------- +.. type:: gcc_jit_rvalue + +A :c:type:`gcc_jit_rvalue` is an expression that can be computed. + +It can be simple, e.g.: + + * an integer value e.g. `0` or `42` + * a string literal e.g. `"Hello world"` + * a variable e.g. `i`. These are also lvalues (see below). + +or compound e.g.: + + * a unary expression e.g. `!cond` + * a binary expression e.g. `(a + b)` + * a function call e.g. `get_distance (&player_ship, &target)` + * etc. + +Every rvalue has an associated type, and the API will check to ensure +that types match up correctly (otherwise the context will emit an error). + +.. function:: gcc_jit_type *gcc_jit_rvalue_get_type (gcc_jit_rvalue *rvalue) + + Get the type of this rvalue. + +.. function:: gcc_jit_object *gcc_jit_rvalue_as_object (gcc_jit_rvalue *rvalue) + + Upcast the given rvalue to be an object. + + +Simple expressions +****************** + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_rvalue_from_int (gcc_jit_context *ctxt, \ + gcc_jit_type *numeric_type, \ + int value) + + Given a numeric type (integer or floating point), build an rvalue for + the given constant :expr:`int` value. + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_rvalue_from_long (gcc_jit_context *ctxt, \ + gcc_jit_type *numeric_type, \ + long value) + + Given a numeric type (integer or floating point), build an rvalue for + the given constant :expr:`long` value. + +.. function:: gcc_jit_rvalue *gcc_jit_context_zero (gcc_jit_context *ctxt, \ + gcc_jit_type *numeric_type) + + Given a numeric type (integer or floating point), get the rvalue for + zero. Essentially this is just a shortcut for: + + .. code-block:: c + + gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 0) + +.. function:: gcc_jit_rvalue *gcc_jit_context_one (gcc_jit_context *ctxt, \ + gcc_jit_type *numeric_type) + + Given a numeric type (integer or floating point), get the rvalue for + one. Essentially this is just a shortcut for: + + .. code-block:: c + + gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 1) + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_rvalue_from_double (gcc_jit_context *ctxt, \ + gcc_jit_type *numeric_type, \ + double value) + + Given a numeric type (integer or floating point), build an rvalue for + the given constant :expr:`double` value. + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt, \ + gcc_jit_type *pointer_type, \ + void *value) + + Given a pointer type, build an rvalue for the given address. + +.. function:: gcc_jit_rvalue *gcc_jit_context_null (gcc_jit_context *ctxt, \ + gcc_jit_type *pointer_type) + + Given a pointer type, build an rvalue for ``NULL``. Essentially this + is just a shortcut for: + + .. code-block:: c + + gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL) + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_string_literal (gcc_jit_context *ctxt, \ + const char *value) + + Generate an rvalue for the given NIL-terminated string, of type + :c:data:`GCC_JIT_TYPE_CONST_CHAR_PTR`. + + The parameter ``value`` must be non-NULL. The call takes a copy of the + underlying string, so it is valid to pass in a pointer to an on-stack + buffer. + +Constructor expressions +*********************** + + The following functions make constructors for array, struct and union + types. + + The constructor rvalue can be used for assignment to locals. + It can be used to initialize global variables with + :func:`gcc_jit_global_set_initializer_rvalue`. It can also be used as a + temporary value for function calls and return values, but its address + can't be taken. + + Note that arrays in libgccjit do not collapse to pointers like in + C. I.e. if an array constructor is used as e.g. a return value, the whole + array would be returned by value - array constructors can be assigned to + array variables. + + The constructor can contain nested constructors. + + Note that a string literal rvalue can't be used to construct a char array; + the latter needs one rvalue for each char. + + These entrypoints were added in :ref:`LIBGCCJIT_ABI_19`; you can test for + their presence using: + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_CTORS + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_type *type,\ + size_t num_values,\ + gcc_jit_rvalue **values) + + Create a constructor for an array as an rvalue. + + Returns NULL on error. ``values`` are copied and + do not have to outlive the context. + + ``type`` specifies what the constructor will build and has to be + an array. + + ``num_values`` specifies the number of elements in ``values`` and + it can't have more elements than the array type. + + Each value in ``values`` sets the corresponding value in the array. + If the array type itself has more elements than ``values``, the + left-over elements will be zeroed. + + Each value in ``values`` need to be the same unqualified type as the + array type's element type. + + If ``num_values`` is 0, the ``values`` parameter will be + ignored and zero initialization will be used. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_19`; you can test for its + presence using: + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_CTORS + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_struct_constructor (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_type *type,\ + size_t num_values,\ + gcc_jit_field **fields,\ + gcc_jit_rvalue **values) + + + Create a constructor for a struct as an rvalue. + + Returns NULL on error. The two parameter arrays are copied and + do not have to outlive the context. + + ``type`` specifies what the constructor will build and has to be + a struct. + + ``num_values`` specifies the number of elements in ``values``. + + ``fields`` need to have the same length as ``values``, or be NULL. + + If ``fields`` is null, the values are applied in definition order. + + Otherwise, each field in ``fields`` specifies which field in the struct to + set to the corresponding value in ``values``. ``fields`` and ``values`` + are paired by index. + + The fields in ``fields`` have to be in definition order, but there + can be gaps. Any field in the struct that is not specified in + ``fields`` will be zeroed. + + The fields in ``fields`` need to be the same objects that were used + to create the struct. + + Each value has to have have the same unqualified type as the field + it is applied to. + + A NULL value element in ``values`` is a shorthand for zero initialization + of the corresponding field. + + If ``num_values`` is 0, the array parameters will be + ignored and zero initialization will be used. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_19`; you can test for its + presence using: + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_CTORS + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_union_constructor (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_type *type,\ + gcc_jit_field *field,\ + gcc_jit_rvalue *value) + + Create a constructor for a union as an rvalue. + + Returns NULL on error. + + ``type`` specifies what the constructor will build and has to be + an union. + + ``field`` specifies which field to set. If it is NULL, the first + field in the union will be set.``field`` need to be the same object + that were used to create the union. + + ``value`` specifies what value to set the corresponding field to. + If ``value`` is NULL, zero initialization will be used. + + Each value has to have have the same unqualified type as the field + it is applied to. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_19`; you can test for its + presence using: + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_CTORS + +Vector expressions +****************** + +.. function:: gcc_jit_rvalue * \ + gcc_jit_context_new_rvalue_from_vector (gcc_jit_context *ctxt, \ + gcc_jit_location *loc, \ + gcc_jit_type *vec_type, \ + size_t num_elements, \ + gcc_jit_rvalue **elements) + + Build a vector rvalue from an array of elements. + + "vec_type" should be a vector type, created using + :func:`gcc_jit_type_get_vector`. + + "num_elements" should match that of the vector type. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_10`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector + +Unary Operations +**************** + +.. function:: gcc_jit_rvalue * \ + gcc_jit_context_new_unary_op (gcc_jit_context *ctxt, \ + gcc_jit_location *loc, \ + enum gcc_jit_unary_op op, \ + gcc_jit_type *result_type, \ + gcc_jit_rvalue *rvalue) + + Build a unary operation out of an input rvalue. + + The parameter ``result_type`` must be a numeric type. + +.. enum:: gcc_jit_unary_op + +The available unary operations are: + +.. list-table:: + :header-rows: 1 + + * - Unary Operation + - C equivalent + + * - :c:macro:`GCC_JIT_UNARY_OP_MINUS` + - `-(EXPR)` + * - :c:macro:`GCC_JIT_UNARY_OP_BITWISE_NEGATE` + - `~(EXPR)` + * - :c:macro:`GCC_JIT_UNARY_OP_LOGICAL_NEGATE` + - `!(EXPR)` + * - :c:macro:`GCC_JIT_UNARY_OP_ABS` + - `abs (EXPR)` + +.. c:macro:: GCC_JIT_UNARY_OP_MINUS + + Negate an arithmetic value; analogous to: + + .. code-block:: c + + -(EXPR) + + in C. + +.. c:macro:: GCC_JIT_UNARY_OP_BITWISE_NEGATE + + Bitwise negation of an integer value (one's complement); analogous + to: + + .. code-block:: c + + ~(EXPR) + + in C. + +.. c:macro:: GCC_JIT_UNARY_OP_LOGICAL_NEGATE + + Logical negation of an arithmetic or pointer value; analogous to: + + .. code-block:: c + + !(EXPR) + + in C. + +.. c:macro:: GCC_JIT_UNARY_OP_ABS + + Absolute value of an arithmetic expression; analogous to: + + .. code-block:: c + + abs (EXPR) + + in C. + +Binary Operations +***************** + +.. function:: gcc_jit_rvalue *gcc_jit_context_new_binary_op (gcc_jit_context *ctxt, \ + gcc_jit_location *loc, \ + enum gcc_jit_binary_op op, \ + gcc_jit_type *result_type, \ + gcc_jit_rvalue *a, gcc_jit_rvalue *b) + + Build a binary operation out of two constituent rvalues. + + The parameter ``result_type`` must be a numeric type. + +.. enum:: gcc_jit_binary_op + +The available binary operations are: + +.. list-table:: + :header-rows: 1 + + * - Binary Operation + - C equivalent + + * - :c:macro:`GCC_JIT_BINARY_OP_PLUS` + - `x + y` + * - :c:macro:`GCC_JIT_BINARY_OP_MINUS` + - `x - y` + * - :c:macro:`GCC_JIT_BINARY_OP_MULT` + - `x * y` + * - :c:macro:`GCC_JIT_BINARY_OP_DIVIDE` + - `x / y` + * - :c:macro:`GCC_JIT_BINARY_OP_MODULO` + - `x % y` + * - :c:macro:`GCC_JIT_BINARY_OP_BITWISE_AND` + - `x & y` + * - :c:macro:`GCC_JIT_BINARY_OP_BITWISE_XOR` + - `x ^ y` + * - :c:macro:`GCC_JIT_BINARY_OP_BITWISE_OR` + - `x | y` + * - :c:macro:`GCC_JIT_BINARY_OP_LOGICAL_AND` + - `x && y` + * - :c:macro:`GCC_JIT_BINARY_OP_LOGICAL_OR` + - `x || y` + * - :c:macro:`GCC_JIT_BINARY_OP_LSHIFT` + - `x << y` + * - :c:macro:`GCC_JIT_BINARY_OP_RSHIFT` + - `x >> y` + +.. c:macro:: GCC_JIT_BINARY_OP_PLUS + + Addition of arithmetic values; analogous to: + + .. code-block:: c + + (EXPR_A) + (EXPR_B) + + in C. + + For pointer addition, use :c:func:`gcc_jit_context_new_array_access`. + +.. c:macro:: GCC_JIT_BINARY_OP_MINUS + + Subtraction of arithmetic values; analogous to: + + .. code-block:: c + + (EXPR_A) - (EXPR_B) + + in C. + +.. c:macro:: GCC_JIT_BINARY_OP_MULT + + Multiplication of a pair of arithmetic values; analogous to: + + .. code-block:: c + + (EXPR_A) * (EXPR_B) + + in C. + +.. c:macro:: GCC_JIT_BINARY_OP_DIVIDE + + Quotient of division of arithmetic values; analogous to: + + .. code-block:: c + + (EXPR_A) / (EXPR_B) + + in C. + + The result type affects the kind of division: if the result type is + integer-based, then the result is truncated towards zero, whereas + a floating-point result type indicates floating-point division. + +.. c:macro:: GCC_JIT_BINARY_OP_MODULO + + Remainder of division of arithmetic values; analogous to: + + .. code-block:: c + + (EXPR_A) % (EXPR_B) + + in C. + +.. c:macro:: GCC_JIT_BINARY_OP_BITWISE_AND + + Bitwise AND; analogous to: + + .. code-block:: c + + (EXPR_A) & (EXPR_B) + + in C. + +.. c:macro:: GCC_JIT_BINARY_OP_BITWISE_XOR + + Bitwise exclusive OR; analogous to: + + .. code-block:: c + + (EXPR_A) ^ (EXPR_B) + + in C. + +.. c:macro:: GCC_JIT_BINARY_OP_BITWISE_OR + + Bitwise inclusive OR; analogous to: + + .. code-block:: c + + (EXPR_A) | (EXPR_B) + + in C. + +.. c:macro:: GCC_JIT_BINARY_OP_LOGICAL_AND + + Logical AND; analogous to: + + .. code-block:: c + + (EXPR_A) && (EXPR_B) + + in C. + +.. c:macro:: GCC_JIT_BINARY_OP_LOGICAL_OR + + Logical OR; analogous to: + + .. code-block:: c + + (EXPR_A) || (EXPR_B) + + in C. + +.. c:macro:: GCC_JIT_BINARY_OP_LSHIFT + + Left shift; analogous to: + + .. code-block:: c + + (EXPR_A) << (EXPR_B) + + in C. + +.. c:macro:: GCC_JIT_BINARY_OP_RSHIFT + + Right shift; analogous to: + + .. code-block:: c + + (EXPR_A) >> (EXPR_B) + + in C. + +Comparisons +*********** + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_comparison (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + enum gcc_jit_comparison op,\ + gcc_jit_rvalue *a, gcc_jit_rvalue *b) + + Build a boolean rvalue out of the comparison of two other rvalues. + +.. enum:: gcc_jit_comparison + +.. list-table:: + :header-rows: 1 + + * - Comparison + - C equivalent + + * - :c:macro:`GCC_JIT_COMPARISON_EQ` + - `x == y` + * - :c:macro:`GCC_JIT_COMPARISON_NE` + - `x != y` + * - :c:macro:`GCC_JIT_COMPARISON_LT` + - `x < y` + * - :c:macro:`GCC_JIT_COMPARISON_LE` + - `x <= y` + * - :c:macro:`GCC_JIT_COMPARISON_GT` + - `x > y` + * - :c:macro:`GCC_JIT_COMPARISON_GE` + - `x >= y` + +Function calls +************** +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_call (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_function *func,\ + int numargs , gcc_jit_rvalue **args) + + Given a function and the given table of argument rvalues, construct a + call to the function, with the result as an rvalue. + + .. note:: + + :c:func:`gcc_jit_context_new_call` merely builds a + :c:type:`gcc_jit_rvalue` i.e. an expression that can be evaluated, + perhaps as part of a more complicated expression. + The call *won't* happen unless you add a statement to a function + that evaluates the expression. + + For example, if you want to call a function and discard the result + (or to call a function with ``void`` return type), use + :c:func:`gcc_jit_block_add_eval`: + + .. code-block:: c + + /* Add "(void)printf (arg0, arg1);". */ + gcc_jit_block_add_eval ( + block, NULL, + gcc_jit_context_new_call ( + ctxt, + NULL, + printf_func, + 2, args)); + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_call_through_ptr (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *fn_ptr,\ + int numargs, \ + gcc_jit_rvalue **args) + + Given an rvalue of function pointer type (e.g. from + :c:func:`gcc_jit_context_new_function_ptr_type`), and the given table of + argument rvalues, construct a call to the function pointer, with the + result as an rvalue. + + .. note:: + + The same caveat as for :c:func:`gcc_jit_context_new_call` applies. + +.. function:: void\ + gcc_jit_rvalue_set_bool_require_tail_call (gcc_jit_rvalue *call,\ + int require_tail_call) + + Given an :c:type:`gcc_jit_rvalue` for a call created through + :c:func:`gcc_jit_context_new_call` or + :c:func:`gcc_jit_context_new_call_through_ptr`, mark/clear the + call as needing tail-call optimization. The optimizer will + attempt to optimize the call into a jump instruction; if it is + unable to do do, an error will be emitted. + + This may be useful when implementing functions that use the + continuation-passing style (e.g. for functional programming + languages), in which every function "returns" by calling a + "continuation" function pointer. This call must be + guaranteed to be implemented as a jump, otherwise the program + could consume an arbitrary amount of stack space as it executed. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_6`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_rvalue_set_bool_require_tail_call + +Function pointers +***************** + +Function pointers can be obtained: + + * from a :c:type:`gcc_jit_function` using + :c:func:`gcc_jit_function_get_address`, or + + * from an existing function using + :c:func:`gcc_jit_context_new_rvalue_from_ptr`, + using a function pointer type obtained using + :c:func:`gcc_jit_context_new_function_ptr_type`. + +Type-coercion +************* + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_cast (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *rvalue,\ + gcc_jit_type *type) + + Given an rvalue of T, construct another rvalue of another type. + + Currently only a limited set of conversions are possible: + + * int <-> float + * int <-> bool + * P* <-> Q*, for pointer types P and Q + +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *rvalue,\ + gcc_jit_type *type) + + Given an rvalue of T, bitcast it to another type, meaning that this will + generate a new rvalue by interpreting the bits of ``rvalue`` to the layout + of ``type``. + + The type of rvalue must be the same size as the size of ``type``. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_21`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast + +Lvalues +------- + +.. type:: gcc_jit_lvalue + +An lvalue is something that can of the *left*-hand side of an assignment: +a storage area (such as a variable). It is also usable as an rvalue, +where the rvalue is computed by reading from the storage area. + +.. function:: gcc_jit_object *\ + gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue) + + Upcast an lvalue to be an object. + +.. function:: gcc_jit_rvalue *\ + gcc_jit_lvalue_as_rvalue (gcc_jit_lvalue *lvalue) + + Upcast an lvalue to be an rvalue. + +.. function:: gcc_jit_rvalue *\ + gcc_jit_lvalue_get_address (gcc_jit_lvalue *lvalue,\ + gcc_jit_location *loc) + + Take the address of an lvalue; analogous to: + + .. code-block:: c + + &(EXPR) + + in C. + +.. function:: void\ + gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue *lvalue,\ + enum gcc_jit_tls_model model) + + Make a variable a thread-local variable. + + The "model" parameter determines the thread-local storage model of the "lvalue": + + .. enum:: gcc_jit_tls_model + + .. c:macro:: GCC_JIT_TLS_MODEL_NONE + + Don't set the TLS model. + + .. c:macro:: GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC + + .. c:macro:: GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC + + .. c:macro:: GCC_JIT_TLS_MODEL_INITIAL_EXEC + + .. c:macro:: GCC_JIT_TLS_MODEL_LOCAL_EXEC + + This is analogous to: + + .. code-block:: c + + _Thread_local int foo __attribute__ ((tls_model("MODEL"))); + + in C. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_17`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model + +.. function:: void\ + gcc_jit_lvalue_set_link_section (gcc_jit_lvalue *lvalue,\ + const char *section_name) + + Set the link section of a variable. + The parameter ``section_name`` must be non-NULL and must contain the + leading dot. Analogous to: + + .. code-block:: c + + int variable __attribute__((section(".section"))); + + in C. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_18`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_link_section + +.. function:: void\ + gcc_jit_lvalue_set_register_name (gcc_jit_lvalue *lvalue,\ + const char *reg_name); + + Set the register name of a variable. + The parameter ``reg_name`` must be non-NULL. Analogous to: + + .. code-block:: c + + register int variable asm ("r12"); + + in C. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_22`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_register_name + +.. function:: void\ + gcc_jit_lvalue_set_alignment (gcc_jit_lvalue *lvalue,\ + unsigned bytes) + + Set the alignment of a variable, in bytes. + Analogous to: + + .. code-block:: c + + int variable __attribute__((aligned (16))); + + in C. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_24`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_ALIGNMENT + +.. function:: unsigned\ + gcc_jit_lvalue_get_alignment (gcc_jit_lvalue *lvalue) + + Return the alignment of a variable set by ``gcc_jit_lvalue_set_alignment``. + Return 0 if the alignment was not set. Analogous to: + + .. code-block:: c + + _Alignof (variable) + + in C. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_24`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_ALIGNMENT + +Global variables +**************** + +.. function:: gcc_jit_lvalue *\ + gcc_jit_context_new_global (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + enum gcc_jit_global_kind kind,\ + gcc_jit_type *type,\ + const char *name) + + Add a new global variable of the given type and name to the context. + + The parameter ``type`` must be non-`void`. + + The parameter ``name`` must be non-NULL. The call takes a copy of the + underlying string, so it is valid to pass in a pointer to an on-stack + buffer. + + The "kind" parameter determines the visibility of the "global" outside + of the :c:type:`gcc_jit_result`: + + .. enum:: gcc_jit_global_kind + + .. c:macro:: GCC_JIT_GLOBAL_EXPORTED + + Global is defined by the client code and is visible + by name outside of this JIT context via + :c:func:`gcc_jit_result_get_global` (and this value is required for + the global to be accessible via that entrypoint). + + .. c:macro:: GCC_JIT_GLOBAL_INTERNAL + + Global is defined by the client code, but is invisible + outside of it. Analogous to a "static" global within a .c file. + Specifically, the variable will only be visible within this + context and within child contexts. + + .. c:macro:: GCC_JIT_GLOBAL_IMPORTED + + Global is not defined by the client code; we're merely + referring to it. Analogous to using an "extern" global from a + header file. + +.. function:: gcc_jit_lvalue *\ + gcc_jit_global_set_initializer (gcc_jit_lvalue *global,\ + const void *blob,\ + size_t num_bytes) + + Set an initializer for ``global`` using the memory content pointed + by ``blob`` for ``num_bytes``. ``global`` must be an array of an + integral type. Return the global itself. + + The parameter ``blob`` must be non-NULL. The call copies the memory + pointed by ``blob`` for ``num_bytes`` bytes, so it is valid to pass + in a pointer to an on-stack buffer. The content will be stored in + the compilation unit and used as initialization value of the array. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_14`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer + +.. function:: gcc_jit_lvalue *\ + gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global,\ + gcc_jit_rvalue *init_value) + + Set the initial value of a global with an rvalue. + + The rvalue needs to be a constant expression, e.g. no function calls. + + The global can't have the ``kind`` :c:macro:`GCC_JIT_GLOBAL_IMPORTED`. + + As a non-comprehensive example it is OK to do the equivalent of: + + .. code-block:: c + + int foo = 3 * 2; /* rvalue from gcc_jit_context_new_binary_op. */ + int arr[] = {1,2,3,4}; /* rvalue from gcc_jit_context_new_constructor. */ + int *bar = &arr[2] + 1; /* rvalue from nested "get address" of "array access". */ + const int baz = 3; /* rvalue from gcc_jit_context_rvalue_from_int. */ + int boz = baz; /* rvalue from gcc_jit_lvalue_as_rvalue. */ + + Use together with :c:func:`gcc_jit_context_new_struct_constructor`, + :c:func:`gcc_jit_context_new_union_constructor`, :c:func:`gcc_jit_context_new_array_constructor` + to initialize structs, unions and arrays. + + On success, returns the ``global`` parameter unchanged. Otherwise, ``NULL``. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_19`; you can test for its + presence using: + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_CTORS + +Working with pointers, structs and unions +----------------------------------------- + +.. function:: gcc_jit_lvalue *\ + gcc_jit_rvalue_dereference (gcc_jit_rvalue *rvalue,\ + gcc_jit_location *loc) + + Given an rvalue of pointer type ``T *``, dereferencing the pointer, + getting an lvalue of type ``T``. Analogous to: + + .. code-block:: c + + *(EXPR) + + in C. + +Field access is provided separately for both lvalues and rvalues. + +.. function:: gcc_jit_lvalue *\ + gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_,\ + gcc_jit_location *loc,\ + gcc_jit_field *field) + + Given an lvalue of struct or union type, access the given field, + getting an lvalue of the field's type. Analogous to: + + .. code-block:: c + + (EXPR).field = ...; + + in C. + +.. function:: gcc_jit_rvalue *\ + gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_,\ + gcc_jit_location *loc,\ + gcc_jit_field *field) + + Given an rvalue of struct or union type, access the given field + as an rvalue. Analogous to: + + .. code-block:: c + + (EXPR).field + + in C. + +.. function:: gcc_jit_lvalue *\ + gcc_jit_rvalue_dereference_field (gcc_jit_rvalue *ptr,\ + gcc_jit_location *loc,\ + gcc_jit_field *field) + + Given an rvalue of pointer type ``T *`` where T is of struct or union + type, access the given field as an lvalue. Analogous to: + + .. code-block:: c + + (EXPR)->field + + in C, itself equivalent to ``(*EXPR).FIELD``. + +.. function:: gcc_jit_lvalue *\ + gcc_jit_context_new_array_access (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *ptr,\ + gcc_jit_rvalue *index) + + Given an rvalue of pointer type ``T *``, get at the element `T` at + the given index, using standard C array indexing rules i.e. each + increment of ``index`` corresponds to ``sizeof(T)`` bytes. + Analogous to: + + .. code-block:: c + + PTR[INDEX] + + in C (or, indeed, to ``PTR + INDEX``). diff --git a/gcc/jit/docs/topics/function-pointers.rst b/gcc/jit/docs/topics/function-pointers.rst new file mode 100644 index 0000000..dde4921 --- /dev/null +++ b/gcc/jit/docs/topics/function-pointers.rst @@ -0,0 +1,82 @@ +.. Copyright (C) 2017-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Function pointers +================= + +You can generate calls that use a function pointer via +:c:func:`gcc_jit_context_new_call_through_ptr`. + +To do requires a :c:type:`gcc_jit_rvalue` of the correct function pointer type. + +Function pointers for a :c:type:`gcc_jit_function` can be obtained +via :c:func:`gcc_jit_function_get_address`. + +.. function:: gcc_jit_rvalue *\ + gcc_jit_function_get_address (gcc_jit_function *fn,\ + gcc_jit_location *loc) + + Get the address of a function as an rvalue, of function pointer + type. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_9`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_function_get_address + +Alternatively, given an existing function, you can obtain a pointer +to it in :c:type:`gcc_jit_rvalue` form using +:c:func:`gcc_jit_context_new_rvalue_from_ptr`, using a function pointer +type obtained using :c:func:`gcc_jit_context_new_function_ptr_type`. + +Here's an example of creating a function pointer type corresponding to C's +:expr:`void (*) (int, int, int)`: + +.. code-block:: c + + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + gcc_jit_type *int_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + /* Build the function ptr type. */ + gcc_jit_type *param_types[3]; + param_types[0] = int_type; + param_types[1] = int_type; + param_types[2] = int_type; + + gcc_jit_type *fn_ptr_type = + gcc_jit_context_new_function_ptr_type (ctxt, NULL, + void_type, + 3, param_types, 0); + +.. function:: gcc_jit_type *\ + gcc_jit_context_new_function_ptr_type (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_type *return_type,\ + int num_params,\ + gcc_jit_type **param_types,\ + int is_variadic) + + Generate a :c:type:`gcc_jit_type` for a function pointer with the + given return type and parameters. + + Each of `param_types` must be non-`void`; `return_type` may be `void`. diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst new file mode 100644 index 0000000..d6d4fe9 --- /dev/null +++ b/gcc/jit/docs/topics/functions.rst @@ -0,0 +1,489 @@ +.. Copyright (C) 2014-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Creating and using functions +============================ + +Params +------ +.. type:: gcc_jit_param + + A `gcc_jit_param` represents a parameter to a function. + +.. function:: gcc_jit_param *\ + gcc_jit_context_new_param (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_type *type,\ + const char *name) + + In preparation for creating a function, create a new parameter of the + given type and name. + + The parameter ``type`` must be non-`void`. + + The parameter ``name`` must be non-NULL. The call takes a copy of the + underlying string, so it is valid to pass in a pointer to an on-stack + buffer. + +Parameters are lvalues, and thus are also rvalues (and objects), so the +following upcasts are available: + +.. function:: gcc_jit_lvalue *\ + gcc_jit_param_as_lvalue (gcc_jit_param *param) + + Upcasting from param to lvalue. + +.. function:: gcc_jit_rvalue *\ + gcc_jit_param_as_rvalue (gcc_jit_param *param) + + Upcasting from param to rvalue. + +.. function:: gcc_jit_object *\ + gcc_jit_param_as_object (gcc_jit_param *param) + + Upcasting from param to object. + + +Functions +--------- + +.. type:: gcc_jit_function + + A `gcc_jit_function` represents a function - either one that we're + creating ourselves, or one that we're referencing. + +.. function:: gcc_jit_function *\ + gcc_jit_context_new_function (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + enum gcc_jit_function_kind kind,\ + gcc_jit_type *return_type,\ + const char *name,\ + int num_params,\ + gcc_jit_param **params,\ + int is_variadic) + + Create a gcc_jit_function with the given name and parameters. + + .. enum:: gcc_jit_function_kind + + This enum controls the kind of function created, and has the following + values: + + .. macro:: GCC_JIT_FUNCTION_EXPORTED + + Function is defined by the client code and visible + by name outside of the JIT. + + This value is required if you want to extract machine code + for this function from a :type:`gcc_jit_result` via + :func:`gcc_jit_result_get_code`. + + .. macro:: GCC_JIT_FUNCTION_INTERNAL + + Function is defined by the client code, but is invisible + outside of the JIT. Analogous to a "static" function. + + .. macro:: GCC_JIT_FUNCTION_IMPORTED + + Function is not defined by the client code; we're merely + referring to it. Analogous to using an "extern" function from a + header file. + + .. macro:: GCC_JIT_FUNCTION_ALWAYS_INLINE + + Function is only ever inlined into other functions, and is + invisible outside of the JIT. + + Analogous to prefixing with ``inline`` and adding + ``__attribute__((always_inline))`` + + Inlining will only occur when the optimization level is + above 0; when optimization is off, this is essentially the + same as GCC_JIT_FUNCTION_INTERNAL. + + The parameter ``name`` must be non-NULL. The call takes a copy of the + underlying string, so it is valid to pass in a pointer to an on-stack + buffer. + +.. function:: gcc_jit_function *\ + gcc_jit_context_get_builtin_function (gcc_jit_context *ctxt,\ + const char *name) + + Get the :type:`gcc_jit_function` for the built-in function with the + given name. For example: + + .. code-block:: c + + gcc_jit_function *fn + = gcc_jit_context_get_builtin_function (ctxt, "__builtin_memcpy"); + + .. note:: Due to technical limitations with how libgccjit interacts with + the insides of GCC, not all built-in functions are supported. More + precisely, not all types are supported for parameters of built-in + functions from libgccjit. Attempts to get a built-in function that + uses such a parameter will lead to an error being emitted within + the context. + +.. function:: gcc_jit_object *\ + gcc_jit_function_as_object (gcc_jit_function *func) + + Upcasting from function to object. + +.. function:: gcc_jit_param *\ + gcc_jit_function_get_param (gcc_jit_function *func, int index) + + Get the param of the given index (0-based). + +.. function:: void \ + gcc_jit_function_dump_to_dot (gcc_jit_function *func,\ + const char *path) + + Emit the function in graphviz format to the given path. + +.. function:: gcc_jit_lvalue *\ + gcc_jit_function_new_local (gcc_jit_function *func,\ + gcc_jit_location *loc,\ + gcc_jit_type *type,\ + const char *name) + + Create a new local variable within the function, of the given type and + name. + + The parameter ``type`` must be non-`void`. + + The parameter ``name`` must be non-NULL. The call takes a copy of the + underlying string, so it is valid to pass in a pointer to an on-stack + buffer. + +.. function:: size_t \ + gcc_jit_function_get_param_count (gcc_jit_function *func) + + Get the number of parameters of the function. + +.. function:: gcc_jit_type *\ + gcc_jit_function_get_return_type (gcc_jit_function *func) + + Get the return type of the function. + + The API entrypoints relating to getting info about parameters and return + types: + + * :c:func:`gcc_jit_function_get_return_type` + + * :c:func:`gcc_jit_function_get_param_count` + + were added in :ref:`LIBGCCJIT_ABI_16`; you can test for their presence + using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_REFLECTION + + .. type:: gcc_jit_case + +Blocks +------ +.. type:: gcc_jit_block + + A `gcc_jit_block` represents a basic block within a function i.e. a + sequence of statements with a single entry point and a single exit + point. + + 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:: gcc_jit_block *\ + gcc_jit_function_new_block (gcc_jit_function *func,\ + 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. It is copied, so the input buffer does not need to outlive + the call; you can pass in a pointer to an on-stack buffer, e.g.: + + .. code-block:: c + + for (pc = 0; pc < fn->fn_num_ops; pc++) + { + char buf[16]; + sprintf (buf, "instr%i", pc); + state.op_blocks[pc] = gcc_jit_function_new_block (state.fn, buf); + } + +.. function:: gcc_jit_object *\ + gcc_jit_block_as_object (gcc_jit_block *block) + + Upcast from block to object. + +.. function:: gcc_jit_function *\ + gcc_jit_block_get_function (gcc_jit_block *block) + + Which function is this block within? + + +Statements +---------- + +.. function:: void\ + gcc_jit_block_add_eval (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *rvalue) + + 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\ + gcc_jit_block_add_assignment (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + gcc_jit_lvalue *lvalue,\ + gcc_jit_rvalue *rvalue) + + 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\ + gcc_jit_block_add_assignment_op (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + gcc_jit_lvalue *lvalue,\ + enum gcc_jit_binary_op op,\ + gcc_jit_rvalue *rvalue) + + 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++" */ + gcc_jit_block_add_assignment_op ( + loop_body, NULL, + i, + GCC_JIT_BINARY_OP_PLUS, + gcc_jit_context_one (ctxt, int_type)); + +.. function:: void\ + gcc_jit_block_add_comment (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + const char *text) + + 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 :macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` + and :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. + + The parameter ``text`` must be non-NULL. It is copied, so the input + buffer does not need to outlive the call. For example: + + .. code-block:: c + + char buf[100]; + snprintf (buf, sizeof (buf), + "op%i: %s", + pc, opcode_names[op->op_opcode]); + gcc_jit_block_add_comment (block, loc, buf); + +.. function:: void\ + gcc_jit_block_end_with_conditional (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *boolval,\ + gcc_jit_block *on_true,\ + gcc_jit_block *on_false) + + 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\ + gcc_jit_block_end_with_jump (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + gcc_jit_block *target) + + + 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\ + gcc_jit_block_end_with_return (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *rvalue) + + + Terminate a block by adding evaluation of an rvalue, returning the value. + + This is roughly equivalent to this C code: + + .. code-block:: c + + return expression; + +.. function:: void\ + gcc_jit_block_end_with_void_return (gcc_jit_block *block,\ + gcc_jit_location *loc) + + + Terminate a block 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; + +.. function:: void\ + gcc_jit_block_end_with_switch (gcc_jit_block *block,\ + gcc_jit_location *loc,\ + gcc_jit_rvalue *expr,\ + gcc_jit_block *default_block,\ + int num_cases,\ + gcc_jit_case **cases) + + 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; + } + + ``block``, ``expr``, ``default_block`` and ``cases`` must all be + non-NULL. + + ``expr`` must be of the same integer type as all of the ``min_value`` + and ``max_value`` within the cases. + + ``num_cases`` must be >= 0. + + The ranges of the cases must not overlap (or have duplicate + values). + + The API entrypoints relating to switch statements and cases: + + * :c:func:`gcc_jit_block_end_with_switch` + + * :c:func:`gcc_jit_case_as_object` + + * :c:func:`gcc_jit_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 + + .. type:: gcc_jit_case + + A `gcc_jit_case` represents a case within a switch statement, and + is created within a particular :c:type:`gcc_jit_context` using + :c:func:`gcc_jit_context_new_case`. + + 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:: gcc_jit_case *\ + gcc_jit_context_new_case (gcc_jit_context *ctxt,\ + gcc_jit_rvalue *min_value,\ + gcc_jit_rvalue *max_value,\ + gcc_jit_block *dest_block) + + Create a new gcc_jit_case instance 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:: gcc_jit_object *\ + gcc_jit_case_as_object (gcc_jit_case *case_) + + Upcast from a case to an object. + + Here's an example of creating a switch statement: + + .. literalinclude:: ../../../testsuite/jit.dg/test-switch.c + :start-after: /* Quote from here in docs/topics/functions.rst. */ + :end-before: /* Quote up to here in docs/topics/functions.rst. */ + :language: c + +See also :type:`gcc_jit_extended_asm` for entrypoints for adding inline +assembler statements to a function. diff --git a/gcc/jit/docs/topics/index.rst b/gcc/jit/docs/topics/index.rst new file mode 100644 index 0000000..8e843c2 --- /dev/null +++ b/gcc/jit/docs/topics/index.rst @@ -0,0 +1,34 @@ +.. Copyright (C) 2014-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +Topic Reference +=============== + +.. toctree:: + :maxdepth: 2 + + contexts.rst + objects.rst + types.rst + expressions.rst + functions.rst + function-pointers.rst + locations.rst + compilation.rst + compatibility.rst + performance.rst + asm.rst diff --git a/gcc/jit/docs/topics/locations.rst b/gcc/jit/docs/topics/locations.rst new file mode 100644 index 0000000..c488713 --- /dev/null +++ b/gcc/jit/docs/topics/locations.rst @@ -0,0 +1,73 @@ +.. Copyright (C) 2014-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Source Locations +================ + +.. type:: gcc_jit_location + + A `gcc_jit_location` encapsulates a source code location, so that + you can (optionally) associate locations in your language with + statements in the JIT-compiled code, allowing the debugger to + single-step through your language. + + `gcc_jit_location` instances are optional: you can always pass NULL to + any API entrypoint accepting one. + + You can construct them using :c:func:`gcc_jit_context_new_location`. + + You need to enable :c:macro:`GCC_JIT_BOOL_OPTION_DEBUGINFO` on the + :c:type:`gcc_jit_context` for these locations to actually be usable by + the debugger: + + .. code-block:: c + + gcc_jit_context_set_bool_option ( + ctxt, + GCC_JIT_BOOL_OPTION_DEBUGINFO, + 1); + +.. function:: gcc_jit_location *\ + gcc_jit_context_new_location (gcc_jit_context *ctxt,\ + const char *filename,\ + int line,\ + int column) + + Create a `gcc_jit_location` instance representing the given source + location. + + The parameter ``filename`` must be non-NULL. The call takes a copy of + the underlying string, so it is valid to pass in a pointer to an + on-stack buffer. + +Faking it +--------- +If you don't have source code for your internal representation, but need +to debug, you can generate a C-like representation of the functions in +your context using :c:func:`gcc_jit_context_dump_to_file()`: + +.. code-block:: c + + gcc_jit_context_dump_to_file (ctxt, "/tmp/something.c", + 1 /* update_locations */); + +This will dump C-like code to the given path. If the `update_locations` +argument is true, this will also set up `gcc_jit_location` information +throughout the context, pointing at the dump file as if it were a source +file, giving you *something* you can step through in the debugger. diff --git a/gcc/jit/docs/topics/objects.rst b/gcc/jit/docs/topics/objects.rst new file mode 100644 index 0000000..42f3675 --- /dev/null +++ b/gcc/jit/docs/topics/objects.rst @@ -0,0 +1,88 @@ +.. Copyright (C) 2014-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Objects +======= + +.. type:: gcc_jit_object + +Almost every entity in the API (with the exception of +:c:expr:`gcc_jit_context *` and :c:expr:`gcc_jit_result *`) is a +"contextual" object, a :c:expr:`gcc_jit_object *` + +A JIT object: + + * is associated with a :c:expr:`gcc_jit_context *`. + + * is automatically cleaned up for you when its context is released so + you don't need to manually track and cleanup all objects, just the + contexts. + +Although the API is C-based, there is a form of class hierarchy, which +looks like this:: + + +- gcc_jit_object + +- gcc_jit_location + +- gcc_jit_type + +- gcc_jit_struct + +- gcc_jit_field + +- gcc_jit_function + +- gcc_jit_block + +- gcc_jit_rvalue + +- gcc_jit_lvalue + +- gcc_jit_param + +- gcc_jit_case + +- gcc_jit_extended_asm + +There are casting methods for upcasting from subclasses to parent classes. +For example, :c:func:`gcc_jit_type_as_object`: + +.. code-block:: c + + gcc_jit_object *obj = gcc_jit_type_as_object (int_type); + +The object "base class" has the following operations: + +.. function:: gcc_jit_context *gcc_jit_object_get_context (gcc_jit_object *obj) + + Which context is "obj" within? + + +.. function:: const char *gcc_jit_object_get_debug_string (gcc_jit_object *obj) + + Generate a human-readable description for the given object. + + For example, + + .. code-block:: c + + printf ("obj: %s\n", gcc_jit_object_get_debug_string (obj)); + + might give this text on stdout: + + .. code-block:: bash + + obj: 4.0 * (float)i + + .. note:: + + If you call this on an object, the `const char *` buffer is allocated + and generated on the first call for that object, and the buffer will + have the same lifetime as the object i.e. it will exist until the + object's context is released. diff --git a/gcc/jit/docs/topics/performance.rst b/gcc/jit/docs/topics/performance.rst new file mode 100644 index 0000000..8fc56bd --- /dev/null +++ b/gcc/jit/docs/topics/performance.rst @@ -0,0 +1,240 @@ +.. Copyright (C) 2015-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Performance +=========== + +The timing API +-------------- + +As of GCC 6, libgccjit exposes a timing API, for printing reports on +how long was spent in different parts of code. + +You can create a :c:type:`gcc_jit_timer` instance, which will +measure time spent since its creation. The timer maintains a stack +of "timer items": as control flow moves through your code, you can push +and pop named items relating to your code onto the stack, and the timer +will account the time spent accordingly. + +You can also asssociate a timer with a :c:type:`gcc_jit_context`, in +which case the time spent inside compilation will be subdivided. + +For example, the following code uses a timer, recording client items +"create_code", "compile", and "running code": + +.. code-block:: c + + /* Create a timer. */ + gcc_jit_timer *timer = gcc_jit_timer_new (); + if (!timer) + { + error ("gcc_jit_timer_new failed"); + return -1; + } + + /* Let's repeatedly compile and run some code, accumulating it + all into the timer. */ + for (int i = 0; i < num_iterations; i++) + { + /* Create a context and associate it with the timer. */ + gcc_jit_context *ctxt = gcc_jit_context_acquire (); + if (!ctxt) + { + error ("gcc_jit_context_acquire failed"); + return -1; + } + gcc_jit_context_set_timer (ctxt, timer); + + /* Populate the context, timing it as client item "create_code". */ + gcc_jit_timer_push (timer, "create_code"); + create_code (ctxt); + gcc_jit_timer_pop (timer, "create_code"); + + /* Compile the context, timing it as client item "compile". */ + gcc_jit_timer_push (timer, "compile"); + result = gcc_jit_context_compile (ctxt); + gcc_jit_timer_pop (timer, "compile"); + + /* Run the generated code, timing it as client item "running code". */ + gcc_jit_timer_push (timer, "running code"); + run_the_code (ctxt, result); + gcc_jit_timer_pop (timer, "running code"); + + /* Clean up. */ + gcc_jit_context_release (ctxt); + gcc_jit_result_release (result); + } + + /* Print the accumulated timings. */ + gcc_jit_timer_print (timer, stderr); + gcc_jit_timer_release (timer); + +giving output like this, showing the internal GCC items at the top, then +client items, then the total:: + + Execution times (seconds) + GCC items: + phase setup : 0.29 (14%) usr 0.00 ( 0%) sys 0.32 ( 5%) wall 10661 kB (50%) ggc + phase parsing : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 653 kB ( 3%) ggc + phase finalize : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc + dump files : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc + callgraph construction : 0.02 ( 1%) usr 0.01 ( 6%) sys 0.01 ( 0%) wall 242 kB ( 1%) ggc + callgraph optimization : 0.03 ( 2%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 142 kB ( 1%) ggc + trivially dead code : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc + df scan insns : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 9 kB ( 0%) ggc + df live regs : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc + inline parameters : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 82 kB ( 0%) ggc + tree CFG cleanup : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc + tree PHI insertion : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 64 kB ( 0%) ggc + tree SSA other : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 18 kB ( 0%) ggc + expand : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 398 kB ( 2%) ggc + jump : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc + loop init : 0.01 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 67 kB ( 0%) ggc + integrated RA : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 2468 kB (12%) ggc + thread pro- & epilogue : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 162 kB ( 1%) ggc + final : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 216 kB ( 1%) ggc + rest of compilation : 1.37 (69%) usr 0.00 ( 0%) sys 1.13 (18%) wall 1391 kB ( 6%) ggc + assemble JIT code : 0.01 ( 1%) usr 0.00 ( 0%) sys 4.04 (66%) wall 0 kB ( 0%) ggc + load JIT result : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc + JIT client code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc + Client items: + create_code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc + compile : 0.36 (18%) usr 0.15 (83%) sys 0.86 (14%) wall 14939 kB (70%) ggc + running code : 0.00 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc + TOTAL : 2.00 0.18 6.12 21444 kB + +The exact format is intended to be human-readable, and is subject to change. + +.. macro:: LIBGCCJIT_HAVE_TIMING_API + + The timer API was added to libgccjit in GCC 6. + This macro is only defined in versions of libgccjit.h which have the + timer API, and so can be used to guard code that may need to compile + against earlier releases:: + + #ifdef LIBGCCJIT_HAVE_TIMING_API + gcc_jit_timer *t = gcc_jit_timer_new (); + gcc_jit_context_set_timer (ctxt, t); + #endif + +.. type:: gcc_jit_timer + +.. function:: gcc_jit_timer * gcc_jit_timer_new(void) + + Create a :c:type:`gcc_jit_timer` instance, and start timing:: + + gcc_jit_timer *t = gcc_jit_timer_new (); + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_TIMING_API + +.. function:: void gcc_jit_timer_release(gcc_jit_timer *timer) + + Release a :c:type:`gcc_jit_timer` instance:: + + gcc_jit_timer_release (t); + + This should be called exactly once on a timer. + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_TIMING_API + +.. function:: void gcc_jit_context_set_timer(gcc_jit_context *ctxt, \ + gcc_jit_timer *timer) + + Associate a :c:type:`gcc_jit_timer` instance with a context:: + + gcc_jit_context_set_timer (ctxt, t); + + A timer instance can be shared between multiple + :c:type:`gcc_jit_context` instances. + + Timers have no locking, so if you have a multithreaded program, you + must provide your own locks if more than one thread could be working + with the same timer via timer-associated contexts. + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_TIMING_API + +.. function:: gcc_jit_timer *gcc_jit_context_get_timer(gcc_jit_context *ctxt) + + Get the timer associated with a context (if any). + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_TIMING_API + +.. function:: void gcc_jit_timer_push(gcc_jit_timer *timer, \ + const char *item_name) + + Push the given item onto the timer's stack:: + + gcc_jit_timer_push (t, "running code"); + run_the_code (ctxt, result); + gcc_jit_timer_pop (t, "running code"); + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_TIMING_API + +.. function:: void gcc_jit_timer_pop(gcc_jit_timer *timer, \ + const char *item_name) + + Pop the top item from the timer's stack. + + If "item_name" is provided, it must match that of the top item. + Alternatively, ``NULL`` can be passed in, to suppress checking. + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_TIMING_API + +.. function:: void gcc_jit_timer_print(gcc_jit_timer *timer, \ + FILE *f_out) + + Print timing information to the given stream about activity since + the timer was started. + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_TIMING_API diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst new file mode 100644 index 0000000..457b362 --- /dev/null +++ b/gcc/jit/docs/topics/types.rst @@ -0,0 +1,543 @@ +.. Copyright (C) 2014-2022 Free Software Foundation, Inc. + Originally contributed by David Malcolm <dmalcolm@redhat.com> + + 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 + <https://www.gnu.org/licenses/>. + +.. default-domain:: c + +Types +===== + +.. c:type:: gcc_jit_type + + gcc_jit_type represents a type within the library. + +.. function:: gcc_jit_object *gcc_jit_type_as_object (gcc_jit_type *type) + + Upcast a type to an object. + +Types can be created in several ways: + +* fundamental types can be accessed using + :func:`gcc_jit_context_get_type`: + + .. code-block:: c + + gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); + + See :func:`gcc_jit_context_get_type` for the available types. + +* derived types can be accessed by using functions such as + :func:`gcc_jit_type_get_pointer` and :func:`gcc_jit_type_get_const`: + + .. code-block:: c + + gcc_jit_type *const_int_star = gcc_jit_type_get_pointer (gcc_jit_type_get_const (int_type)); + gcc_jit_type *int_const_star = gcc_jit_type_get_const (gcc_jit_type_get_pointer (int_type)); + +* by creating structures (see below). + +Standard types +-------------- + +.. function:: gcc_jit_type *gcc_jit_context_get_type (gcc_jit_context *ctxt, \ + enum gcc_jit_types type_) + + Access a specific type. The available types are: + + .. list-table:: + :header-rows: 1 + + * - `enum gcc_jit_types` value + - Meaning + + * - :c:data:`GCC_JIT_TYPE_VOID` + - C's ``void`` type. + * - :c:data:`GCC_JIT_TYPE_VOID_PTR` + - C's ``void *``. + * - :c:data:`GCC_JIT_TYPE_BOOL` + - C++'s ``bool`` type; also C99's ``_Bool`` type, aka ``bool`` if using stdbool.h. + * - :c:data:`GCC_JIT_TYPE_CHAR` + - C's ``char`` (of some signedness) + * - :c:data:`GCC_JIT_TYPE_SIGNED_CHAR` + - C's ``signed char`` + * - :c:data:`GCC_JIT_TYPE_UNSIGNED_CHAR` + - C's ``unsigned char`` + * - :c:data:`GCC_JIT_TYPE_SHORT` + - C's ``short`` (signed) + * - :c:data:`GCC_JIT_TYPE_UNSIGNED_SHORT` + - C's ``unsigned short`` + * - :c:data:`GCC_JIT_TYPE_INT` + - C's ``int`` (signed) + * - :c:data:`GCC_JIT_TYPE_UNSIGNED_INT` + - C's ``unsigned int`` + * - :c:data:`GCC_JIT_TYPE_LONG` + - C's ``long`` (signed) + * - :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG` + - C's ``unsigned long`` + * - :c:data:`GCC_JIT_TYPE_LONG_LONG` + - C99's ``long long`` (signed) + * - :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG_LONG` + - C99's ``unsigned long long`` + * - :c:data:`GCC_JIT_TYPE_UINT8_T` + - C99's ``uint8_t`` + * - :c:data:`GCC_JIT_TYPE_UINT16_T` + - C99's ``uint16_t`` + * - :c:data:`GCC_JIT_TYPE_UINT32_T` + - C99's ``uint32_t`` + * - :c:data:`GCC_JIT_TYPE_UINT64_T` + - C99's ``uint64_t`` + * - :c:data:`GCC_JIT_TYPE_UINT128_T` + - C99's ``__uint128_t`` + * - :c:data:`GCC_JIT_TYPE_INT8_T` + - C99's ``int8_t`` + * - :c:data:`GCC_JIT_TYPE_INT16_T` + - C99's ``int16_t`` + * - :c:data:`GCC_JIT_TYPE_INT32_T` + - C99's ``int32_t`` + * - :c:data:`GCC_JIT_TYPE_INT64_T` + - C99's ``int64_t`` + * - :c:data:`GCC_JIT_TYPE_INT128_T` + - C99's ``__int128_t`` + * - :c:data:`GCC_JIT_TYPE_FLOAT` + - + * - :c:data:`GCC_JIT_TYPE_DOUBLE` + - + * - :c:data:`GCC_JIT_TYPE_LONG_DOUBLE` + - + * - :c:data:`GCC_JIT_TYPE_CONST_CHAR_PTR` + - C type: ``(const char *)`` + * - :c:data:`GCC_JIT_TYPE_SIZE_T` + - C's ``size_t`` type + * - :c:data:`GCC_JIT_TYPE_FILE_PTR` + - C type: ``(FILE *)`` + * - :c:data:`GCC_JIT_TYPE_COMPLEX_FLOAT` + - C99's ``_Complex float`` + * - :c:data:`GCC_JIT_TYPE_COMPLEX_DOUBLE` + - C99's ``_Complex double`` + * - :c:data:`GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE` + - C99's ``_Complex long double`` + +.. function:: gcc_jit_type *\ + gcc_jit_context_get_int_type (gcc_jit_context *ctxt, \ + int num_bytes, int is_signed) + + Access the integer type of the given size. + + +Pointers, `const`, and `volatile` +--------------------------------- + +.. function:: gcc_jit_type *gcc_jit_type_get_pointer (gcc_jit_type *type) + + Given type "T", get type "T*". + +.. function:: gcc_jit_type *gcc_jit_type_get_const (gcc_jit_type *type) + + Given type "T", get type "const T". + +.. function:: gcc_jit_type *gcc_jit_type_get_volatile (gcc_jit_type *type) + + Given type "T", get type "volatile T". + +.. function:: gcc_jit_type *\ + gcc_jit_context_new_array_type (gcc_jit_context *ctxt, \ + gcc_jit_location *loc, \ + gcc_jit_type *element_type, \ + int num_elements) + + Given non-`void` type "T", get type "T[N]" (for a constant N). + +.. function:: gcc_jit_type *\ + gcc_jit_type_get_aligned (gcc_jit_type *type, \ + size_t alignment_in_bytes) + + Given non-`void` type "T", get type: + + .. code-block:: c + + T __attribute__ ((aligned (ALIGNMENT_IN_BYTES))) + + The alignment must be a power of two. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_7`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_aligned + +Vector types +------------ + +.. function:: gcc_jit_type *\ + gcc_jit_type_get_vector (gcc_jit_type *type, \ + size_t num_units) + + Given type "T", get type: + + .. code-block:: c + + T __attribute__ ((vector_size (sizeof(T) * num_units)) + + T must be integral or floating point; num_units must be a power of two. + + This can be used to construct a vector type in which operations + are applied element-wise. The compiler will automatically + use SIMD instructions where possible. See: + https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html + + For example, assuming 4-byte ``ints``, then: + + .. code-block:: c + + typedef int v4si __attribute__ ((vector_size (16))); + + can be obtained using: + + .. code-block:: c + + gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, + GCC_JIT_TYPE_INT); + gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4); + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_8`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector + + Vector rvalues can be generated using + :func:`gcc_jit_context_new_rvalue_from_vector`. + + +Structures and unions +--------------------- + +.. c:type:: gcc_jit_struct + +A compound type analagous to a C `struct`. + +.. c:type:: gcc_jit_field + +A field within a :c:type:`gcc_jit_struct`. + +You can model C `struct` types by creating :c:type:`gcc_jit_struct` and +:c:type:`gcc_jit_field` instances, in either order: + +* by creating the fields, then the structure. For example, to model: + + .. code-block:: c + + struct coord {double x; double y; }; + + you could call: + + .. code-block:: c + + gcc_jit_field *field_x = + gcc_jit_context_new_field (ctxt, NULL, double_type, "x"); + gcc_jit_field *field_y = + gcc_jit_context_new_field (ctxt, NULL, double_type, "y"); + gcc_jit_field *fields[2] = {field_x, field_y}; + gcc_jit_struct *coord = + gcc_jit_context_new_struct_type (ctxt, NULL, "coord", 2, fields); + +* by creating the structure, then populating it with fields, typically + to allow modelling self-referential structs such as: + + .. code-block:: c + + struct node { int m_hash; struct node *m_next; }; + + like this: + + .. code-block:: c + + gcc_jit_type *node = + gcc_jit_context_new_opaque_struct (ctxt, NULL, "node"); + gcc_jit_type *node_ptr = + gcc_jit_type_get_pointer (node); + gcc_jit_field *field_hash = + gcc_jit_context_new_field (ctxt, NULL, int_type, "m_hash"); + gcc_jit_field *field_next = + gcc_jit_context_new_field (ctxt, NULL, node_ptr, "m_next"); + gcc_jit_field *fields[2] = {field_hash, field_next}; + gcc_jit_struct_set_fields (node, NULL, 2, fields); + +.. function:: gcc_jit_field *\ + gcc_jit_context_new_field (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_type *type,\ + const char *name) + + Construct a new field, with the given type and name. + + The parameter ``type`` must be non-`void`. + + The parameter ``name`` must be non-NULL. The call takes a copy of the + underlying string, so it is valid to pass in a pointer to an on-stack + buffer. + +.. function:: gcc_jit_field *\ + gcc_jit_context_new_bitfield (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + gcc_jit_type *type,\ + int width,\ + const char *name) + + Construct a new bit field, with the given type width and name. + + The parameter ``name`` must be non-NULL. The call takes a copy of the + underlying string, so it is valid to pass in a pointer to an on-stack + buffer. + + The parameter ``type`` must be an integer type. + + The parameter ``width`` must be a positive integer that does not exceed the + size of ``type``. + + This API entrypoint was added in :ref:`LIBGCCJIT_ABI_12`; you can test + for its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield + +.. function:: gcc_jit_object *\ + gcc_jit_field_as_object (gcc_jit_field *field) + + Upcast from field to object. + +.. function:: gcc_jit_struct *\ + gcc_jit_context_new_struct_type (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + const char *name,\ + int num_fields,\ + gcc_jit_field **fields) + + Construct a new struct type, with the given name and fields. + + The parameter ``name`` must be non-NULL. The call takes a copy of + the underlying string, so it is valid to pass in a pointer to an + on-stack buffer. + +.. function:: gcc_jit_struct *\ + gcc_jit_context_new_opaque_struct (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + const char *name) + + Construct a new struct type, with the given name, but without + specifying the fields. The fields can be omitted (in which case the + size of the struct is not known), or later specified using + :c:func:`gcc_jit_struct_set_fields`. + + The parameter ``name`` must be non-NULL. The call takes a copy of + the underlying string, so it is valid to pass in a pointer to an + on-stack buffer. + +.. function:: gcc_jit_type *\ + gcc_jit_struct_as_type (gcc_jit_struct *struct_type) + + Upcast from struct to type. + +.. function:: void\ + gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,\ + gcc_jit_location *loc,\ + int num_fields,\ + gcc_jit_field **fields) + + Populate the fields of a formerly-opaque struct type. + + This can only be called once on a given struct type. + +.. function:: gcc_jit_type *\ + gcc_jit_context_new_union_type (gcc_jit_context *ctxt,\ + gcc_jit_location *loc,\ + const char *name,\ + int num_fields,\ + gcc_jit_field **fields) + + Construct a new union type, with the given name and fields. + + The parameter ``name`` must be non-NULL. It is copied, so the input + buffer does not need to outlive the call. + + Example of use: + + .. literalinclude:: ../../../testsuite/jit.dg/test-accessing-union.c + :start-after: /* Quote from here in docs/topics/types.rst. */ + :end-before: /* Quote up to here in docs/topics/types.rst. */ + :language: c + +Function pointer types +---------------------- + +Function pointer types can be created using +:c:func:`gcc_jit_context_new_function_ptr_type`. + +Reflection API +-------------- + +.. function:: gcc_jit_type *\ + gcc_jit_type_dyncast_array (gcc_jit_type *type) + + Get the element type of an array type or NULL if it's not an array. + +.. function:: int\ + gcc_jit_type_is_bool (gcc_jit_type *type) + + Return non-zero if the type is a bool. + +.. function:: gcc_jit_function_type *\ + gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type) + + Return the function type if it is one or NULL. + +.. function:: gcc_jit_type *\ + gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type) + + Given a function type, return its return type. + +.. function:: size_t\ + gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type) + + Given a function type, return its number of parameters. + +.. function:: gcc_jit_type *\ + gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,\ + size_t index) + + Given a function type, return the type of the specified parameter. + +.. function:: int\ + gcc_jit_type_is_integral (gcc_jit_type *type) + + Return non-zero if the type is an integral. + +.. function:: gcc_jit_type *\ + gcc_jit_type_is_pointer (gcc_jit_type *type) + + Return the type pointed by the pointer type or NULL if it's not a pointer. + +.. function:: gcc_jit_vector_type *\ + gcc_jit_type_dyncast_vector (gcc_jit_type *type) + + Given a type, return a dynamic cast to a vector type or NULL. + +.. function:: gcc_jit_struct *\ + gcc_jit_type_is_struct (gcc_jit_type *type) + + Given a type, return a dynamic cast to a struct type or NULL. + +.. function:: size_t\ + gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type) + + Given a vector type, return the number of units it contains. + +.. function:: gcc_jit_type *\ + gcc_jit_vector_type_get_element_type (gcc_jit_vector_type * vector_type) + + Given a vector type, return the type of its elements. + +.. function:: gcc_jit_type *\ + gcc_jit_type_unqualified (gcc_jit_type *type) + + Given a type, return the unqualified type, removing "const", "volatile" and + alignment qualifiers. + +.. function:: gcc_jit_field *\ + gcc_jit_struct_get_field (gcc_jit_struct *struct_type,\ + size_t index) + + Get a struct field by index. + +.. function:: size_t\ + gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type) + + Get the number of fields in the struct. + + The API entrypoints related to the reflection API: + + * :c:func:`gcc_jit_function_type_get_return_type` + + * :c:func:`gcc_jit_function_type_get_param_count` + + * :c:func:`gcc_jit_function_type_get_param_type` + + * :c:func:`gcc_jit_type_unqualified` + + * :c:func:`gcc_jit_type_dyncast_array` + + * :c:func:`gcc_jit_type_is_bool` + + * :c:func:`gcc_jit_type_dyncast_function_ptr_type` + + * :c:func:`gcc_jit_type_is_integral` + + * :c:func:`gcc_jit_type_is_pointer` + + * :c:func:`gcc_jit_type_dyncast_vector` + + * :c:func:`gcc_jit_vector_type_get_element_type` + + * :c:func:`gcc_jit_vector_type_get_num_units` + + * :c:func:`gcc_jit_struct_get_field` + + * :c:func:`gcc_jit_type_is_struct` + + * :c:func:`gcc_jit_struct_get_field_count` + + were added in :ref:`LIBGCCJIT_ABI_16`; you can test for their presence + using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_REFLECTION + + .. type:: gcc_jit_case + +.. function:: int\ + gcc_jit_compatible_types (gcc_jit_type *ltype,\ + gcc_jit_type *rtype) + + Return non-zero if the two types are compatible. For instance, + if :c:data:`GCC_JIT_TYPE_UINT64_T` and :c:data:`GCC_JIT_TYPE_UNSIGNED_LONG` + are the same size on the target, this will return non-zero. + The parameters ``ltype`` and ``rtype`` must be non-NULL. + Return 0 on errors. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_20`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS + +.. function:: ssize_t\ + gcc_jit_type_get_size (gcc_jit_type *type) + + Return the size of a type, in bytes. It only works on integer types for now. + The parameter ``type`` must be non-NULL. + Return -1 on errors. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_20`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS |