math: remove the get_implied_value_low_overhead() function
[smatch.git] / smatch_mtag_data.c
blob9f9a87f3a1253f645abe4d6cfbe18e41ecfb93b0
1 /*
2 * Copyright (C) 2016 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * What we're doing here is saving all the possible values for static variables.
20 * Later on we might do globals as well.
24 #include "smatch.h"
25 #include "smatch_slist.h"
26 #include "smatch_extra.h"
28 static int my_id;
29 static struct stree *vals;
31 static int save_rl(void *_rl, int argc, char **argv, char **azColName)
33 unsigned long *rl = _rl;
35 *rl = strtoul(argv[0], NULL, 10);
36 return 0;
39 static struct range_list *select_orig(mtag_t tag, int offset)
41 struct range_list *rl = NULL;
43 mem_sql(&save_rl, &rl, "select value from mtag_data where tag = %lld and offset = %d;",
44 tag, offset);
45 return rl;
48 static int is_kernel_param(const char *name)
50 struct sm_state *tmp;
51 char buf[256];
54 * I'm ignoring these because otherwise Smatch thinks that kernel
55 * parameters are always set to the default.
59 if (option_project != PROJ_KERNEL)
60 return 0;
62 snprintf(buf, sizeof(buf), "__param_%s.arg", name);
64 FOR_EACH_SM(vals, tmp) {
65 if (strcmp(tmp->name, buf) == 0)
66 return 1;
67 } END_FOR_EACH_SM(tmp);
69 return 0;
72 static void insert_mtag_data(mtag_t tag, int offset, struct range_list *rl)
74 rl = clone_rl_permanent(rl);
76 mem_sql(NULL, NULL, "delete from mtag_data where tag = %lld and offset = %d and type = %d",
77 tag, offset, DATA_VALUE);
78 mem_sql(NULL, NULL, "insert into mtag_data values (%lld, %d, %d, '%lu');",
79 tag, offset, DATA_VALUE, (unsigned long)rl);
82 void update_mtag_data(struct expression *expr)
84 struct range_list *orig, *new, *rl;
85 char *name;
86 mtag_t tag;
87 int offset;
89 name = expr_to_var(expr);
90 if (is_kernel_param(name)) {
91 free_string(name);
92 return;
94 free_string(name);
96 if (!expr_to_mtag_offset(expr, &tag, &offset))
97 return;
99 get_absolute_rl(expr, &rl);
101 orig = select_orig(tag, offset);
102 new = rl_union(orig, rl);
103 insert_mtag_data(tag, offset, new);
106 static void match_global_assign(struct expression *expr)
108 struct range_list *rl;
109 mtag_t tag;
110 int offset;
111 char *name;
113 name = expr_to_var(expr->left);
114 if (is_kernel_param(name)) {
115 free_string(name);
116 return;
118 free_string(name);
120 if (!expr_to_mtag_offset(expr->left, &tag, &offset))
121 return;
123 get_absolute_rl(expr->right, &rl);
124 insert_mtag_data(tag, offset, rl);
127 static int save_mtag_data(void *_unused, int argc, char **argv, char **azColName)
129 struct range_list *rl;
131 if (argc != 4) {
132 sm_msg("Error saving mtag data");
133 return 0;
135 if (!option_info)
136 return 0;
138 rl = (struct range_list *)strtoul(argv[3], NULL, 10);
139 sm_msg("SQL: insert into mtag_data values ('%s', '%s', '%s', '%s');",
140 argv[0], argv[1], argv[2], show_rl(rl));
142 return 0;
145 static void match_end_file(struct symbol_list *sym_list)
147 mem_sql(&save_mtag_data, NULL, "select * from mtag_data where type = %d;",
148 DATA_VALUE);
151 struct db_info {
152 struct symbol *type;
153 struct range_list *rl;
156 static int get_vals(void *_db_info, int argc, char **argv, char **azColName)
158 struct db_info *db_info = _db_info;
159 struct range_list *tmp;
161 str_to_rl(db_info->type, argv[0], &tmp);
162 if (db_info->rl)
163 db_info->rl = rl_union(db_info->rl, tmp);
164 else
165 db_info->rl = tmp;
167 return 0;
170 struct db_cache_results {
171 mtag_t tag;
172 struct range_list *rl;
174 static struct db_cache_results cached_results[8];
176 static int get_rl_from_mtag_offset(mtag_t tag, int offset, struct symbol *type, struct range_list **rl)
178 struct db_info db_info = {};
179 mtag_t merged = tag | offset;
180 static int idx;
181 int ret;
182 int i;
184 for (i = 0; i < ARRAY_SIZE(cached_results); i++) {
185 if (merged == cached_results[i].tag) {
186 if (cached_results[i].rl) {
187 *rl = cached_results[i].rl;
188 return 1;
190 return 0;
194 db_info.type = type;
196 run_sql(get_vals, &db_info,
197 "select value from mtag_data where tag = %lld and offset = %d and type = %d;",
198 tag, offset, DATA_VALUE);
199 if (!db_info.rl || is_whole_rl(db_info.rl)) {
200 db_info.rl = NULL;
201 ret = 0;
202 goto update_cache;
205 *rl = db_info.rl;
206 ret = 1;
208 update_cache:
209 cached_results[idx].tag = tag;
210 cached_results[idx].rl = db_info.rl;
211 idx = (idx + 1) % ARRAY_SIZE(cached_results);
213 return ret;
216 static void clear_cache(struct symbol *sym)
218 memset(cached_results, 0, sizeof(cached_results));
221 int get_mtag_rl(struct expression *expr, struct range_list **rl)
223 struct symbol *type;
224 mtag_t tag;
225 int offset;
227 if (!expr_to_mtag_offset(expr, &tag, &offset))
228 return 0;
229 if (offset >= MTAG_OFFSET_MASK)
230 return 0;
232 type = get_type(expr);
233 if (!type)
234 return 0;
236 return get_rl_from_mtag_offset(tag, offset, type, rl);
239 void register_mtag_data(int id)
241 my_id = id;
243 add_hook(&clear_cache, FUNC_DEF_HOOK);
245 // if (!option_info)
246 // return;
247 add_hook(&match_global_assign, GLOBAL_ASSIGNMENT_HOOK);
248 add_hook(&match_end_file, END_FILE_HOOK);