1/* Support for plugin-supplied behaviors of known functions.
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#define INCLUDE_MEMORY
23#include "system.h"
24#include "coretypes.h"
25#include "tree.h"
26#include "analyzer/analyzer.h"
27#include "diagnostic-core.h"
28#include "analyzer/analyzer-logging.h"
29#include "stringpool.h"
30#include "basic-block.h"
31#include "gimple.h"
32#include "analyzer/known-function-manager.h"
33#include "analyzer/region-model.h"
34#include "analyzer/call-details.h"
35
36#if ENABLE_ANALYZER
37
38namespace ana {
39
40/* class known_function_manager : public log_user. */
41
42known_function_manager::known_function_manager (logger *logger)
43: log_user (logger)
44{
45 memset (s: m_combined_fns_arr, c: 0, n: sizeof (m_combined_fns_arr));
46}
47
48known_function_manager::~known_function_manager ()
49{
50 /* Delete all owned kfs. */
51 for (auto iter : m_map_id_to_kf)
52 delete iter.second;
53 for (auto iter : m_combined_fns_arr)
54 delete iter;
55}
56
57void
58known_function_manager::add (const char *name,
59 std::unique_ptr<known_function> kf)
60{
61 LOG_FUNC_1 (get_logger (), "registering %s", name);
62 tree id = get_identifier (name);
63 m_map_id_to_kf.put (k: id, v: kf.release ());
64}
65
66void
67known_function_manager::add (enum built_in_function name,
68 std::unique_ptr<known_function> kf)
69{
70 gcc_assert (name < END_BUILTINS);
71 delete m_combined_fns_arr[name];
72 m_combined_fns_arr[name] = kf.release ();
73}
74
75void
76known_function_manager::add (enum internal_fn ifn,
77 std::unique_ptr<known_function> kf)
78{
79 gcc_assert (ifn < IFN_LAST);
80 delete m_combined_fns_arr[ifn + END_BUILTINS];
81 m_combined_fns_arr[ifn + END_BUILTINS] = kf.release ();
82}
83
84/* Get any known_function for FNDECL for call CD.
85
86 The call must match all assumptions made by the known_function (such as
87 e.g. "argument 1's type must be a pointer type").
88
89 Return NULL if no known_function is found, or it does not match the
90 assumption(s). */
91
92const known_function *
93known_function_manager::get_match (tree fndecl, const call_details &cd) const
94{
95 /* Look for a matching built-in. */
96 if (fndecl_built_in_p (node: fndecl, klass: BUILT_IN_NORMAL))
97 {
98 if (const known_function *candidate
99 = get_normal_builtin (name: DECL_FUNCTION_CODE (decl: fndecl)))
100 if (gimple_builtin_call_types_compatible_p (cd.get_call_stmt (),
101 fndecl))
102 return candidate;
103 }
104
105 /* Look for a match by name. */
106
107 /* Reject fndecls that aren't in the root namespace. */
108 if (DECL_CONTEXT (fndecl)
109 && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
110 return NULL;
111 if (tree identifier = DECL_NAME (fndecl))
112 if (const known_function *candidate = get_by_identifier (identifier))
113 if (candidate->matches_call_types_p (cd))
114 return candidate;
115
116 return NULL;
117}
118
119/* Get any known_function for IFN, or NULL. */
120
121const known_function *
122known_function_manager::get_internal_fn (enum internal_fn ifn) const
123{
124 gcc_assert (ifn < IFN_LAST);
125 return m_combined_fns_arr[ifn + END_BUILTINS];
126}
127
128/* Get any known_function for NAME, without type-checking.
129 Return NULL if there isn't one. */
130
131const known_function *
132known_function_manager::get_normal_builtin (enum built_in_function name) const
133{
134 /* The numbers for built-in functions in enum combined_fn are the same as
135 for the built_in_function enum. */
136 gcc_assert (name < END_BUILTINS);
137 return m_combined_fns_arr[name];
138}
139
140const known_function *
141known_function_manager::
142get_normal_builtin (const builtin_known_function *builtin_kf) const
143{
144 return get_normal_builtin (name: builtin_kf->builtin_code ());
145}
146
147/* Get any known_function matching IDENTIFIER, without type-checking.
148 Return NULL if there isn't one. */
149
150const known_function *
151known_function_manager::get_by_identifier (tree identifier) const
152{
153 known_function_manager *mut_this = const_cast<known_function_manager *>(this);
154 known_function **slot = mut_this->m_map_id_to_kf.get (k: identifier);
155 if (slot)
156 return *slot;
157 else
158 return NULL;
159}
160
161} // namespace ana
162
163#endif /* #if ENABLE_ANALYZER */
164

source code of gcc/analyzer/known-function-manager.cc