1.. Copyright (C) 2020-2022 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   <https://www.gnu.org/licenses/>.
17
18.. default-domain:: cpp
19
20Using Assembly Language with libgccjit++
21========================================
22
23libgccjit has some support for directly embedding assembler instructions.
24This is based on GCC's support for inline ``asm`` in C code, and the
25following assumes a familiarity with that functionality.  See
26`How to Use Inline Assembly Language in C Code <https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html>`_
27in GCC's documentation, the "Extended Asm" section in particular.
28
29These entrypoints were added in :ref:`LIBGCCJIT_ABI_15`; you can test
30for their presence using
31
32   .. code-block:: c
33
34      #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS
35
36Adding assembler instructions within a function
37***********************************************
38
39.. class:: gccjit::extended_asm
40
41   A `gccjit::extended_asm` represents an extended ``asm`` statement: a
42   series of low-level instructions inside a function that convert inputs
43   to outputs.
44
45   :class:`gccjit::extended_asm` is a subclass of :class:`gccjit::object`.
46   It is a thin wrapper around the C API's :c:type:`gcc_jit_extended_asm *`.
47
48   To avoid having an API entrypoint with a very large number of
49   parameters, an extended ``asm`` statement is made in stages:
50   an initial call to create the :type:`gccjit::extended_asm`,
51   followed by calls to add operands and set other properties of the
52   statement.
53
54   There are two API entrypoints for creating a :type:`gccjit::extended_asm`:
55
56   * :func:`gccjit::block::add_extended_asm` for an ``asm`` statement with
57     no control flow, and
58
59   * :func:`gccjit::block::end_with_extended_asm_goto` for an ``asm goto``.
60
61   For example, to create the equivalent of:
62
63   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
64      :start-after: // Quote from here in docs/cp/topics/asm.rst: example 1: C
65      :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 1: C
66      :language: c
67
68   the following API calls could be used:
69
70   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
71      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 1: jit.  */
72      :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 1: jit.  */
73      :language: c
74
75   .. warning::  When considering the numbering of operands within an
76		 extended ``asm`` statement (e.g. the ``%0`` and ``%1``
77		 above), the equivalent to the C syntax is followed i.e. all
78		 output operands, then all input operands, regardless of
79		 what order the calls to
80		 :func:`gccjit::extended_asm::add_output_operand` and
81		 :func:`gccjit::extended_asm::add_input_operand` were made in.
82
83   As in the C syntax, operands can be given symbolic names to avoid having
84   to number them.  For example, to create the equivalent of:
85
86   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
87      :start-after: // Quote from here in docs/cp/topics/asm.rst: example 2: C
88      :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 2: C
89      :language: c
90
91   the following API calls could be used:
92
93   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
94      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 2: jit.  */
95      :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 2: jit.  */
96      :language: c
97
98.. function:: extended_asm \
99	      gccjit::block::add_extended_asm (const std::string &asm_template,\
100                                               gccjit::location loc = location ())
101
102   Create a :type:`gccjit::extended_asm` for an extended ``asm`` statement
103   with no control flow (i.e. without the ``goto`` qualifier).
104
105   The parameter ``asm_template`` corresponds to the `AssemblerTemplate`
106   within C's extended ``asm`` syntax.  It must be non-NULL.  The call takes
107   a copy of the underlying string, so it is valid to pass in a pointer to
108   an on-stack buffer.
109
110.. function:: extended_asm\
111              gccjit::block::end_with_extended_asm_goto (const std::string &asm_template,\
112                                                         std::vector<block> goto_blocks,\
113                                                         block *fallthrough_block,\
114                                                         location loc = location ())
115
116   Create a :type:`gccjit::extended_asm` for an extended ``asm`` statement
117   that may perform jumps, and use it to terminate the given block.
118   This is equivalent to the ``goto`` qualifier in C's extended ``asm``
119   syntax.
120
121   For example, to create the equivalent of:
122
123   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
124      :start-after: // Quote from here in docs/cp/topics/asm.rst: example 3b: C
125      :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 3b: C
126      :language: c
127
128   the following API calls could be used:
129
130   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
131      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 3: jit.  */
132      :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 3: jit.  */
133      :language: c
134
135   here referencing a :type:`gcc_jit_block` named "carry".
136
137   ``num_goto_blocks`` corresponds to the ``GotoLabels`` parameter within C's
138   extended ``asm`` syntax.  The block names can be referenced within the
139   assembler template.
140
141   ``fallthrough_block`` can be NULL.  If non-NULL, it specifies the block
142   to fall through to after the statement.
143
144   .. note:: This is needed since each :type:`gccjit::block` must have a
145	     single exit point, as a basic block: you can't jump from the
146	     middle of a block.  A "goto" is implicitly added after the
147	     asm to handle the fallthrough case, which is equivalent to what
148	     would have happened in the C case.
149
150.. function:: gccjit::extended_asm &\
151	      gccjit::extended_asm::set_volatile_flag (bool flag)
152
153   Set whether the :type:`gccjit::extended_asm` has side-effects, equivalent to the
154   `volatile <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile>`_
155   qualifier in C's extended asm syntax.
156
157   For example, to create the equivalent of:
158
159   .. code-block:: c
160
161      asm volatile ("rdtsc\n\t"    // Returns the time in EDX:EAX.
162                     "shl $32, %%rdx\n\t"  // Shift the upper bits left.
163                     "or %%rdx, %0"        // 'Or' in the lower bits.
164                     : "=a" (msr)
165                     :
166                     : "rdx");
167
168   the following API calls could be used:
169
170   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
171      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 4: jit.  */
172      :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 4: jit.  */
173      :language: c
174
175   where the :type:`gccjit::extended_asm` is flagged as volatile.
176
177.. function::  gccjit::extended_asm &\
178	       gccjit::extended_asm::set_inline_flag (bool flag)
179
180   Set the equivalent of the
181   `inline <https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm>`_
182   qualifier in C's extended ``asm`` syntax.
183
184.. function:: gccjit::extended_asm&\
185	      gccjit::extended_asm::add_output_operand (const std::string &asm_symbolic_name,\
186                                                        const std::string &constraint,\
187                                                        gccjit::lvalue dest)
188
189   Add an output operand to the extended ``asm`` statement.  See the
190   `Output Operands <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands>`_
191   section of the documentation of the C syntax.
192
193   ``asm_symbolic_name`` corresponds to the ``asmSymbolicName`` component of
194   C's extended ``asm`` syntax, and specifies the symbolic name for the operand.
195   See the overload below for an alternative that does not supply a symbolic
196   name.
197
198   ``constraint`` corresponds to the ``constraint`` component of C's extended
199   ``asm`` syntax.
200
201   ``dest`` corresponds to the ``cvariablename`` component of C's extended
202   ``asm`` syntax.
203
204   .. code-block:: c++
205
206      // Example with a symbolic name ("aIndex"), the equivalent of:
207      //   : [aIndex] "=r" (index)
208      ext_asm.add_output_operand ("aIndex", "=r", index);
209
210   This function can't be called on an ``asm goto`` as such instructions can't
211   have outputs; see the
212   `Goto Labels <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels>`_
213   section of GCC's "Extended Asm" documentation.
214
215.. function:: gccjit::extended_asm&\
216              gccjit::extended_asm::add_output_operand (const std::string &constraint,\
217                                                        gccjit::lvalue dest)
218
219   As above, but don't supply a symbolic name for the operand.
220
221   .. code-block:: c++
222
223      // Example without a symbolic name, the equivalent of:
224      //   : "=r" (dst)
225      ext_asm.add_output_operand ("=r", dst);
226
227.. function:: gccjit::extended_asm&\
228              gccjit::extended_asm::add_input_operand (const std::string &asm_symbolic_name, \
229                                                       const std::string &constraint, \
230                                                       gccjit::rvalue src)
231
232   Add an input operand to the extended ``asm`` statement.  See the
233   `Input Operands <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands>`_
234   section of the documentation of the C syntax.
235
236   ``asm_symbolic_name`` corresponds to the ``asmSymbolicName`` component
237   of C's extended ``asm`` syntax.  See the overload below for an alternative
238   that does not supply a symbolic name.
239
240   ``constraint`` corresponds to the ``constraint`` component of C's extended
241   ``asm`` syntax.
242
243   ``src`` corresponds to the ``cexpression`` component of C's extended
244   ``asm`` syntax.
245
246   .. code-block:: c++
247
248      // Example with a symbolic name ("aMask"), the equivalent of:
249      //   : [aMask] "r" (Mask)
250      ext_asm.add_input_operand ("aMask", "r", mask);
251
252.. function:: gccjit::extended_asm&\
253              gccjit::extended_asm::add_input_operand (const std::string &constraint,\
254                                                       gccjit::rvalue src)
255
256   As above, but don't supply a symbolic name for the operand.
257
258   .. code-block:: c++
259
260      // Example without a symbolic name, the equivalent of:
261      //   : "r" (src)
262      ext_asm.add_input_operand ("r", src);
263
264.. function:: gccjit::extended_asm&\
265              gccjit::extended_asm::add_clobber (const std::string &victim)
266
267   Add `victim` to the list of registers clobbered by the extended ``asm``
268   statement.  See the
269   `Clobbers and Scratch Registers <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#>`_
270   section of the documentation of the C syntax.
271
272   Statements with multiple clobbers will require multiple calls, one per
273   clobber.
274
275   For example:
276
277   .. code-block:: c++
278
279     ext_asm.add_clobber ("r0").add_clobber ("cc").add_clobber ("memory");
280
281
282Adding top-level assembler statements
283*************************************
284
285In addition to creating extended ``asm`` instructions within a function,
286there is support for creating "top-level" assembler statements, outside
287of any function.
288
289.. function:: void\
290              gccjit::context::add_top_level_asm (const char *asm_stmts,\
291                                                  gccjit::location loc = location ())
292
293   Create a set of top-level asm statements, analogous to those created
294   by GCC's "basic" ``asm`` syntax in C at file scope.
295
296   For example, to create the equivalent of:
297
298   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
299      :start-after: // Quote from here in docs/cp/topics/asm.rst: example 5: C
300      :end-before: // Quote up to here in docs/cp/topics/asm.rst: example 5: C
301      :language: c
302
303   the following API calls could be used:
304
305   .. literalinclude:: ../../../../testsuite/jit.dg/test-asm.cc
306      :start-after: /* Quote from here in docs/cp/topics/asm.rst: example 5: jit.  */
307      :end-before: /* Quote up to here in docs/cp/topics/asm.rst: example 5: jit.  */
308      :language: c
309