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