LCOV - code coverage report
Current view: top level - gcc - attr-callback.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 98.5 % 65 64
Test Date: 2026-08-22 16:33:35 Functions: 100.0 % 9 9
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Callback attribute handling
       2              :    Copyright (C) 2025-2026 Free Software Foundation, Inc.
       3              :    Contributed by Josef Melcr <jmelcr@gcc.gnu.org>
       4              : 
       5              :    This file is part of GCC.
       6              : 
       7              :    GCC is free software; you can redistribute it and/or modify
       8              :    under the terms of the GNU General Public License as published by
       9              :    the Free Software Foundation; either version 3 of the License, or
      10              :    (at your option) any later version.
      11              : 
      12              :    GCC is distributed in the hope that it will be useful,
      13              :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14              :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15              :    GNU General Public License for more details.
      16              : 
      17              :    You should have received a copy of the GNU General Public License
      18              :    along with GCC; see the file COPYING3.  If not see
      19              :    <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "backend.h"
      25              : #include "tree.h"
      26              : #include "gimple.h"
      27              : #include "alloc-pool.h"
      28              : #include "cgraph.h"
      29              : #include "diagnostic.h"
      30              : #include "builtins.h"
      31              : #include "options.h"
      32              : #include "gimple-range.h"
      33              : #include "attribs.h"
      34              : #include "symbol-summary.h"
      35              : #include "lto-streamer.h"
      36              : #include "attr-callback.h"
      37              : #include "callback-info.h"
      38              : 
      39              : /* Returns a callback attribute with callback index FN_IDX, and ARG_COUNT
      40              :    arguments specified by VA_ARGS.  */
      41              : tree
      42       388488 : callback_build_attr (unsigned fn_idx, unsigned arg_count...)
      43              : {
      44       388488 :   va_list args;
      45       388488 :   va_start (args, arg_count);
      46              : 
      47       388488 :   tree cblist = NULL_TREE;
      48       388488 :   tree *pp = &cblist;
      49       388488 :   unsigned i;
      50       776976 :   for (i = 0; i < arg_count; i++)
      51              :     {
      52       388488 :       int num = va_arg (args, int);
      53       388488 :       tree tnum = build_int_cst (integer_type_node, num);
      54       388488 :       *pp = build_tree_list (NULL, tnum);
      55       388488 :       pp = &TREE_CHAIN (*pp);
      56              :     }
      57       388488 :   cblist
      58       388488 :     = tree_cons (NULL_TREE, build_int_cst (integer_type_node, fn_idx), cblist);
      59       388488 :   tree attr
      60       388488 :     = tree_cons (get_identifier ("callback_only"), cblist, NULL_TREE);
      61       388488 :   return attr;
      62              : }
      63              : 
      64              : /* Returns TRUE if a function should be treated as if it had a callback
      65              :    attribute despite the DECL not having it.  STMT can be passed NULL
      66              :    if the call statement is not available at the time, for example WPA, but it
      67              :    should be called with the statement itself whenever possible.  */
      68              : bool
      69      2774983 : callback_is_special_cased (tree decl, gcall *stmt)
      70              : {
      71      2774983 :   if (fndecl_built_in_p (decl, BUILT_IN_GOMP_TASK))
      72              :     {
      73        18345 :       if (stmt)
      74        18345 :         return gimple_call_arg (stmt, 2) == null_pointer_node;
      75              :       return true;
      76              :     }
      77              :   return false;
      78              : }
      79              : 
      80              : /* Returns an attribute for a special cased function.  */
      81              : tree
      82         3540 : callback_special_case_attr (tree decl)
      83              : {
      84         3540 :   if (fndecl_built_in_p (decl, BUILT_IN_GOMP_TASK))
      85         3540 :     return callback_build_attr (1, 1, 2);
      86            0 :   gcc_unreachable ();
      87              : }
      88              : 
      89              : /* Returns TRUE if the callee of E has a callback attribute.  */
      90              : bool
      91      2641931 : callback_edge_callee_has_attr (cgraph_edge *e)
      92              : {
      93      2641931 :   return lookup_attribute ("callback_only",
      94      2641931 :                            DECL_ATTRIBUTES (e->callee->decl))
      95      2641931 :          || callback_is_special_cased (e->callee->decl, e->call_stmt);
      96              : }
      97              : 
      98              : /* Given an instance of callback attribute, return the 0-based
      99              :    index of the called function in question.  */
     100              : int
     101        28489 : callback_get_fn_index (tree cb_attr)
     102              : {
     103        28489 :   tree args = TREE_VALUE (cb_attr);
     104        28489 :   int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
     105        28489 :   return idx;
     106              : }
     107              : 
     108              : /* For a given callback pair, retrieves the callback attribute used
     109              :    to create E from the callee of CARRYING.  */
     110              : tree
     111        15127 : callback_fetch_attr_by_edge (cgraph_edge *e, cgraph_edge *carrying)
     112              : {
     113        15127 :   gcc_checking_assert (e->call_stmt == carrying->call_stmt
     114              :                        && e->lto_stmt_uid == carrying->lto_stmt_uid);
     115              : 
     116        15127 :   if (callback_is_special_cased (carrying->callee->decl, e->call_stmt))
     117         1770 :     return callback_special_case_attr (carrying->callee->decl);
     118              : 
     119        13357 :   tree cb_attr = lookup_attribute ("callback_only",
     120        13357 :                                    DECL_ATTRIBUTES (carrying->callee->decl));
     121        13357 :   gcc_checking_assert (cb_attr);
     122        13357 :   callback_info *ci = callback_info_sum->get (e);
     123        13357 :   tree res = NULL_TREE;
     124        13358 :   for (; cb_attr;
     125            1 :        cb_attr = lookup_attribute ("callback_only", TREE_CHAIN (cb_attr)))
     126              :     {
     127        13358 :       unsigned fn_idx = callback_get_fn_index (cb_attr);
     128        13358 :       if (fn_idx == ci->get_id ())
     129              :         {
     130              :           res = cb_attr;
     131              :           break;
     132              :         }
     133              :     }
     134        13357 :   gcc_checking_assert (res != NULL_TREE);
     135              :   return res;
     136              : }
     137              : 
     138              : /* Returns the argument mapping from the dispatching function to the callback
     139              :    function parsed from the attribute.  */
     140              : auto_vec<int>
     141        15127 : callback_get_arg_mapping_from_attr (tree attr)
     142              : {
     143        15127 :   tree args = TREE_VALUE (attr);
     144        15127 :   auto_vec<int> res;
     145        15127 :   tree it;
     146              : 
     147              :   /* Skip over the first argument, which denotes
     148              :      which argument is the called function.  */
     149        30255 :   for (it = TREE_CHAIN (args); it != NULL_TREE; it = TREE_CHAIN (it))
     150              :     {
     151        15128 :       int idx = TREE_INT_CST_LOW (TREE_VALUE (it));
     152              :       /* Subtract 1 to account for 1-based indexing.  If the value is unknown,
     153              :          use ARG_MAPPING_UNKNOWN_IDX instead.  */
     154        15128 :       idx = idx == CB_UNKNOWN_POS ? ARG_MAPPING_UNKNOWN_IDX : idx - 1;
     155        15128 :       res.safe_push (idx);
     156              :     }
     157              : 
     158        15127 :   return res;
     159              : }
     160              : 
     161              : /* Returns TRUE if E is considered useful in the callgraph, FALSE otherwise.  If
     162              :    this predicate returns FALSE, then E wasn't used to optimize its callee and
     163              :    can be safely removed from the callgraph.  */
     164              : bool
     165        13672 : callback_edge_useful_p (cgraph_edge *e)
     166              : {
     167        13672 :   gcc_checking_assert (e->callback);
     168        13672 :   callback_info *ci = callback_info_sum->get (e);
     169        13672 :   return ci->redirected;
     170              : }
     171              : 
     172              : /* Returns the number of arguments the callback function described by ATTR
     173              :    takes.  */
     174              : 
     175              : size_t
     176        15127 : callback_num_args (tree attr)
     177              : {
     178        15127 :   tree args = TREE_VALUE (attr);
     179        15127 :   size_t res = 0;
     180        15127 :   tree it;
     181              : 
     182        30255 :   for (it = TREE_CHAIN (args); it != NULL_TREE; it = TREE_CHAIN (it), ++res)
     183              :     ;
     184        15127 :   return res;
     185              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.