summaryrefslogtreecommitdiff
path: root/gcc/jit/docs/topics/compilation.rst
blob: b6ace12120f5ed48ff0084e8391b8d181302c4be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
.. Copyright (C) 2014-2021 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
   <http://www.gnu.org/licenses/>.

.. default-domain:: c

Compiling a context
===================

Once populated, a :c:type:`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
   :type:`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 :c:type:`int` this is
   an :c:type:`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
   :type:`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.

.. 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:type:`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:type:`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.

.. type:: enum gcc_jit_output_kind

The available kinds of output are:

==============================================  ==============
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.

   There is currently no support for specifying other libraries to link
   against.

.. c:macro:: GCC_JIT_OUTPUT_KIND_EXECUTABLE

   Compile the context to an executable.

   There is currently no support for specifying libraries to link
   against.