summaryrefslogtreecommitdiff
path: root/gcc/jit/docs/cp/topics/asm.rst
blob: 4a59682782c4175ad7c2ca5629c0b477bed9a4fb (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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
.. Copyright (C) 2020-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
   <https://www.gnu.org/licenses/>.

.. default-domain:: cpp

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
***********************************************

.. class:: gccjit::extended_asm

   A `gccjit::extended_asm` represents an extended ``asm`` statement: a
   series of low-level instructions inside a function that convert inputs
   to outputs.

   :class:`gccjit::extended_asm` is a subclass of :class:`gccjit::object`.
   It is a thin wrapper around the C API's :c:type:`gcc_jit_extended_asm *`.

   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:`gccjit::extended_asm`,
   followed by calls to add operands and set other properties of the
   statement.

   There are two API entrypoints for creating a :type:`gccjit::extended_asm`:

   * :func:`gccjit::block::add_extended_asm` for an ``asm`` statement with
     no control flow, and

   * :func:`gccjit::block::end_with_extended_asm_goto` for an ``asm goto``.

   For example, to create the equivalent of:

   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
      :start-after: // Quote from here in docs/cp/topics/asm.rst: example 1: C
      :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 1: C
      :language: c

   the following API calls could be used:

   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 1: jit.  */
      :end-before: /* Quote up to here in docs/cp/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:`gccjit::extended_asm::add_output_operand` and
		 :func:`gccjit::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.cc
      :start-after: // Quote from here in docs/cp/topics/asm.rst: example 2: C
      :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 2: C
      :language: c

   the following API calls could be used:

   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 2: jit.  */
      :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 2: jit.  */
      :language: c

.. function:: extended_asm \
	      gccjit::block::add_extended_asm (const std::string &asm_template,\
                                               gccjit::location loc = location ())

   Create a :type:`gccjit::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:: extended_asm\
              gccjit::block::end_with_extended_asm_goto (const std::string &asm_template,\
                                                         std::vector<block> goto_blocks,\
                                                         block *fallthrough_block,\
                                                         location loc = location ())

   Create a :type:`gccjit::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.cc
      :start-after: // Quote from here in docs/cp/topics/asm.rst: example 3b: C
      :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 3b: C
      :language: c

   the following API calls could be used:

   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 3: jit.  */
      :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 3: jit.  */
      :language: c

   here referencing a :type:`gcc_jit_block` named "carry".

   ``num_goto_blocks`` 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:`gccjit::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:: gccjit::extended_asm &\
	      gccjit::extended_asm::set_volatile_flag (bool flag)

   Set whether the :type:`gccjit::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.cc
      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 4: jit.  */
      :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 4: jit.  */
      :language: c

   where the :type:`gccjit::extended_asm` is flagged as volatile.

.. function::  gccjit::extended_asm &\
	       gccjit::extended_asm::set_inline_flag (bool 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:: gccjit::extended_asm&\
	      gccjit::extended_asm::add_output_operand (const std::string &asm_symbolic_name,\
                                                        const std::string &constraint,\
                                                        gccjit::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, and specifies the symbolic name for the operand.
   See the overload below for an alternative that does not supply a symbolic
   name.

   ``constraint`` corresponds to the ``constraint`` component of C's extended
   ``asm`` syntax.

   ``dest`` corresponds to the ``cvariablename`` component of C's extended
   ``asm`` syntax.

   .. code-block:: c++

      // Example with a symbolic name ("aIndex"), the equivalent of:
      //   : [aIndex] "=r" (index)
      ext_asm.add_output_operand ("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:: gccjit::extended_asm&\
              gccjit::extended_asm::add_output_operand (const std::string &constraint,\
                                                        gccjit::lvalue dest)

   As above, but don't supply a symbolic name for the operand.

   .. code-block:: c++

      // Example without a symbolic name, the equivalent of:
      //   : "=r" (dst)
      ext_asm.add_output_operand ("=r", dst);

.. function:: gccjit::extended_asm&\
              gccjit::extended_asm::add_input_operand (const std::string &asm_symbolic_name, \
                                                       const std::string &constraint, \
                                                       gccjit::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.  See the overload below for an alternative
   that does not supply a symbolic name.

   ``constraint`` corresponds to the ``constraint`` component of C's extended
   ``asm`` syntax.

   ``src`` corresponds to the ``cexpression`` component of C's extended
   ``asm`` syntax.

   .. code-block:: c++

      // Example with a symbolic name ("aMask"), the equivalent of:
      //   : [aMask] "r" (Mask)
      ext_asm.add_input_operand ("aMask", "r", mask);

.. function:: gccjit::extended_asm&\
              gccjit::extended_asm::add_input_operand (const std::string &constraint,\
                                                       gccjit::rvalue src)

   As above, but don't supply a symbolic name for the operand.

   .. code-block:: c++

      // Example without a symbolic name, the equivalent of:
      //   : "r" (src)
      ext_asm.add_input_operand ("r", src);

.. function:: gccjit::extended_asm&\
              gccjit::extended_asm::add_clobber (const std::string &victim)

   Add `victim` to the list of registers clobbered by the extended ``asm``
   statement.  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++

     ext_asm.add_clobber ("r0").add_clobber ("cc").add_clobber ("memory");


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\
              gccjit::context::add_top_level_asm (const char *asm_stmts,\
                                                  gccjit::location loc = location ())

   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.cc
      :start-after: // Quote from here in docs/cp/topics/asm.rst: example 5: C
      :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 5: C
      :language: c

   the following API calls could be used:

   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 5: jit.  */
      :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 5: jit.  */
      :language: c