Home | History | Annotate | Line # | Download | only in topics
      1 .. Copyright (C) 2020-2022 Free Software Foundation, Inc.
      2    Originally contributed by David Malcolm <dmalcolm (a] 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 
     20 Using Assembly Language with libgccjit++
     21 ========================================
     22 
     23 libgccjit has some support for directly embedding assembler instructions.
     24 This is based on GCC's support for inline ``asm`` in C code, and the
     25 following 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>`_
     27 in GCC's documentation, the "Extended Asm" section in particular.
     28 
     29 These entrypoints were added in :ref:`LIBGCCJIT_ABI_15`; you can test
     30 for their presence using
     31 
     32    .. code-block:: c
     33 
     34       #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS
     35 
     36 Adding 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 
    282 Adding top-level assembler statements
    283 *************************************
    284 
    285 In addition to creating extended ``asm`` instructions within a function,
    286 there is support for creating "top-level" assembler statements, outside
    287 of 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