Home | History | Annotate | Line # | Download | only in topics
      1 .. Copyright (C) 2014-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 Expressions
     21 ===========
     22 
     23 Rvalues
     24 -------
     25 .. class:: gccjit::rvalue
     26 
     27 A :class:`gccjit::rvalue` is an expression that can be computed.  It is a
     28 subclass of :class:`gccjit::object`, and is a thin wrapper around
     29 :c:type:`gcc_jit_rvalue *` from the C API.
     30 
     31 It can be simple, e.g.:
     32 
     33   * an integer value e.g. `0` or `42`
     34   * a string literal e.g. `"Hello world"`
     35   * a variable e.g. `i`.  These are also lvalues (see below).
     36 
     37 or compound e.g.:
     38 
     39   * a unary expression e.g. `!cond`
     40   * a binary expression e.g. `(a + b)`
     41   * a function call e.g. `get_distance (&player_ship, &target)`
     42   * etc.
     43 
     44 Every rvalue has an associated type, and the API will check to ensure
     45 that types match up correctly (otherwise the context will emit an error).
     46 
     47 .. function:: gccjit::type gccjit::rvalue::get_type ()
     48 
     49   Get the type of this rvalue.
     50 
     51 
     52 Simple expressions
     53 ******************
     54 
     55 .. function:: gccjit::rvalue \
     56               gccjit::context::new_rvalue (gccjit::type numeric_type, \
     57                                            int value) const
     58 
     59    Given a numeric type (integer or floating point), build an rvalue for
     60    the given constant :c:type:`int` value.
     61 
     62 .. function:: gccjit::rvalue \
     63               gccjit::context::new_rvalue (gccjit::type numeric_type, \
     64                                            long value) const
     65 
     66    Given a numeric type (integer or floating point), build an rvalue for
     67    the given constant :c:type:`long` value.
     68 
     69 .. function::  gccjit::rvalue \
     70                gccjit::context::zero (gccjit::type numeric_type) const
     71 
     72    Given a numeric type (integer or floating point), get the rvalue for
     73    zero.  Essentially this is just a shortcut for:
     74 
     75    .. code-block:: c++
     76 
     77       ctxt.new_rvalue (numeric_type, 0)
     78 
     79 .. function::  gccjit::rvalue \
     80                gccjit::context::one (gccjit::type numeric_type) const
     81 
     82    Given a numeric type (integer or floating point), get the rvalue for
     83    one.  Essentially this is just a shortcut for:
     84 
     85    .. code-block:: c++
     86 
     87       ctxt.new_rvalue (numeric_type, 1)
     88 
     89 .. function::  gccjit::rvalue \
     90                gccjit::context::new_rvalue (gccjit::type numeric_type, \
     91                                             double value) const
     92 
     93    Given a numeric type (integer or floating point), build an rvalue for
     94    the given constant :c:type:`double` value.
     95 
     96 .. function:: gccjit::rvalue \
     97               gccjit::context::new_rvalue (gccjit::type pointer_type, \
     98                                            void *value) const
     99 
    100    Given a pointer type, build an rvalue for the given address.
    101 
    102 .. function:: gccjit::rvalue \
    103               gccjit::context::new_rvalue (const std::string &value) const
    104 
    105    Generate an rvalue of type :c:data:`GCC_JIT_TYPE_CONST_CHAR_PTR` for
    106    the given string.  This is akin to a string literal.
    107 
    108 Vector expressions
    109 ******************
    110 
    111 .. function:: gccjit::rvalue \
    112 	      gccjit::context::new_rvalue (gccjit::type vector_type, \
    113 	                                   std::vector<gccjit::rvalue> elements) const
    114 
    115    Given a vector type, and a vector of scalar rvalue elements, generate a
    116    vector rvalue.
    117 
    118    The number of elements needs to match that of the vector type.
    119 
    120 Unary Operations
    121 ****************
    122 
    123 .. function:: gccjit::rvalue  \
    124               gccjit::context::new_unary_op (enum gcc_jit_unary_op, \
    125                                              gccjit::type result_type, \
    126                                              gccjit::rvalue rvalue, \
    127                                              gccjit::location loc)
    128 
    129    Build a unary operation out of an input rvalue.
    130 
    131    Parameter ``loc`` is optional.
    132 
    133    This is a thin wrapper around the C API's
    134    :c:func:`gcc_jit_context_new_unary_op` and the available unary
    135    operations are documented there.
    136 
    137 There are shorter ways to spell the various specific kinds of unary
    138 operation:
    139 
    140 .. function:: gccjit::rvalue \
    141               gccjit::context::new_minus (gccjit::type result_type, \
    142                                           gccjit::rvalue a, \
    143                                           gccjit::location loc)
    144 
    145    Negate an arithmetic value; for example:
    146 
    147    .. code-block:: c++
    148 
    149       gccjit::rvalue negpi = ctxt.new_minus (t_double, pi);
    150 
    151    builds the equivalent of this C expression:
    152 
    153    .. code-block:: c
    154 
    155       -pi
    156 
    157 .. function:: gccjit::rvalue \
    158               new_bitwise_negate (gccjit::type result_type, \
    159                                   gccjit::rvalue a, \
    160                                   gccjit::location loc)
    161 
    162    Bitwise negation of an integer value (one's complement); for example:
    163 
    164    .. code-block:: c++
    165 
    166       gccjit::rvalue mask = ctxt.new_bitwise_negate (t_int, a);
    167 
    168    builds the equivalent of this C expression:
    169 
    170    .. code-block:: c
    171 
    172       ~a
    173 
    174 .. function:: gccjit::rvalue \
    175               new_logical_negate (gccjit::type result_type, \
    176                                   gccjit::rvalue a, \
    177                                   gccjit::location loc)
    178 
    179    Logical negation of an arithmetic or pointer value; for example:
    180 
    181    .. code-block:: c++
    182 
    183       gccjit::rvalue guard = ctxt.new_logical_negate (t_bool, cond);
    184 
    185    builds the equivalent of this C expression:
    186 
    187    .. code-block:: c
    188 
    189       !cond
    190 
    191 
    192 The most concise way to spell them is with overloaded operators:
    193 
    194 .. function:: gccjit::rvalue operator- (gccjit::rvalue a)
    195 
    196    .. code-block:: c++
    197 
    198      gccjit::rvalue negpi = -pi;
    199 
    200 
    201 .. function:: gccjit::rvalue operator~ (gccjit::rvalue a)
    202 
    203    .. code-block:: c++
    204 
    205       gccjit::rvalue mask = ~a;
    206 
    207 .. function:: gccjit::rvalue operator! (gccjit::rvalue a)
    208 
    209    .. code-block:: c++
    210 
    211       gccjit::rvalue guard = !cond;
    212 
    213 
    214 Binary Operations
    215 *****************
    216 
    217 .. function:: gccjit::rvalue\
    218               gccjit::context::new_binary_op (enum gcc_jit_binary_op, \
    219                                               gccjit::type result_type, \
    220                                               gccjit::rvalue a, \
    221                                               gccjit::rvalue b, \
    222                                               gccjit::location loc)
    223 
    224    Build a binary operation out of two constituent rvalues.
    225 
    226    Parameter ``loc`` is optional.
    227 
    228    This is a thin wrapper around the C API's
    229    :c:func:`gcc_jit_context_new_binary_op` and the available binary
    230    operations are documented there.
    231 
    232 There are shorter ways to spell the various specific kinds of binary
    233 operation:
    234 
    235 .. function:: gccjit::rvalue \
    236               gccjit::context::new_plus (gccjit::type result_type, \
    237                                          gccjit::rvalue a, gccjit::rvalue b, \
    238                                          gccjit::location loc)
    239 
    240 .. function:: gccjit::rvalue \
    241               gccjit::context::new_minus (gccjit::type result_type, \
    242                                           gccjit::rvalue a, gccjit::rvalue b, \
    243                                           gccjit::location loc)
    244 
    245 .. function:: gccjit::rvalue \
    246               gccjit::context::new_mult (gccjit::type result_type, \
    247                                          gccjit::rvalue a, gccjit::rvalue b, \
    248                                          gccjit::location loc)
    249 
    250 .. function:: gccjit::rvalue \
    251               gccjit::context::new_divide (gccjit::type result_type, \
    252                                            gccjit::rvalue a, gccjit::rvalue b, \
    253                                            gccjit::location loc)
    254 
    255 .. function:: gccjit::rvalue \
    256               gccjit::context::new_modulo (gccjit::type result_type, \
    257                                            gccjit::rvalue a, gccjit::rvalue b, \
    258                                            gccjit::location loc)
    259 
    260 .. function:: gccjit::rvalue \
    261               gccjit::context::new_bitwise_and (gccjit::type result_type, \
    262                                                 gccjit::rvalue a, gccjit::rvalue b, \
    263                                                 gccjit::location loc)
    264 
    265 .. function:: gccjit::rvalue \
    266               gccjit::context::new_bitwise_xor (gccjit::type result_type, \
    267                                                 gccjit::rvalue a, gccjit::rvalue b, \
    268                                                 gccjit::location loc)
    269 
    270 .. function:: gccjit::rvalue \
    271               gccjit::context::new_bitwise_or (gccjit::type result_type, \
    272                                                gccjit::rvalue a, gccjit::rvalue b, \
    273                                                gccjit::location loc)
    274 
    275 .. function:: gccjit::rvalue \
    276               gccjit::context::new_logical_and (gccjit::type result_type, \
    277                                                 gccjit::rvalue a, gccjit::rvalue b, \
    278                                                 gccjit::location loc)
    279 
    280 .. function:: gccjit::rvalue \
    281               gccjit::context::new_logical_or (gccjit::type result_type, \
    282                                                gccjit::rvalue a, gccjit::rvalue b, \
    283                                                gccjit::location loc)
    284 
    285 The most concise way to spell them is with overloaded operators:
    286 
    287 .. function:: gccjit::rvalue operator+ (gccjit::rvalue a, gccjit::rvalue b)
    288 
    289    .. code-block:: c++
    290 
    291       gccjit::rvalue sum = a + b;
    292 
    293 .. function:: gccjit::rvalue operator- (gccjit::rvalue a, gccjit::rvalue b)
    294 
    295    .. code-block:: c++
    296 
    297       gccjit::rvalue diff = a - b;
    298 
    299 .. function:: gccjit::rvalue operator* (gccjit::rvalue a, gccjit::rvalue b)
    300 
    301    .. code-block:: c++
    302 
    303       gccjit::rvalue prod = a * b;
    304 
    305 .. function:: gccjit::rvalue operator/ (gccjit::rvalue a, gccjit::rvalue b)
    306 
    307    .. code-block:: c++
    308 
    309       gccjit::rvalue result = a / b;
    310 
    311 .. function:: gccjit::rvalue operator% (gccjit::rvalue a, gccjit::rvalue b)
    312 
    313    .. code-block:: c++
    314 
    315       gccjit::rvalue mod = a % b;
    316 
    317 .. function:: gccjit::rvalue operator& (gccjit::rvalue a, gccjit::rvalue b)
    318 
    319    .. code-block:: c++
    320 
    321       gccjit::rvalue x = a & b;
    322 
    323 .. function:: gccjit::rvalue operator^ (gccjit::rvalue a, gccjit::rvalue b)
    324 
    325    .. code-block:: c++
    326 
    327       gccjit::rvalue x = a ^ b;
    328 
    329 .. function:: gccjit::rvalue operator| (gccjit::rvalue a, gccjit::rvalue b)
    330 
    331    .. code-block:: c++
    332 
    333       gccjit::rvalue x = a | b;
    334 
    335 .. function:: gccjit::rvalue operator&& (gccjit::rvalue a, gccjit::rvalue b)
    336 
    337    .. code-block:: c++
    338 
    339       gccjit::rvalue cond = a && b;
    340 
    341 .. function:: gccjit::rvalue operator|| (gccjit::rvalue a, gccjit::rvalue b)
    342 
    343    .. code-block:: c++
    344 
    345       gccjit::rvalue cond = a || b;
    346 
    347 These can of course be combined, giving a terse way to build compound
    348 expressions:
    349 
    350    .. code-block:: c++
    351 
    352       gccjit::rvalue discriminant = (b * b) - (four * a * c);
    353 
    354 
    355 Comparisons
    356 ***********
    357 
    358 .. function:: gccjit::rvalue \
    359               gccjit::context::new_comparison (enum gcc_jit_comparison,\
    360                                                gccjit::rvalue a, \
    361                                                gccjit::rvalue b, \
    362                                                gccjit::location loc)
    363 
    364    Build a boolean rvalue out of the comparison of two other rvalues.
    365 
    366    Parameter ``loc`` is optional.
    367 
    368    This is a thin wrapper around the C API's
    369    :c:func:`gcc_jit_context_new_comparison` and the available kinds
    370    of comparison are documented there.
    371 
    372 There are shorter ways to spell the various specific kinds of binary
    373 operation:
    374 
    375 .. function:: gccjit::rvalue \
    376               gccjit::context::new_eq (gccjit::rvalue a, gccjit::rvalue b, \
    377                                        gccjit::location loc)
    378 
    379 .. function:: gccjit::rvalue \
    380               gccjit::context::new_ne (gccjit::rvalue a, gccjit::rvalue b, \
    381                                        gccjit::location loc)
    382 
    383 .. function:: gccjit::rvalue \
    384               gccjit::context::new_lt (gccjit::rvalue a, gccjit::rvalue b, \
    385                                        gccjit::location loc)
    386 
    387 .. function:: gccjit::rvalue \
    388               gccjit::context::new_le (gccjit::rvalue a, gccjit::rvalue b, \
    389                                        gccjit::location loc)
    390 
    391 .. function:: gccjit::rvalue \
    392               gccjit::context::new_gt (gccjit::rvalue a, gccjit::rvalue b, \
    393                                        gccjit::location loc)
    394 
    395 .. function:: gccjit::rvalue \
    396               gccjit::context::new_ge (gccjit::rvalue a, gccjit::rvalue b, \
    397                                        gccjit::location loc)
    398 
    399 The most concise way to spell them is with overloaded operators:
    400 
    401 .. function:: gccjit::rvalue \
    402               operator== (gccjit::rvalue a, gccjit::rvalue b)
    403 
    404    .. code-block:: c++
    405 
    406       gccjit::rvalue cond = (a == ctxt.zero (t_int));
    407 
    408 .. function:: gccjit::rvalue \
    409               operator!= (gccjit::rvalue a, gccjit::rvalue b)
    410 
    411    .. code-block:: c++
    412 
    413       gccjit::rvalue cond = (i != j);
    414 
    415 .. function:: gccjit::rvalue \
    416               operator< (gccjit::rvalue a, gccjit::rvalue b)
    417 
    418    .. code-block:: c++
    419 
    420       gccjit::rvalue cond = i < n;
    421 
    422 .. function:: gccjit::rvalue \
    423               operator<= (gccjit::rvalue a, gccjit::rvalue b)
    424 
    425    .. code-block:: c++
    426 
    427       gccjit::rvalue cond = i <= n;
    428 
    429 .. function:: gccjit::rvalue \
    430               operator> (gccjit::rvalue a, gccjit::rvalue b)
    431 
    432    .. code-block:: c++
    433 
    434       gccjit::rvalue cond = (ch > limit);
    435 
    436 .. function:: gccjit::rvalue \
    437               operator>= (gccjit::rvalue a, gccjit::rvalue b)
    438 
    439    .. code-block:: c++
    440 
    441       gccjit::rvalue cond = (score >= ctxt.new_rvalue (t_int, 100));
    442 
    443 .. TODO: beyond this point
    444 
    445 Function calls
    446 **************
    447 .. function:: gcc_jit_rvalue *\
    448               gcc_jit_context_new_call (gcc_jit_context *ctxt,\
    449                                         gcc_jit_location *loc,\
    450                                         gcc_jit_function *func,\
    451                                         int numargs , gcc_jit_rvalue **args)
    452 
    453    Given a function and the given table of argument rvalues, construct a
    454    call to the function, with the result as an rvalue.
    455 
    456    .. note::
    457 
    458       :func:`gccjit::context::new_call` merely builds a
    459       :class:`gccjit::rvalue` i.e. an expression that can be evaluated,
    460       perhaps as part of a more complicated expression.
    461       The call *won't* happen unless you add a statement to a function
    462       that evaluates the expression.
    463 
    464       For example, if you want to call a function and discard the result
    465       (or to call a function with ``void`` return type), use
    466       :func:`gccjit::block::add_eval`:
    467 
    468       .. code-block:: c++
    469 
    470          /* Add "(void)printf (arg0, arg1);".  */
    471          block.add_eval (ctxt.new_call (printf_func, arg0, arg1));
    472 
    473 Function pointers
    474 *****************
    475 
    476 .. function:: gccjit::rvalue \
    477 	      gccjit::function::get_address (gccjit::location loc)
    478 
    479    Get the address of a function as an rvalue, of function pointer
    480    type.
    481 
    482 Type-coercion
    483 *************
    484 
    485 .. function:: gccjit::rvalue \
    486               gccjit::context::new_cast (gccjit::rvalue rvalue,\
    487                                          gccjit::type type, \
    488                                          gccjit::location loc)
    489 
    490    Given an rvalue of T, construct another rvalue of another type.
    491 
    492    Currently only a limited set of conversions are possible:
    493 
    494      * int <-> float
    495      * int <-> bool
    496      * P*  <-> Q*, for pointer types P and Q
    497 
    498 Lvalues
    499 -------
    500 
    501 .. class:: gccjit::lvalue
    502 
    503 An lvalue is something that can of the *left*-hand side of an assignment:
    504 a storage area (such as a variable).  It is a subclass of
    505 :class:`gccjit::rvalue`, where the rvalue is computed by reading from the
    506 storage area.
    507 
    508 It iss a thin wrapper around :c:type:`gcc_jit_lvalue *` from the C API.
    509 
    510 .. function:: gccjit::rvalue \
    511               gccjit::lvalue::get_address (gccjit::location loc)
    512 
    513    Take the address of an lvalue; analogous to:
    514 
    515    .. code-block:: c
    516 
    517      &(EXPR)
    518 
    519    in C.
    520 
    521    Parameter "loc" is optional.
    522 
    523 Global variables
    524 ****************
    525 
    526 .. function:: gccjit::lvalue \
    527               gccjit::context::new_global (enum gcc_jit_global_kind,\
    528                                            gccjit::type type, \
    529                                            const char *name, \
    530                                            gccjit::location loc)
    531 
    532    Add a new global variable of the given type and name to the context.
    533 
    534    This is a thin wrapper around :c:func:`gcc_jit_context_new_global` from
    535    the C API; the "kind" parameter has the same meaning as there.
    536 
    537 Working with pointers, structs and unions
    538 -----------------------------------------
    539 
    540 .. function:: gccjit::lvalue \
    541               gccjit::rvalue::dereference (gccjit::location loc)
    542 
    543    Given an rvalue of pointer type ``T *``, dereferencing the pointer,
    544    getting an lvalue of type ``T``.  Analogous to:
    545 
    546    .. code-block:: c++
    547 
    548      *(EXPR)
    549 
    550    in C.
    551 
    552    Parameter "loc" is optional.
    553 
    554 If you don't need to specify the location, this can also be expressed using
    555 an overloaded operator:
    556 
    557 .. function:: gccjit::lvalue \
    558               gccjit::rvalue::operator* ()
    559 
    560    .. code-block:: c++
    561 
    562       gccjit::lvalue content = *ptr;
    563 
    564 Field access is provided separately for both lvalues and rvalues:
    565 
    566 .. function:: gccjit::lvalue \
    567               gccjit::lvalue::access_field (gccjit::field field, \
    568                                             gccjit::location loc)
    569 
    570    Given an lvalue of struct or union type, access the given field,
    571    getting an lvalue of the field's type.  Analogous to:
    572 
    573    .. code-block:: c++
    574 
    575       (EXPR).field = ...;
    576 
    577    in C.
    578 
    579 .. function:: gccjit::rvalue \
    580               gccjit::rvalue::access_field (gccjit::field field, \
    581                                             gccjit::location loc)
    582 
    583    Given an rvalue of struct or union type, access the given field
    584    as an rvalue.  Analogous to:
    585 
    586    .. code-block:: c++
    587 
    588       (EXPR).field
    589 
    590    in C.
    591 
    592 .. function:: gccjit::lvalue \
    593               gccjit::rvalue::dereference_field (gccjit::field field, \
    594                                                  gccjit::location loc)
    595 
    596    Given an rvalue of pointer type ``T *`` where T is of struct or union
    597    type, access the given field as an lvalue.  Analogous to:
    598 
    599    .. code-block:: c++
    600 
    601       (EXPR)->field
    602 
    603    in C, itself equivalent to ``(*EXPR).FIELD``.
    604 
    605 .. function:: gccjit::lvalue \
    606               gccjit::context::new_array_access (gccjit::rvalue ptr, \
    607                                                  gccjit::rvalue index, \
    608                                                  gccjit::location loc)
    609 
    610    Given an rvalue of pointer type ``T *``, get at the element `T` at
    611    the given index, using standard C array indexing rules i.e. each
    612    increment of ``index`` corresponds to ``sizeof(T)`` bytes.
    613    Analogous to:
    614 
    615    .. code-block:: c++
    616 
    617       PTR[INDEX]
    618 
    619    in C (or, indeed, to ``PTR + INDEX``).
    620 
    621    Parameter "loc" is optional.
    622 
    623 For array accesses where you don't need to specify a :class:`gccjit::location`,
    624 two overloaded operators are available:
    625 
    626     gccjit::lvalue gccjit::rvalue::operator[] (gccjit::rvalue index)
    627 
    628     .. code-block:: c++
    629 
    630        gccjit::lvalue element = array[idx];
    631 
    632     gccjit::lvalue gccjit::rvalue::operator[] (int index)
    633 
    634     .. code-block:: c++
    635 
    636        gccjit::lvalue element = array[0];
    637