1.. Copyright (C) 2014-2021 Free Software Foundation, Inc.
2   Originally contributed by David Malcolm <dmalcolm@redhat.com>
3
4   This is free software: you can redistribute it and/or modify it
5   under the terms of the GNU General Public License as published by
6   the Free Software Foundation, either version 3 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program.  If not, see
16   <http://www.gnu.org/licenses/>.
17
18Internals
19=========
20
21Working on the JIT library
22--------------------------
23Having checked out the source code (to "src"), you can configure and build
24the JIT library like this:
25
26.. code-block:: bash
27
28  mkdir build
29  mkdir install
30  PREFIX=$(pwd)/install
31  cd build
32  ../src/configure \
33     --enable-host-shared \
34     --enable-languages=jit,c++ \
35     --disable-bootstrap \
36     --enable-checking=release \
37     --prefix=$PREFIX
38  nice make -j4 # altering the "4" to however many cores you have
39
40This should build a libgccjit.so within jit/build/gcc:
41
42.. code-block:: console
43
44 [build] $ file gcc/libgccjit.so*
45 gcc/libgccjit.so:       symbolic link to `libgccjit.so.0'
46 gcc/libgccjit.so.0:     symbolic link to `libgccjit.so.0.0.1'
47 gcc/libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped
48
49Here's what those configuration options mean:
50
51.. option:: --enable-host-shared
52
53  Configuring with this option means that the compiler is built as
54  position-independent code, which incurs a slight performance hit,
55  but it necessary for a shared library.
56
57.. option:: --enable-languages=jit,c++
58
59  This specifies which frontends to build.  The JIT library looks like
60  a frontend to the rest of the code.
61
62  The C++ portion of the JIT test suite requires the C++ frontend to be
63  enabled at configure-time, or you may see errors like this when
64  running the test suite:
65
66  .. code-block:: console
67
68    xgcc: error: /home/david/jit/src/gcc/testsuite/jit.dg/test-quadratic.cc: C++ compiler not installed on this system
69    c++: error trying to exec 'cc1plus': execvp: No such file or directory
70
71.. option:: --disable-bootstrap
72
73  For hacking on the "jit" subdirectory, performing a full
74  bootstrap can be overkill, since it's unused by a bootstrap.  However,
75  when submitting patches, you should remove this option, to ensure that
76  the compiler can still bootstrap itself.
77
78.. option:: --enable-checking=release
79
80  The compile can perform extensive self-checking as it runs, useful when
81  debugging, but slowing things down.
82
83  For maximum speed, configure with ``--enable-checking=release`` to
84  disable this self-checking.
85
86Running the test suite
87----------------------
88
89.. code-block:: console
90
91  [build] $ cd gcc
92  [gcc] $ make check-jit RUNTESTFLAGS="-v -v -v"
93
94A summary of the tests can then be seen in:
95
96.. code-block:: console
97
98  jit/build/gcc/testsuite/jit/jit.sum
99
100and detailed logs in:
101
102.. code-block:: console
103
104  jit/build/gcc/testsuite/jit/jit.log
105
106The test executables are normally deleted after each test is run.  For
107debugging, they can be preserved by setting :envvar:`PRESERVE_EXECUTABLES`
108in the environment.  If so, they can then be seen as:
109
110.. code-block:: console
111
112  jit/build/gcc/testsuite/jit/*.exe
113
114which can be run independently.
115
116You can compile and run individual tests by passing "jit.exp=TESTNAME" to RUNTESTFLAGS e.g.:
117
118.. code-block:: console
119
120   [gcc] $ PRESERVE_EXECUTABLES= \
121             make check-jit \
122               RUNTESTFLAGS="-v -v -v jit.exp=test-factorial.c"
123
124and once a test has been compiled, you can debug it directly:
125
126.. code-block:: console
127
128   [gcc] $ PATH=.:$PATH \
129           LD_LIBRARY_PATH=. \
130           LIBRARY_PATH=. \
131             gdb --args \
132               testsuite/jit/test-factorial.c.exe
133
134Running under valgrind
135**********************
136
137The jit testsuite detects if :envvar:`RUN_UNDER_VALGRIND` is present in the
138environment (with any value).  If it is present, it runs the test client
139code under `valgrind <http://valgrind.org>`_,
140specifcally, the default
141`memcheck <http://valgrind.org/docs/manual/mc-manual.html>`_
142tool with
143`--leak-check=full
144<http://valgrind.org/docs/manual/mc-manual.html#opt.leak-check>`_.
145
146It automatically parses the output from valgrind, injecting XFAIL results if
147any issues are found, or PASS results if the output is clean.  The output
148is saved to ``TESTNAME.exe.valgrind.txt``.
149
150For example, the following invocation verbosely runs the testcase
151``test-sum-of-squares.c`` under valgrind, showing an issue:
152
153.. code-block:: console
154
155  $ RUN_UNDER_VALGRIND= \
156      make check-jit \
157        RUNTESTFLAGS="-v -v -v jit.exp=test-sum-of-squares.c"
158
159  (...verbose log contains detailed valgrind errors, if any...)
160
161                  === jit Summary ===
162
163  # of expected passes            28
164  # of expected failures          2
165
166  $ less testsuite/jit/jit.sum
167  (...other results...)
168  XFAIL: jit.dg/test-sum-of-squares.c: test-sum-of-squares.c.exe.valgrind.txt: definitely lost: 8 bytes in 1 blocks
169  XFAIL: jit.dg/test-sum-of-squares.c: test-sum-of-squares.c.exe.valgrind.txt: unsuppressed errors: 1
170  (...other results...)
171
172  $ less testsuite/jit/test-sum-of-squares.c.exe.valgrind.txt
173  (...shows full valgrind report for this test case...)
174
175When running under valgrind, it's best to have configured gcc with
176:option:`--enable-valgrind-annotations`, which automatically suppresses
177various known false positives.
178
179Environment variables
180---------------------
181When running client code against a locally-built libgccjit, three
182environment variables need to be set up:
183
184.. envvar:: LD_LIBRARY_PATH
185
186   `libgccjit.so` is dynamically linked into client code, so if running
187   against a locally-built library, ``LD_LIBRARY_PATH`` needs to be set
188   up appropriately.  The library can be found within the "gcc"
189   subdirectory of the build tree:
190
191  .. code-block:: console
192
193    $ file libgccjit.so*
194    libgccjit.so:       symbolic link to `libgccjit.so.0'
195    libgccjit.so.0:     symbolic link to `libgccjit.so.0.0.1'
196    libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, not stripped
197
198.. envvar:: PATH
199
200  The library uses a driver executable for converting from .s assembler
201  files to .so shared libraries.  Specifically, it looks for a name
202  expanded from
203  ``${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}``
204  such as ``x86_64-unknown-linux-gnu-gcc-5.0.0``.
205
206  Hence ``PATH`` needs to include a directory where the library can
207  locate this executable.
208
209  The executable is normally installed to the installation bindir
210  (e.g. /usr/bin), but a copy is also created within the "gcc"
211  subdirectory of the build tree for running the testsuite, and for ease
212  of development.
213
214.. envvar:: LIBRARY_PATH
215
216  The driver executable invokes the linker, and the latter needs to locate
217  support libraries needed by the generated code, or you will see errors
218  like:
219
220  .. code-block:: console
221
222    ld: cannot find crtbeginS.o: No such file or directory
223    ld: cannot find -lgcc
224    ld: cannot find -lgcc_s
225
226  Hence if running directly from a locally-built copy (without installing),
227  ``LIBRARY_PATH`` needs to contain the "gcc" subdirectory of the build
228  tree.
229
230For example, to run a binary that uses the library against a non-installed
231build of the library in LIBGCCJIT_BUILD_DIR you need an invocation of the
232client code like this, to preprend the dir to each of the environment
233variables:
234
235.. code-block:: console
236
237  $ LD_LIBRARY_PATH=$(LIBGCCJIT_BUILD_DIR):$(LD_LIBRARY_PATH) \
238    PATH=$(LIBGCCJIT_BUILD_DIR):$(PATH) \
239    LIBRARY_PATH=$(LIBGCCJIT_BUILD_DIR):$(LIBRARY_PATH) \
240      ./jit-hello-world
241  hello world
242
243Packaging notes
244---------------
245The configure-time option :option:`--enable-host-shared` is needed when
246building the jit in order to get position-independent code.  This will
247slow down the regular compiler by a few percent.  Hence when packaging gcc
248with libgccjit, please configure and build twice:
249
250  * once without :option:`--enable-host-shared` for most languages, and
251
252  * once with :option:`--enable-host-shared` for the jit
253
254For example:
255
256.. code-block:: bash
257
258  # Configure and build with --enable-host-shared
259  # for the jit:
260  mkdir configuration-for-jit
261  pushd configuration-for-jit
262  $(SRCDIR)/configure \
263    --enable-host-shared \
264    --enable-languages=jit \
265    --prefix=$(DESTDIR)
266  make
267  popd
268
269  # Configure and build *without* --enable-host-shared
270  # for maximum speed:
271  mkdir standard-configuration
272  pushd standard-configuration
273  $(SRCDIR)/configure \
274    --enable-languages=all \
275    --prefix=$(DESTDIR)
276  make
277  popd
278
279  # Both of the above are configured to install to $(DESTDIR)
280  # Install the configuration with --enable-host-shared first
281  # *then* the one without, so that the faster build
282  # of "cc1" et al overwrites the slower build.
283  pushd configuration-for-jit
284  make install
285  popd
286
287  pushd standard-configuration
288  make install
289  popd
290
291Overview of code structure
292--------------------------
293
294The library is implemented in C++.  The source files have the ``.c``
295extension for legacy reasons.
296
297* ``libgccjit.c`` implements the API entrypoints.  It performs error
298  checking, then calls into classes of the gcc::jit::recording namespace
299  within ``jit-recording.c`` and ``jit-recording.h``.
300
301* The gcc::jit::recording classes (within ``jit-recording.c`` and
302  ``jit-recording.h``) record the API calls that are made:
303
304   .. literalinclude:: ../../jit-common.h
305    :start-after: /* Recording types.  */
306    :end-before: /* End of recording types. */
307    :language: c++
308
309* When the context is compiled, the gcc::jit::playback classes (within
310  ``jit-playback.c`` and ``jit-playback.h``) replay the API calls
311  within langhook:parse_file:
312
313   .. literalinclude:: ../../jit-common.h
314    :start-after: /* Playback types.  */
315    :end-before: /* End of playback types. */
316    :language: c++
317
318   .. literalinclude:: ../../notes.txt
319    :lines: 1-
320
321Here is a high-level summary from ``jit-common.h``:
322
323.. include:: ../../jit-common.h
324  :start-after: This comment is included by the docs.
325  :end-before: End of comment for inclusion in the docs.  */
326
327.. _example-of-log-file:
328
329Another way to understand the structure of the code is to enable logging,
330via :c:func:`gcc_jit_context_set_logfile`.  Here is an example of a log
331generated via this call:
332
333.. literalinclude:: test-hello-world.exe.log.txt
334    :lines: 1-
335
336Design notes
337------------
338It should not be possible for client code to cause an internal compiler
339error.  If this *does* happen, the root cause should be isolated (perhaps
340using :c:func:`gcc_jit_context_dump_reproducer_to_file`) and the cause
341should be rejected via additional checking.  The checking ideally should
342be within the libgccjit API entrypoints in libgccjit.c, since this is as
343close as possible to the error; failing that, a good place is within
344``recording::context::validate ()`` in jit-recording.c.
345
346Submitting patches
347------------------
348Please read the contribution guidelines for gcc at
349https://gcc.gnu.org/contribute.html.
350
351Patches for the jit should be sent to both the
352gcc-patches@gcc.gnu.org and jit@gcc.gnu.org mailing lists,
353with "jit" and "PATCH" in the Subject line.
354
355You don't need to do a full bootstrap for code that just touches the
356``jit`` and ``testsuite/jit.dg`` subdirectories.  However, please run
357``make check-jit`` before submitting the patch, and mention the results
358in your email (along with the host triple that the tests were run on).
359
360A good patch should contain the information listed in the
361gcc contribution guide linked to above; for a ``jit`` patch, the patch
362shold contain:
363
364  * the code itself (for example, a new API entrypoint will typically
365    touch ``libgccjit.h`` and ``.c``, along with support code in
366    ``jit-recording.[ch]`` and ``jit-playback.[ch]`` as appropriate)
367
368  * test coverage
369
370  * documentation for the C API
371
372  * documentation for the C++ API
373
374A patch that adds new API entrypoints should also contain:
375
376  * a feature macro in ``libgccjit.h`` so that client code that doesn't
377    use a "configure" mechanism can still easily detect the presence of
378    the entrypoint.  See e.g. ``LIBGCCJIT_HAVE_SWITCH_STATEMENTS`` (for
379    a category of entrypoints) and
380    ``LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks``
381    (for an individual entrypoint).
382
383  * a new ABI tag containing the new symbols (in ``libgccjit.map``), so
384    that we can detect client code that uses them
385
386  * Support for :c:func:`gcc_jit_context_dump_reproducer_to_file`.  Most
387    jit testcases attempt to dump their contexts to a .c file; ``jit.exp``
388    then sanity-checks the generated c by compiling them (though
389    not running them).   A new API entrypoint
390    needs to "know" how to write itself back out to C (by implementing
391    ``gcc::jit::recording::memento::write_reproducer`` for the appropriate
392    ``memento`` subclass).
393
394  * C++ bindings for the new entrypoints (see ``libgccjit++.h``); ideally
395    with test coverage, though the C++ API test coverage is admittedly
396    spotty at the moment
397
398  * documentation for the new C entrypoints
399
400  * documentation for the new C++ entrypoints
401
402  * documentation for the new ABI tag (see ``topics/compatibility.rst``).
403
404Depending on the patch you can either extend an existing test case, or
405add a new test case.  If you add an entirely new testcase: ``jit.exp``
406expects jit testcases to begin with ``test-``, or ``test-error-`` (for a
407testcase that generates an error on a :c:type:`gcc_jit_context`).
408
409Every new testcase that doesn't generate errors should also touch
410``gcc/testsuite/jit.dg/all-non-failing-tests.h``:
411
412  * Testcases that don't generate errors should ideally be added to the
413    ``testcases`` array in that file; this means that, in addition
414    to being run standalone, they also get run within
415    ``test-combination.c`` (which runs all successful tests inside one
416    big :c:type:`gcc_jit_context`), and ``test-threads.c`` (which runs all
417    successful tests in one process, each one running in a different
418    thread on a different :c:type:`gcc_jit_context`).
419
420    .. note::
421
422       Given that exported functions within a :c:type:`gcc_jit_context`
423       must have unique names, and most testcases are run within
424       ``test-combination.c``, this means that every jit-compiled test
425       function typically needs a name that's unique across the entire
426       test suite.
427
428  * Testcases that aren't to be added to the ``testcases`` array should
429    instead add a comment to the file clarifying why they're not in that
430    array. See the file for examples.
431
432Typically a patch that touches the .rst documentation will also need the
433texinfo to be regenerated.  You can do this with
434`Sphinx 1.0 <http://sphinx-doc.org/>`_ or later by
435running ``make texinfo`` within ``SRCDIR/gcc/jit/docs``.   Don't do this
436within the patch sent to the mailing list; it can often be relatively
437large and inconsequential (e.g. anchor renumbering), rather like generated
438"configure" changes from configure.ac.  You can regenerate it when
439committing to svn.
440