]>
Commit | Line | Data |
---|---|---|
07e30160 | 1 | /* Support for plugin-supplied behaviors of known functions. |
83ffe9cd | 2 | Copyright (C) 2022-2023 Free Software Foundation, Inc. |
07e30160 DM |
3 | Contributed by David Malcolm <dmalcolm@redhat.com>. |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it | |
8 | under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but | |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | 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" | |
accece8c | 22 | #define INCLUDE_MEMORY |
07e30160 DM |
23 | #include "system.h" |
24 | #include "coretypes.h" | |
25 | #include "tree.h" | |
07e30160 DM |
26 | #include "analyzer/analyzer.h" |
27 | #include "diagnostic-core.h" | |
28 | #include "analyzer/analyzer-logging.h" | |
29 | #include "stringpool.h" | |
6bd31b33 DM |
30 | #include "basic-block.h" |
31 | #include "gimple.h" | |
07e30160 | 32 | #include "analyzer/known-function-manager.h" |
6bd31b33 | 33 | #include "analyzer/region-model.h" |
861c917a | 34 | #include "analyzer/call-details.h" |
07e30160 DM |
35 | |
36 | #if ENABLE_ANALYZER | |
37 | ||
38 | namespace ana { | |
39 | ||
40 | /* class known_function_manager : public log_user. */ | |
41 | ||
42 | known_function_manager::known_function_manager (logger *logger) | |
43 | : log_user (logger) | |
44 | { | |
6bd31b33 | 45 | memset (m_combined_fns_arr, 0, sizeof (m_combined_fns_arr)); |
07e30160 DM |
46 | } |
47 | ||
48 | known_function_manager::~known_function_manager () | |
49 | { | |
50 | /* Delete all owned kfs. */ | |
51 | for (auto iter : m_map_id_to_kf) | |
52 | delete iter.second; | |
6bd31b33 DM |
53 | for (auto iter : m_combined_fns_arr) |
54 | delete iter; | |
07e30160 DM |
55 | } |
56 | ||
57 | void | |
76dd2c4f DM |
58 | known_function_manager::add (const char *name, |
59 | std::unique_ptr<known_function> kf) | |
07e30160 DM |
60 | { |
61 | LOG_FUNC_1 (get_logger (), "registering %s", name); | |
62 | tree id = get_identifier (name); | |
76dd2c4f | 63 | m_map_id_to_kf.put (id, kf.release ()); |
07e30160 DM |
64 | } |
65 | ||
6bd31b33 DM |
66 | void |
67 | known_function_manager::add (enum built_in_function name, | |
68 | std::unique_ptr<known_function> kf) | |
07e30160 | 69 | { |
6bd31b33 DM |
70 | gcc_assert (name < END_BUILTINS); |
71 | delete m_combined_fns_arr[name]; | |
72 | m_combined_fns_arr[name] = kf.release (); | |
07e30160 DM |
73 | } |
74 | ||
6bd31b33 DM |
75 | void |
76 | known_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 | ||
07e30160 | 92 | const known_function * |
6bd31b33 | 93 | known_function_manager::get_match (tree fndecl, const call_details &cd) const |
07e30160 | 94 | { |
ec7c796d | 95 | /* Look for a matching built-in. */ |
6bd31b33 DM |
96 | if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) |
97 | { | |
98 | if (const known_function *candidate | |
99 | = get_normal_builtin (DECL_FUNCTION_CODE (fndecl))) | |
100 | if (gimple_builtin_call_types_compatible_p (cd.get_call_stmt (), | |
101 | fndecl)) | |
102 | return candidate; | |
103 | } | |
ec7c796d DM |
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; | |
07e30160 | 111 | if (tree identifier = DECL_NAME (fndecl)) |
ec7c796d DM |
112 | if (const known_function *candidate = get_by_identifier (identifier)) |
113 | if (candidate->matches_call_types_p (cd)) | |
114 | return candidate; | |
115 | ||
07e30160 DM |
116 | return NULL; |
117 | } | |
118 | ||
6bd31b33 DM |
119 | /* Get any known_function for IFN, or NULL. */ |
120 | ||
121 | const known_function * | |
122 | known_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 | ||
131 | const known_function * | |
132 | known_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 | ||
140 | /* Get any known_function matching IDENTIFIER, without type-checking. | |
141 | Return NULL if there isn't one. */ | |
142 | ||
143 | const known_function * | |
144 | known_function_manager::get_by_identifier (tree identifier) const | |
145 | { | |
146 | known_function_manager *mut_this = const_cast<known_function_manager *>(this); | |
147 | known_function **slot = mut_this->m_map_id_to_kf.get (identifier); | |
148 | if (slot) | |
149 | return *slot; | |
150 | else | |
151 | return NULL; | |
152 | } | |
153 | ||
07e30160 DM |
154 | } // namespace ana |
155 | ||
156 | #endif /* #if ENABLE_ANALYZER */ |